From a036da9b275a9614bf7734ab227fc5cd4305f7e7 Mon Sep 17 00:00:00 2001 From: Bill Peckham Date: Fri, 8 Jan 2021 16:09:09 -0800 Subject: [PATCH] Enable android_app_import to supply framework-res. By enabling an android_app_import module to supply the special framework-res module, it becomes possible to create a split build that excludes the source of over 10,000 files under frameworks/base/core/res, replacing this source with a prebuilt. However, since other parts of a monolithic build use the source of framework-res, this scheme works only if your split build manifest excludes modules that depend on framework-res source. Bug: 176851898 Test: lunch aosp_arm64-userdebug && m nothing Test: new TestAndroidAppImportExportPackageResources Test: local build without prebuilt framework-res Test: local build with prebuilt framework-res Change-Id: If00d9dbc656c8406c038448d09f93f767c1e06d1 --- java/androidmk.go | 3 ++ java/app_import.go | 27 ++++++++++++++++-- java/app_import_test.go | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/java/androidmk.go b/java/androidmk.go index 21f3012a4..6e7c437ab 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -646,6 +646,9 @@ func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", a.dexpreopter.builtInstalled) } entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel()) + if Bool(a.properties.Export_package_resources) { + entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile) + } }, }, }} diff --git a/java/app_import.go b/java/app_import.go index 6f21bfbbf..59eb10a9b 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -92,6 +92,10 @@ type AndroidAppImportProperties struct { // Optional name for the installed app. If unspecified, it is derived from the module name. Filename *string + + // If set, create package-export.apk, which other packages can + // use to get PRODUCT-agnostic resource data like IDs and type definitions. + Export_package_resources *bool } func (a *AndroidAppImport) IsInstallable() bool { @@ -142,13 +146,17 @@ func MergePropertiesFromVariant(ctx android.EarlyModuleContext, } } +func (a *AndroidAppImport) isPrebuiltFrameworkRes() bool { + return a.Name() == "prebuilt_framework-res" +} + func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { cert := android.SrcIsModule(String(a.properties.Certificate)) if cert != "" { ctx.AddDependency(ctx.Module(), certificateTag, cert) } - a.usesLibrary.deps(ctx, true) + a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes()) } func (a *AndroidAppImport) uncompressEmbeddedJniLibs( @@ -247,7 +255,12 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath) var installDir android.InstallPath - if Bool(a.properties.Privileged) { + + if a.isPrebuiltFrameworkRes() { + // framework-res.apk is installed as system/framework/framework-res.apk + installDir = android.PathForModuleInstall(ctx, "framework") + a.preprocessed = true + } else if Bool(a.properties.Privileged) { installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName()) } else if ctx.InstallInTestcases() { installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch()) @@ -275,7 +288,15 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // TODO: Handle EXTERNAL // Sign or align the package if package has not been preprocessed - if a.preprocessed { + + if a.isPrebuiltFrameworkRes() { + a.outputFile = srcApk + certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx) + if len(certificates) != 1 { + ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates) + } + a.certificate = certificates[0] + } else if a.preprocessed { a.outputFile = srcApk a.certificate = PresignedCertificate } else if !Bool(a.properties.Presigned) { diff --git a/java/app_import_test.go b/java/app_import_test.go index 344d23b55..d7f69eb36 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -393,6 +393,69 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) { } } +func TestAndroidAppImport_frameworkRes(t *testing.T) { + ctx, config := testJava(t, ` + android_app_import { + name: "framework-res", + certificate: "platform", + apk: "package-res.apk", + prefer: true, + export_package_resources: true, + // Disable dexpreopt and verify_uses_libraries check as the app + // contains no Java code to be dexpreopted. + enforce_uses_libs: false, + dex_preopt: { + enabled: false, + }, + } + `) + + mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module() + a := mod.(*AndroidAppImport) + + if !a.preprocessed { + t.Errorf("prebuilt framework-res is not preprocessed") + } + + expectedInstallPath := buildDir + "/target/product/test_device/system/framework/framework-res.apk" + + if a.dexpreopter.installPath.String() != expectedInstallPath { + t.Errorf("prebuilt framework-res installed to incorrect location, actual: %s, expected: %s", a.dexpreopter.installPath, expectedInstallPath) + + } + + entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] + + expectedPath := "." + // From apk property above, in the root of the source tree. + expectedPrebuiltModuleFile := "package-res.apk" + // Verify that the apk is preprocessed: The export package is the same + // as the prebuilt. + expectedSoongResourceExportPackage := expectedPrebuiltModuleFile + + actualPath := entries.EntryMap["LOCAL_PATH"] + actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"] + actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"] + + if len(actualPath) != 1 { + t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath)) + } else if actualPath[0] != expectedPath { + t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath) + } + + if len(actualPrebuiltModuleFile) != 1 { + t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile)) + } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile { + t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile) + } + + if len(actualSoongResourceExportPackage) != 1 { + t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage)) + } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage { + t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage) + } +} + func TestAndroidTestImport(t *testing.T) { ctx, config := testJava(t, ` android_test_import {