Enforce app updatability in GenerateAndroidBuildActions
Remove part of the apex top down mutator by moving enforceAppUpdatability
to a check in GenerateAndroidBuildActions instead of mutating
dependencies. This requires annotating app dependencies of updatable
apexes with `updatable: true` in the Android.bp files.
Bug: 367784740
Test: builds
Flag: EXEMPT refactor
Change-Id: I234a457bba48c0f48410d53740aaa9b89661ca7c
diff --git a/apex/apex.go b/apex/apex.go
index 63b8d38..fd6f5b5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1110,23 +1110,6 @@
if am, ok := mctx.Module().(android.ApexModule); ok {
android.ApexInfoMutator(mctx, am)
}
- enforceAppUpdatability(mctx)
-}
-
-// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
-func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
- if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() {
- // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
- mctx.VisitDirectDeps(func(module android.Module) {
- // ignore android_test_app
- if app, ok := module.(*java.AndroidApp); ok {
- app.SetUpdatable(true)
- }
- })
- }
}
// TODO: b/215736885 Whittle the denylist
@@ -1872,6 +1855,7 @@
a.CheckMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
a.checkStaticExecutables(ctx)
+ a.enforceAppUpdatability(ctx)
if len(a.properties.Tests) > 0 && !a.testApex {
ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
return false
@@ -2397,6 +2381,24 @@
}
}
+// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
+func (a *apexBundle) enforceAppUpdatability(mctx android.ModuleContext) {
+ if !a.Enabled(mctx) {
+ return
+ }
+ if a.Updatable() {
+ // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
+ mctx.VisitDirectDeps(func(module android.Module) {
+ if appInfo, ok := android.OtherModuleProvider(mctx, module, java.AppInfoProvider); ok {
+ // ignore android_test_app
+ if !appInfo.TestHelperApp && !appInfo.Updatable {
+ mctx.ModuleErrorf("app dependency %s must have updatable: true", mctx.OtherModuleName(module))
+ }
+ }
+ })
+ }
+}
+
// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
// the bootclasspath_fragment contributes to the apex.
func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index b372d7f..da6214d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5450,7 +5450,7 @@
android.PrepareForTestWithAllowMissingDependencies,
android.FixtureMergeMockFs(map[string][]byte{
"build/soong/scripts/check_boot_jars/package_allowed_list.txt": nil,
- "frameworks/base/boot/boot-profile.txt": nil,
+ "frameworks/base/boot/boot-profile.txt": nil,
}),
)
@@ -9876,7 +9876,7 @@
apex {
name: "myapex",
key: "myapex.key",
- updatable: %v,
+ updatable: true,
apps: [
"myapp",
],
@@ -9887,7 +9887,6 @@
}
android_app {
name: "myapp",
- updatable: %v,
apex_available: [
"myapex",
],
@@ -9895,42 +9894,10 @@
min_sdk_version: "30",
}
`
- testCases := []struct {
- name string
- apex_is_updatable_bp bool
- app_is_updatable_bp bool
- app_is_updatable_expected bool
- }{
- {
- name: "Non-updatable apex respects updatable property of non-updatable app",
- apex_is_updatable_bp: false,
- app_is_updatable_bp: false,
- app_is_updatable_expected: false,
- },
- {
- name: "Non-updatable apex respects updatable property of updatable app",
- apex_is_updatable_bp: false,
- app_is_updatable_bp: true,
- app_is_updatable_expected: true,
- },
- {
- name: "Updatable apex respects updatable property of updatable app",
- apex_is_updatable_bp: true,
- app_is_updatable_bp: true,
- app_is_updatable_expected: true,
- },
- {
- name: "Updatable apex sets updatable=true on non-updatable app",
- apex_is_updatable_bp: true,
- app_is_updatable_bp: false,
- app_is_updatable_expected: true,
- },
- }
- for _, testCase := range testCases {
- result := testApex(t, fmt.Sprintf(bp, testCase.apex_is_updatable_bp, testCase.app_is_updatable_bp))
- myapp := result.ModuleForTests("myapp", "android_common").Module().(*java.AndroidApp)
- android.AssertBoolEquals(t, testCase.name, testCase.app_is_updatable_expected, myapp.Updatable())
- }
+ _ = android.GroupFixturePreparers(
+ prepareForApexTest,
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("app dependency myapp must have updatable: true")).
+ RunTestWithBp(t, bp)
}
func TestTrimmedApex(t *testing.T) {
@@ -11699,6 +11666,7 @@
sdk_version: "core_current",
min_sdk_version: "30",
manifest: "AndroidManifest.xml",
+ updatable: true,
}
`)
}