Merge changes from topic "revert-3088867-QEHDREAABY" into main

* changes:
  Revert "Install jni symlinks in Soong"
  Revert "APK-in-APEX should set use_embedded_native_libs: true"
  Revert "Add make java.dependencyTag installable or not"
  Revert "Refactor how jni_libs dependencies are added"
This commit is contained in:
Yu Shan 2024-05-17 22:55:51 +00:00 committed by Gerrit Code Review
commit 4978080b1d
5 changed files with 187 additions and 74 deletions

View file

@ -5922,7 +5922,6 @@ func TestApexWithApps(t *testing.T) {
srcs: ["foo/bar/MyClass.java"], srcs: ["foo/bar/MyClass.java"],
sdk_version: "current", sdk_version: "current",
system_modules: "none", system_modules: "none",
use_embedded_native_libs: true,
jni_libs: ["libjni"], jni_libs: ["libjni"],
stl: "none", stl: "none",
apex_available: [ "myapex" ], apex_available: [ "myapex" ],

View file

@ -17,6 +17,7 @@ package java
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"android/soong/android" "android/soong/android"
@ -412,6 +413,23 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if app.embeddedJniLibs { if app.embeddedJniLibs {
jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String()) jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String()) entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
} else {
for _, jniLib := range app.jniLibs {
entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
var partitionTag string
// Mimic the creation of partition_tag in build/make,
// which defaults to an empty string when the partition is system.
// Otherwise, capitalize with a leading _
if jniLib.partition == "system" {
partitionTag = ""
} else {
split := strings.Split(jniLib.partition, "/")
partitionTag = "_" + strings.ToUpper(split[len(split)-1])
}
entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(),
jniLib.name+":"+partitionTag)
}
} }
if len(app.jniCoverageOutputs) > 0 { if len(app.jniCoverageOutputs) > 0 {

View file

@ -19,6 +19,9 @@ import (
"testing" "testing"
"android/soong/android" "android/soong/android"
"android/soong/cc"
"github.com/google/blueprint/proptools"
) )
func TestRequired(t *testing.T) { func TestRequired(t *testing.T) {
@ -252,3 +255,149 @@ func TestGetOverriddenPackages(t *testing.T) {
android.AssertDeepEquals(t, "overrides property", expected.overrides, actual) android.AssertDeepEquals(t, "overrides property", expected.overrides, actual)
} }
} }
func TestJniPartition(t *testing.T) {
bp := `
cc_library {
name: "libjni_system",
system_shared_libs: [],
sdk_version: "current",
stl: "none",
}
cc_library {
name: "libjni_system_ext",
system_shared_libs: [],
sdk_version: "current",
stl: "none",
system_ext_specific: true,
}
cc_library {
name: "libjni_odm",
system_shared_libs: [],
sdk_version: "current",
stl: "none",
device_specific: true,
}
cc_library {
name: "libjni_product",
system_shared_libs: [],
sdk_version: "current",
stl: "none",
product_specific: true,
}
cc_library {
name: "libjni_vendor",
system_shared_libs: [],
sdk_version: "current",
stl: "none",
soc_specific: true,
}
android_app {
name: "test_app_system_jni_system",
privileged: true,
platform_apis: true,
certificate: "platform",
jni_libs: ["libjni_system"],
}
android_app {
name: "test_app_system_jni_system_ext",
privileged: true,
platform_apis: true,
certificate: "platform",
jni_libs: ["libjni_system_ext"],
}
android_app {
name: "test_app_system_ext_jni_system",
privileged: true,
platform_apis: true,
certificate: "platform",
jni_libs: ["libjni_system"],
system_ext_specific: true
}
android_app {
name: "test_app_system_ext_jni_system_ext",
sdk_version: "core_platform",
jni_libs: ["libjni_system_ext"],
system_ext_specific: true
}
android_app {
name: "test_app_product_jni_product",
sdk_version: "core_platform",
jni_libs: ["libjni_product"],
product_specific: true
}
android_app {
name: "test_app_vendor_jni_odm",
sdk_version: "core_platform",
jni_libs: ["libjni_odm"],
soc_specific: true
}
android_app {
name: "test_app_odm_jni_vendor",
sdk_version: "core_platform",
jni_libs: ["libjni_vendor"],
device_specific: true
}
android_app {
name: "test_app_system_jni_multiple",
privileged: true,
platform_apis: true,
certificate: "platform",
jni_libs: ["libjni_system", "libjni_system_ext"],
}
android_app {
name: "test_app_vendor_jni_multiple",
sdk_version: "core_platform",
jni_libs: ["libjni_odm", "libjni_vendor"],
soc_specific: true
}
`
arch := "arm64"
ctx := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcDefaultModules,
android.PrepareForTestWithAndroidMk,
android.FixtureModifyConfig(func(config android.Config) {
config.TestProductVariables.DeviceArch = proptools.StringPtr(arch)
}),
).
RunTestWithBp(t, bp)
testCases := []struct {
name string
partitionNames []string
partitionTags []string
}{
{"test_app_system_jni_system", []string{"libjni_system"}, []string{""}},
{"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
{"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}},
{"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
{"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}},
{"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}},
{"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}},
{"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}},
{"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
mod := ctx.ModuleForTests(test.name, "android_common").Module()
entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
for i := range test.partitionNames {
actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i]
expected := test.partitionNames[i] + ":" + test.partitionTags[i]
android.AssertStringEquals(t, "Expected and actual differ", expected, actual)
}
})
}
}

View file

@ -274,37 +274,16 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
variation := append(jniTarget.Variations(), variation := append(jniTarget.Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"}) blueprint.Variation{Mutator: "link", Variation: "shared"})
// Test whether to use the SDK variant or the non-SDK variant of JNI dependencies. // If the app builds against an Android SDK use the SDK variant of JNI dependencies
// Many factors are considered here. // unless jni_uses_platform_apis is set.
// 1. Basically, the selection follows whether the app has sdk_version set or not. // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already
jniUsesSdkVariant := usesSDK // have stable APIs through the VNDK.
// 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it if (usesSDK && !a.RequiresStableAPIs(ctx) &&
if Bool(a.appProperties.Jni_uses_sdk_apis) { !Bool(a.appProperties.Jni_uses_platform_apis)) ||
jniUsesSdkVariant = true Bool(a.appProperties.Jni_uses_sdk_apis) {
}
if Bool(a.appProperties.Jni_uses_platform_apis) {
jniUsesSdkVariant = false
}
// 3. Then the use of SDK variant is again prohibited for the following cases:
// 3.1. the app is shipped on unbundled partitions like vendor. Since the entire
// partition (not only the app) is considered unbudled, there's no need to use the
// SDK variant.
// 3.2. the app doesn't support embedding the JNI libs
if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) {
jniUsesSdkVariant = false
}
if jniUsesSdkVariant {
variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
} }
ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
// Use the installable dep tag when the JNIs are not embedded
var tag dependencyTag
if a.shouldEmbedJnis(ctx) {
tag = jniLibTag
} else {
tag = jniInstallTag
}
ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
} }
for _, aconfig_declaration := range a.aaptProperties.Flags_packages { for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration) ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
@ -355,7 +334,6 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkAppSdkVersions(ctx) a.checkAppSdkVersions(ctx)
a.checkEmbedJnis(ctx)
a.generateAndroidBuildActions(ctx) a.generateAndroidBuildActions(ctx)
a.generateJavaUsedByApex(ctx) a.generateJavaUsedByApex(ctx)
} }
@ -400,17 +378,6 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
a.checkSdkVersions(ctx) a.checkSdkVersions(ctx)
} }
// Ensures that use_embedded_native_libs are set for apk-in-apex
func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
apkInApex := !apexInfo.IsForPlatform()
hasJnis := len(a.appProperties.Jni_libs) > 0
if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
}
}
// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. // If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it.
// This check is enforced for "updatable" APKs (including APK-in-APEX). // This check is enforced for "updatable" APKs (including APK-in-APEX).
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) { func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
@ -466,9 +433,9 @@ func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
} }
func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool { func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) || return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
Bool(a.appProperties.Updatable) || !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
a.appProperties.AlwaysPackageNativeLibs
} }
func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
@ -862,9 +829,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
dexJarFile, packageResources := a.dexBuildActions(ctx) dexJarFile, packageResources := a.dexBuildActions(ctx)
// No need to check the SDK version of the JNI deps unless we embed them jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis)
jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion)
jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx) jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
if ctx.Failed() { if ctx.Failed() {
@ -946,22 +911,6 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
installed := ctx.InstallFile(a.installDir, extra.Base(), extra) installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
extraInstalledPaths = append(extraInstalledPaths, installed) extraInstalledPaths = append(extraInstalledPaths, installed)
} }
// If we don't embed jni libs, make sure that those are installed along with the
// app, and also place symlinks to the installed paths under the lib/<arch>
// directory of the app installation directory. ex:
// /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so
if !a.embeddedJniLibs {
for _, jniLib := range jniLibs {
archStr := jniLib.target.Arch.ArchType.String()
symlinkDir := a.installDir.Join(ctx, "lib", archStr)
for _, installedLib := range jniLib.installPaths {
// install the symlink itself
symlinkName := installedLib.Base()
symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib)
ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget)
}
}
}
ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...) ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
} }
@ -1049,7 +998,6 @@ func collectJniDeps(ctx android.ModuleContext,
coverageFile: dep.CoverageOutputFile(), coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(), unstrippedFile: dep.UnstrippedOutputFile(),
partition: dep.Partition(), partition: dep.Partition(),
installPaths: dep.FilesToInstall(),
}) })
} else if ctx.Config().AllowMissingDependencies() { } else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{otherName}) ctx.AddMissingDependencies([]string{otherName})

