diff options
Diffstat (limited to 'apex')
| -rw-r--r-- | apex/apex.go | 69 | ||||
| -rw-r--r-- | apex/apex_test.go | 179 | ||||
| -rw-r--r-- | apex/bootclasspath_fragment_test.go | 16 |
3 files changed, 254 insertions, 10 deletions
diff --git a/apex/apex.go b/apex/apex.go index 89b5f2176..bb9207dc2 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -130,6 +130,13 @@ type apexBundleProperties struct { // symlinking to the system libs. Default is true. Updatable *bool + // Marks that this APEX is designed to be updatable in the future, although it's not + // updatable yet. This is used to mimic some of the build behaviors that are applied only to + // updatable APEXes. Currently, this disables the size optimization, so that the size of + // APEX will not increase when the APEX is actually marked as truly updatable. Default is + // false. + Future_updatable *bool + // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable: // false`. Default is false. Platform_apis *bool @@ -1306,6 +1313,10 @@ func (a *apexBundle) Updatable() bool { return proptools.BoolDefault(a.properties.Updatable, true) } +func (a *apexBundle) FutureUpdatable() bool { + return proptools.BoolDefault(a.properties.Future_updatable, false) +} + func (a *apexBundle) UsePlatformApis() bool { return proptools.BoolDefault(a.properties.Platform_apis, false) } @@ -1670,7 +1681,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 1) do some validity checks such as apex_available, min_sdk_version, etc. a.checkApexAvailability(ctx) a.checkUpdatable(ctx) - a.checkMinSdkVersion(ctx) + a.CheckMinSdkVersion(ctx) a.checkStaticLinkingToStubLibraries(ctx) a.checkStaticExecutables(ctx) if len(a.properties.Tests) > 0 && !a.testApex { @@ -2105,10 +2116,11 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } forced := ctx.Config().ForceApexSymlinkOptimization() + updatable := a.Updatable() || a.FutureUpdatable() // We don't need the optimization for updatable APEXes, as it might give false signal // to the system health when the APEXes are still bundled (b/149805758). - if !forced && a.Updatable() && a.properties.ApexType == imageApex { + if !forced && updatable && a.properties.ApexType == imageApex { a.linkToSystemLib = false } @@ -2174,6 +2186,40 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. filesToAdd = append(filesToAdd, *af) } + if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" { + pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost() + tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex) + + if pathOnHost != nil { + // We need to copy the profile to a temporary path with the right filename because the apexer + // will take the filename as is. + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: pathOnHost, + Output: tempPath, + }) + } else { + // At this point, the boot image profile cannot be generated. It is probably because the boot + // image profile source file does not exist on the branch, or it is not available for the + // current build target. + // However, we cannot enforce the boot image profile to be generated because some build + // targets (such as module SDK) do not need it. It is only needed when the APEX is being + // built. Therefore, we create an error rule so that an error will occur at the ninja phase + // only if the APEX is being built. + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: tempPath, + Args: map[string]string{ + "error": "Boot image profile cannot be generated", + }, + }) + } + + androidMkModuleName := filepath.Base(pathInApex) + af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil) + filesToAdd = append(filesToAdd, af) + } + return filesToAdd } @@ -2300,18 +2346,28 @@ func overrideApexFactory() android.Module { // // TODO(jiyong): move these checks to a separate go file. +var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil) + // Entures that min_sdk_version of the included modules are equal or less than the min_sdk_version // of this apexBundle. -func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) { +func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) { if a.testApex || a.vndkApex { return } // apexBundle::minSdkVersion reports its own errors. minSdkVersion := a.minSdkVersion(ctx) - android.CheckMinSdkVersion(a, ctx, minSdkVersion) + android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) } -func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel { +func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpec{ + Kind: android.SdkNone, + ApiLevel: a.minSdkVersion(ctx), + Raw: String(a.properties.Min_sdk_version), + } +} + +func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { ver := proptools.String(a.properties.Min_sdk_version) if ver == "" { return android.NoneApiLevel @@ -2380,6 +2436,9 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if a.SocSpecific() || a.DeviceSpecific() { ctx.PropertyErrorf("updatable", "vendor APEXes are not updatable") } + if a.FutureUpdatable() { + ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`") + } a.checkJavaStableSdkVersion(ctx) a.checkClasspathFragments(ctx) } diff --git a/apex/apex_test.go b/apex/apex_test.go index b805cd91b..3b9b13acb 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -7037,6 +7037,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F `, insert)) } }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), ). ExtendWithErrorHandler(errorHandler). RunTestWithBp(t, bp) @@ -8409,6 +8410,184 @@ func TestAndroidMk_RequiredModules(t *testing.T) { ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherapex") } +func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) { + preparer := android.GroupFixturePreparers( + PrepareForTestWithApexBuildComponents, + prepareForTestWithMyapex, + java.PrepareForTestWithJavaSdkLibraryFiles, + java.PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAndroidBuildComponents, + dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"), + ) + + // Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex + t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) { + preparer.RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["mybootclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mybootclasspathlib", + srcs: ["mybootclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + min_sdk_version: "31", + static_libs: ["util"], + } + + java_library { + name: "util", + srcs: ["a.java"], + apex_available: ["myapex"], + min_sdk_version: "31", + static_libs: ["another_util"], + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + apex_available: ["myapex"], + } + `) + }) + + // Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex + t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) { + preparer.RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + systemserverclasspath_fragments: ["mysystemserverclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + contents: ["mysystemserverclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mysystemserverclasspathlib", + srcs: ["mysystemserverclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + min_sdk_version: "32", + unsafe_ignore_missing_latest_api: true, + static_libs: ["util"], + } + + java_library { + name: "util", + srcs: ["a.java"], + apex_available: ["myapex"], + min_sdk_version: "31", + static_libs: ["another_util"], + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + apex_available: ["myapex"], + } + `) + }) + + t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) { + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)). + RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["mybootclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mybootclasspathlib", + srcs: ["mybootclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + } + `) + }) + + t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) { + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)). + RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + systemserverclasspath_fragments: ["mysystemserverclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + contents: ["mysystemserverclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mysystemserverclasspathlib", + srcs: ["mysystemserverclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + } + `) + }) +} + func TestMain(m *testing.M) { os.Exit(m.Run()) } diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index cb7d3d113..9e030f10c 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -21,6 +21,7 @@ import ( "testing" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" "github.com/google/blueprint/proptools" @@ -35,11 +36,14 @@ var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( ) // Some additional files needed for the art apex. -var prepareForTestWithArtApex = android.FixtureMergeMockFs(android.MockFS{ - "com.android.art.avbpubkey": nil, - "com.android.art.pem": nil, - "system/sepolicy/apex/com.android.art-file_contexts": nil, -}) +var prepareForTestWithArtApex = android.GroupFixturePreparers( + android.FixtureMergeMockFs(android.MockFS{ + "com.android.art.avbpubkey": nil, + "com.android.art.pem": nil, + "system/sepolicy/apex/com.android.art-file_contexts": nil, + }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), +) func TestBootclasspathFragments(t *testing.T) { result := android.GroupFixturePreparers( @@ -408,6 +412,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", @@ -451,6 +456,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", |