diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/aar.go | 4 | ||||
| -rw-r--r-- | java/androidmk.go | 25 | ||||
| -rw-r--r-- | java/androidmk_test.go | 164 | ||||
| -rw-r--r-- | java/app.go | 100 | ||||
| -rw-r--r-- | java/app_import.go | 4 | ||||
| -rw-r--r-- | java/app_test.go | 79 | ||||
| -rw-r--r-- | java/base.go | 17 | ||||
| -rw-r--r-- | java/bootclasspath_fragment.go | 27 | ||||
| -rw-r--r-- | java/dex.go | 8 | ||||
| -rw-r--r-- | java/dexpreopt.go | 16 | ||||
| -rw-r--r-- | java/droidstubs.go | 4 | ||||
| -rw-r--r-- | java/hiddenapi_singleton_test.go | 11 | ||||
| -rw-r--r-- | java/java.go | 23 | ||||
| -rw-r--r-- | java/platform_bootclasspath.go | 24 | ||||
| -rw-r--r-- | java/sdk_library.go | 18 |
15 files changed, 247 insertions, 277 deletions
diff --git a/java/aar.go b/java/aar.go index 47c64bfe8..07392f6e5 100644 --- a/java/aar.go +++ b/java/aar.go @@ -1014,9 +1014,6 @@ type AARImport struct { usesLibrary classLoaderContexts dexpreopt.ClassLoaderContextMap - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } var _ android.OutputFileProducer = (*AARImport)(nil) @@ -1386,7 +1383,6 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{ JniPackages: a.jniPackages, }) - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) } func (a *AARImport) HeaderJars() android.Paths { diff --git a/java/androidmk.go b/java/androidmk.go index 9cd0bafea..a1bc90494 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -17,7 +17,6 @@ package java import ( "fmt" "io" - "strings" "android/soong/android" @@ -124,7 +123,6 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.dexpreopter.configPath != nil { entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath) } - android.SetAconfigFileMkEntries(&library.ModuleBase, entries, library.mergedAconfigFiles) }, }, }) @@ -298,7 +296,6 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { if len(binary.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled) } - android.SetAconfigFileMkEntries(&binary.ModuleBase, entries, binary.mergedAconfigFiles) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -416,22 +413,11 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String()) entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String()) } else { + var names []string 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) + names = append(names, jniLib.name) } + entries.AddStrings("LOCAL_REQUIRED_MODULES", names...) } if len(app.jniCoverageOutputs) > 0 { @@ -450,10 +436,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports) - if app.Name() != "framework-res" { - android.SetAconfigFileMkEntries(&app.ModuleBase, entries, app.mergedAconfigFiles) - } - entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", app.logtagsSrcs.Strings()...) }, }, @@ -531,7 +513,6 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries { entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile) entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.combinedExportedProguardFlagsFile) entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true) - android.SetAconfigFileMkEntries(&a.ModuleBase, entries, a.mergedAconfigFiles) }) return entriesList diff --git a/java/androidmk_test.go b/java/androidmk_test.go index 2978a40aa..243a2791e 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -20,8 +20,6 @@ import ( "android/soong/android" "android/soong/cc" - - "github.com/google/blueprint/proptools" ) func TestRequired(t *testing.T) { @@ -256,148 +254,50 @@ func TestGetOverriddenPackages(t *testing.T) { } } -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"], - } - +func TestJniAsRequiredDeps(t *testing.T) { + ctx := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + cc.PrepareForTestWithCcDefaultModules, + android.PrepareForTestWithAndroidMk, + ).RunTestWithBp(t, ` android_app { - name: "test_app_system_jni_system_ext", - privileged: true, + name: "app", + jni_libs: ["libjni"], platform_apis: true, - certificate: "platform", - jni_libs: ["libjni_system_ext"], } android_app { - name: "test_app_system_ext_jni_system", - privileged: true, + name: "app_embedded", + jni_libs: ["libjni"], 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 + use_embedded_native_libs: 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 + cc_library { + name: "libjni", + system_shared_libs: [], + stl: "none", } + `) - 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 + testcases := []struct { + name string + expected []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"}}, + { + name: "app", + expected: []string{"libjni"}, + }, + { + name: "app_embedded", + expected: nil, + }, } - 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) - } - }) + for _, tc := range testcases { + mod := ctx.ModuleForTests(tc.name, "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0] + required := entries.EntryMap["LOCAL_REQUIRED_MODULES"] + android.AssertDeepEquals(t, "unexpected required deps", tc.expected, required) } } diff --git a/java/app.go b/java/app.go index 50d1a2f43..d2f2d0be1 100644 --- a/java/app.go +++ b/java/app.go @@ -274,16 +274,37 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { variation := append(jniTarget.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"}) - // If the app builds against an Android SDK use the SDK variant of JNI dependencies - // unless jni_uses_platform_apis is set. - // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already - // have stable APIs through the VNDK. - if (usesSDK && !a.RequiresStableAPIs(ctx) && - !Bool(a.appProperties.Jni_uses_platform_apis)) || - Bool(a.appProperties.Jni_uses_sdk_apis) { + // Test whether to use the SDK variant or the non-SDK variant of JNI dependencies. + // Many factors are considered here. + // 1. Basically, the selection follows whether the app has sdk_version set or not. + jniUsesSdkVariant := usesSDK + // 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it + if Bool(a.appProperties.Jni_uses_sdk_apis) { + jniUsesSdkVariant = true + } + 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"}) } - 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 { ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration) @@ -334,27 +355,17 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkAppSdkVersions(ctx) + a.checkEmbedJnis(ctx) a.generateAndroidBuildActions(ctx) a.generateJavaUsedByApex(ctx) } -func (a *AndroidApp) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { - defaultMinSdkVersion := a.Module.MinSdkVersion(ctx) - if proptools.Bool(a.appProperties.Updatable) { - overrideApiLevel := android.MinSdkVersionFromValue(ctx, ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()) - if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(defaultMinSdkVersion) > 0 { - return overrideApiLevel - } - } - return defaultMinSdkVersion -} - func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if a.Updatable() { if !a.SdkVersion(ctx).Stable() { ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.SdkVersion(ctx)) } - if String(a.deviceProperties.Min_sdk_version) == "" { + if String(a.overridableProperties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") } @@ -378,6 +389,17 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { 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. // This check is enforced for "updatable" APKs (including APK-in-APEX). func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) { @@ -433,9 +455,9 @@ func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) 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) || - !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs + Bool(a.appProperties.Updatable) || + a.appProperties.AlwaysPackageNativeLibs } func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { @@ -521,7 +543,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { } // Use non final ids if we are doing optimized shrinking and are using R8. - nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled() + nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled() a.aapt.buildActions(ctx, aaptBuildActionOptions{ sdkContext: android.SdkContext(a), @@ -552,7 +574,7 @@ func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) { staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles) a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...) - if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) { + if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) { // When using the optimized shrinking the R8 enqueuer will traverse the xml files that become // live for code references and (transitively) mark these as live. // In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now @@ -591,7 +613,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a var packageResources = a.exportPackage if ctx.ModuleName() != "framework-res" { - if a.dexProperties.resourceShrinkingEnabled() { + if a.dexProperties.resourceShrinkingEnabled(ctx) { protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk") aapt2Convert(ctx, protoFile, packageResources, "proto") a.dexer.resourcesInput = android.OptionalPathForPath(protoFile) @@ -614,7 +636,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a } a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars) - if a.dexProperties.resourceShrinkingEnabled() { + if a.dexProperties.resourceShrinkingEnabled(ctx) { binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk") aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary") packageResources = binaryResources @@ -829,7 +851,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile, packageResources := a.dexBuildActions(ctx) - jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) + // No need to check the SDK version of the JNI deps unless we embed them + 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) if ctx.Failed() { @@ -911,6 +935,22 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { installed := ctx.InstallFile(a.installDir, extra.Base(), extra) 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...) } @@ -998,6 +1038,7 @@ func collectJniDeps(ctx android.ModuleContext, coverageFile: dep.CoverageOutputFile(), unstrippedFile: dep.UnstrippedOutputFile(), partition: dep.Partition(), + installPaths: dep.FilesToInstall(), }) } else if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{otherName}) @@ -1243,6 +1284,11 @@ func AndroidAppFactory() android.Module { Manifest: proptools.StringPtr(":" + rroManifestName), Resource_dirs: a.aaptProperties.Resource_dirs, } + if !Bool(a.aaptProperties.Aapt_include_all_resources) { + for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { + rroProperties.Aaptflags = append(rroProperties.Aaptflags, "-c", aaptConfig) + } + } ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties) }) diff --git a/java/app_import.go b/java/app_import.go index bb07c423a..dc8470da7 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -87,9 +87,6 @@ type AndroidAppImport struct { hideApexVariantFromMake bool provenanceMetaDataFile android.OutputPath - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } type AndroidAppImportProperties struct { @@ -416,7 +413,6 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk) a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath) } - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) providePrebuiltInfo(ctx, prebuiltInfoProps{ diff --git a/java/app_test.go b/java/app_test.go index a7c48a1ed..804949435 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -4322,52 +4322,6 @@ func TestPrivappAllowlistAndroidMk(t *testing.T) { ) } -func TestApexGlobalMinSdkVersionOverride(t *testing.T) { - result := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.ApexGlobalMinSdkVersionOverride = proptools.StringPtr("Tiramisu") - }), - ).RunTestWithBp(t, ` - android_app { - name: "com.android.bar", - srcs: ["a.java"], - sdk_version: "current", - } - android_app { - name: "com.android.foo", - srcs: ["a.java"], - sdk_version: "current", - min_sdk_version: "S", - updatable: true, - } - override_android_app { - name: "com.android.go.foo", - base: "com.android.foo", - } - `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") - fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer") - bar := result.ModuleForTests("com.android.bar", "android_common").Rule("manifestFixer") - - android.AssertStringDoesContain(t, - "expected manifest fixer to set com.android.bar minSdkVersion to S", - bar.BuildParams.Args["args"], - "--minSdkVersion S", - ) - android.AssertStringDoesContain(t, - "com.android.foo: expected manifest fixer to set minSdkVersion to T", - foo.BuildParams.Args["args"], - "--minSdkVersion T", - ) - android.AssertStringDoesContain(t, - "com.android.go.foo: expected manifest fixer to set minSdkVersion to T", - fooOverride.BuildParams.Args["args"], - "--minSdkVersion T", - ) - -} - func TestAppFlagsPackages(t *testing.T) { ctx := testApp(t, ` android_app { @@ -4492,3 +4446,36 @@ func TestAppStem(t *testing.T) { t.Errorf("Module output does not contain expected apk %s", "foo-new.apk") } } + +func TestAppMinSdkVersionOverride(t *testing.T) { + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + ).RunTestWithBp(t, ` + android_app { + name: "com.android.foo", + srcs: ["a.java"], + sdk_version: "current", + min_sdk_version: "31", + updatable: true, + } + override_android_app { + name: "com.android.go.foo", + base: "com.android.foo", + min_sdk_version: "33", + } + `) + foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") + fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer") + + android.AssertStringDoesContain(t, + "com.android.foo: expected manifest fixer to set minSdkVersion to T", + foo.BuildParams.Args["args"], + "--minSdkVersion 31", + ) + android.AssertStringDoesContain(t, + "com.android.go.foo: expected manifest fixer to set minSdkVersion to T", + fooOverride.BuildParams.Args["args"], + "--minSdkVersion 33", + ) + +} diff --git a/java/base.go b/java/base.go index 06c18ca43..e97d28de2 100644 --- a/java/base.go +++ b/java/base.go @@ -229,10 +229,6 @@ type DeviceProperties struct { // If the SDK kind is empty, it will be set to public. Sdk_version *string - // if not blank, set the minimum version of the sdk that the compiled artifacts will run against. - // Defaults to sdk_version if not set. See sdk_version for possible values. - Min_sdk_version *string - // if not blank, set the maximum version of the sdk that the compiled artifacts will run against. // Defaults to empty string "". See sdk_version for possible values. Max_sdk_version *string @@ -312,6 +308,10 @@ type OverridableProperties struct { // Otherwise, both the overridden and the overriding modules will have the same output name, which // can cause the duplicate output error. Stem *string + + // if not blank, set the minimum version of the sdk that the compiled artifacts will run against. + // Defaults to sdk_version if not set. See sdk_version for possible values. + Min_sdk_version *string } // Functionality common to Module and Import @@ -537,9 +537,6 @@ type Module struct { // or the module should override Stem(). stem string - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths - // Values that will be set in the JarJarProvider data for jarjar repackaging, // and merged with our dependencies' rules. jarjarRenameRules map[string]string @@ -741,8 +738,8 @@ func (j *Module) SystemModules() string { } func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { - if j.deviceProperties.Min_sdk_version != nil { - return android.ApiLevelFrom(ctx, *j.deviceProperties.Min_sdk_version) + if j.overridableProperties.Min_sdk_version != nil { + return android.ApiLevelFrom(ctx, *j.overridableProperties.Min_sdk_version) } return j.SdkVersion(ctx).ApiLevel } @@ -1734,8 +1731,6 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ctx.CheckbuildFile(outputFile) - android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles) - android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile), diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 82a34ca9d..4d3d794d8 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -590,13 +590,36 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. // TODO(b/202896428): Add better way to handle this. _, unknown = android.RemoveFromList("android.car-module", unknown) - if isActiveModule(ctx, ctx.Module()) && len(unknown) > 0 { - ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) + if isApexVariant(ctx) && len(unknown) > 0 { + if android.IsModulePrebuilt(ctx.Module()) { + // prebuilt bcpf. the validation of this will be done at the top-level apex + providerClasspathFragmentValidationInfoProvider(ctx, unknown) + } else if !disableSourceApexVariant(ctx) { + // source bcpf, and prebuilt apex are not selected. + ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) + } } } return jars } +var ClasspathFragmentValidationInfoProvider = blueprint.NewProvider[ClasspathFragmentValidationInfo]() + +type ClasspathFragmentValidationInfo struct { + ClasspathFragmentModuleName string + UnknownJars []string +} + +// Set a provider with the list of jars that have not been added to PRODUCT_APEX_BOOT_JARS +// The validation will be done in the ctx of the top-level _selected_ apex +func providerClasspathFragmentValidationInfoProvider(ctx android.ModuleContext, unknown []string) { + info := ClasspathFragmentValidationInfo{ + ClasspathFragmentModuleName: ctx.ModuleName(), + UnknownJars: unknown, + } + android.SetProvider(ctx, ClasspathFragmentValidationInfoProvider, info) +} + // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { diff --git a/java/dex.go b/java/dex.go index 6caaa7f48..8cfffaf1f 100644 --- a/java/dex.go +++ b/java/dex.go @@ -111,8 +111,12 @@ func (d *dexer) effectiveOptimizeEnabled() bool { return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault) } -func (d *DexProperties) resourceShrinkingEnabled() bool { - return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources)) +func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool { + return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources)) +} + +func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool { + return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources) } var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 1acac1b40..4d6dbffe1 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -262,6 +262,20 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName s if !isApexSystemServerJar { return true } + ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + allApexInfos := []android.ApexInfo{} + if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok { + allApexInfos = allApexInfosProvider.ApexInfos + } + if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) { + // Apex system server jars are dexpreopted and installed on to the system image. + // Since we can have BigAndroid and Go variants of system server jar providing apexes, + // and these two variants can have different min_sdk_versions, hide one of the apex variants + // from make to prevent collisions. + // + // Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries. + ctx.Module().MakeUninstallable() + } } else { // Don't preopt the platform variant of an APEX system server jar to avoid conflicts. if isApexSystemServerJar { @@ -502,7 +516,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa // Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars // The javalib from the deapexed prebuilt will be copied to this location. // TODO (b/331665856): Implement a principled solution for this. - copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) + copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake() dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex) if err != nil { diff --git a/java/droidstubs.go b/java/droidstubs.go index 730be14b0..ca81343f0 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -106,9 +106,6 @@ type Droidstubs struct { everythingArtifacts stubsArtifacts exportableArtifacts stubsArtifacts - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths - exportableApiFile android.WritablePath exportableRemovedApiFile android.WritablePath } @@ -1342,7 +1339,6 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("nullabilityWarningsCheck", "nullability warnings check") } - android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles) } func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) { diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index 330013ee4..62297978c 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -198,13 +198,22 @@ func TestHiddenAPISingletonSdks(t *testing.T) { hiddenApiFixtureFactory, tc.preparer, prepareForTestWithDefaultPlatformBootclasspath, + // Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi + // file creation. + FixtureConfigureBootJars("platform:foo"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild) variables.BuildFlags = map[string]string{ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true", } }), - ).RunTest(t) + ).RunTestWithBp(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + } + `) hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") diff --git a/java/java.go b/java/java.go index 0df96a3a5..e3f482450 100644 --- a/java/java.go +++ b/java/java.go @@ -366,14 +366,14 @@ type dependencyTag struct { toolchain bool static bool + + installable bool } -// 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. -type installDependencyTag struct { - blueprint.BaseDependencyTag - android.InstallAlwaysNeededDependencyTag - name string +var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil) + +func (d dependencyTag) InstallDepNeeded() bool { + return d.installable } func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation { @@ -405,7 +405,7 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDepe } func IsJniDepTag(depTag blueprint.DependencyTag) bool { - return depTag == jniLibTag + return depTag == jniLibTag || depTag == jniInstallTag } var ( @@ -434,8 +434,8 @@ var ( javaApiContributionTag = dependencyTag{name: "java-api-contribution"} depApiSrcsTag = dependencyTag{name: "dep-api-srcs"} aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} - jniInstallTag = installDependencyTag{name: "jni install"} - binaryInstallTag = installDependencyTag{name: "binary install"} + jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true} + binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true} usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false) usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true) usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true) @@ -491,6 +491,7 @@ type jniLib struct { coverageFile android.OptionalPath unstrippedFile android.Path partition string + installPaths android.InstallPaths } func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) { @@ -908,7 +909,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Check min_sdk_version of the transitive dependencies if this module is created from // java_sdk_library. - if j.deviceProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil { + if j.overridableProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil { j.CheckDepsMinSdkVersion(ctx) } @@ -1096,7 +1097,7 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberCo // If the min_sdk_version was set then add the canonical representation of the API level to the // snapshot. - if j.deviceProperties.Min_sdk_version != nil { + if j.overridableProperties.Min_sdk_version != nil { canonical, err := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String()) if err != nil { ctx.ModuleErrorf("%s", err) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index b3c9ce50f..8d4cf6823 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -294,6 +294,15 @@ func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule { + createEmptyHiddenApiFiles := func() { + paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV} + for _, path := range paths { + ctx.Build(pctx, android.BuildParams{ + Rule: android.Touch, + Output: path, + }) + } + } // Save the paths to the monolithic files for retrieval via OutputFiles(). b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags @@ -306,13 +315,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. // optimization that can be used to reduce the incremental build time but as its name suggests it // can be unsafe to use, e.g. when the changes affect anything that goes on the bootclasspath. if ctx.Config().DisableHiddenApiChecks() { - paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV} - for _, path := range paths { - ctx.Build(pctx, android.BuildParams{ - Rule: android.Touch, - Output: path, - }) - } + createEmptyHiddenApiFiles() return bootDexJarByModule } @@ -325,6 +328,13 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. // the fragments will have already provided the flags that are needed. classesJars := monolithicInfo.ClassesJars + if len(classesJars) == 0 { + // This product does not include any monolithic jars. Monolithic hiddenapi flag generation is not required. + // However, generate an empty file so that the dist tags in f/b/boot/Android.bp can be resolved, and `m dist` works. + createEmptyHiddenApiFiles() + return bootDexJarByModule + } + // Create the input to pass to buildRuleToGenerateHiddenAPIStubFlagsFile input := newHiddenAPIFlagInput() diff --git a/java/sdk_library.go b/java/sdk_library.go index 677b32a5e..8c91288c3 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1504,6 +1504,12 @@ func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"} +var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{} + +func (t sdkLibraryComponentTag) InstallDepNeeded() bool { + return t.name == "xml-permissions-file" || t.name == "impl-library" +} + // Add the dependencies on the child modules in the component deps mutator. func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { for _, apiScope := range module.getGeneratedApiScopes(ctx) { @@ -1650,6 +1656,14 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost + // Properties required for Library.AndroidMkEntries + module.logtagsSrcs = module.implLibraryModule.logtagsSrcs + module.dexpreopter.builtInstalled = module.implLibraryModule.dexpreopter.builtInstalled + module.jacocoReportClassesFile = module.implLibraryModule.jacocoReportClassesFile + module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary + module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip + module.linter.reports = module.implLibraryModule.linter.reports + if !module.Host() { module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile } @@ -1814,7 +1828,6 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) props := struct { Name *string Visibility []string - Instrument bool Libs []string Static_libs []string Apex_available []string @@ -1822,8 +1835,6 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) }{ Name: proptools.StringPtr(module.implLibraryModuleName()), Visibility: visibility, - // Set the instrument property to ensure it is instrumented when instrumentation is required. - Instrument: true, Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...), @@ -1842,6 +1853,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) &module.dexProperties, &module.dexpreoptProperties, &module.linter.properties, + &module.overridableProperties, &props, module.sdkComponentPropertiesForChildLibrary(), } |