View file

@ -366,14 +366,14 @@ type dependencyTag struct {
toolchain bool toolchain bool
static bool static bool
installable bool
} }
var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil) // installDependencyTag is a dependency tag that is annotated to cause the installed files of the
// dependency to be installed when the parent module is installed.
func (d dependencyTag) InstallDepNeeded() bool { type installDependencyTag struct {
return d.installable blueprint.BaseDependencyTag
android.InstallAlwaysNeededDependencyTag
name string
} }
func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation { func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
@ -405,7 +405,7 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDepe
} }
func IsJniDepTag(depTag blueprint.DependencyTag) bool { func IsJniDepTag(depTag blueprint.DependencyTag) bool {
return depTag == jniLibTag || depTag == jniInstallTag return depTag == jniLibTag
} }
var ( var (
@ -434,8 +434,8 @@ var (
javaApiContributionTag = dependencyTag{name: "java-api-contribution"} javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
depApiSrcsTag = dependencyTag{name: "dep-api-srcs"} depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true} jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true} binaryInstallTag = installDependencyTag{name: "binary install"}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false) usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true) usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true) usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
@ -491,7 +491,6 @@ type jniLib struct {
coverageFile android.OptionalPath coverageFile android.OptionalPath
unstrippedFile android.Path unstrippedFile android.Path
partition string partition string
installPaths android.InstallPaths
} }
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) { func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {