Loading android/apex.go +13 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,19 @@ func (i ApexInfo) InApex(apex string) bool { return false } // InApexByBaseName tells whether this apex variant of the module is part of the given APEX or not, // where the APEX is specified by its canonical base name, i.e. typically beginning with // "com.android.". In particular this function doesn't differentiate between source and prebuilt // APEXes, where the latter may have "prebuilt_" prefixes. func (i ApexInfo) InApexByBaseName(apex string) bool { for _, a := range i.InApexes { if RemoveOptionalPrebuiltPrefix(a) == apex { return true } } return false } // ApexTestForInfo stores the contents of APEXes for which this module is a test - although this // module is not part of the APEX - and thus has access to APEX internals. type ApexTestForInfo struct { Loading apex/apex_test.go +211 −1 Original line number Diff line number Diff line Loading @@ -4398,6 +4398,215 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { }) } func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { transform := func(config *dexpreopt.GlobalConfig) { config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"}) } checkBootDexJarPath := func(ctx *android.TestContext, bootDexJarPath string) { s := ctx.SingletonForTests("dex_bootjars") foundLibfooJar := false for _, output := range s.AllOutputs() { if strings.HasSuffix(output, "/libfoo.jar") { foundLibfooJar = true buildRule := s.Output(output) actual := android.NormalizePathForTesting(buildRule.Input) if actual != bootDexJarPath { t.Errorf("Incorrect boot dex jar path '%s', expected '%s'", actual, bootDexJarPath) } } } if !foundLibfooJar { t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs") } } t.Run("prebuilt only", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source library preferred", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` // In this test the source (java_library) libfoo is active since the // prebuilt (java_import) defaults to prefer:false. However the // prebuilt_apex module always depends on the prebuilt, and so it doesn't // find the dex boot jar in it. We either need to disable the source libfoo // or make the prebuilt libfoo preferred. testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", transform) }) t.Run("prebuilt library preferred with source", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", prefer: true, jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source apex preferred", func(t *testing.T) { bp := ` apex { name: "myapex", key: "myapex.key", java_libs: ["libfoo"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/libfoo/android_common_apex10000/aligned/libfoo.jar") }) t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) { bp := ` apex { name: "myapex", enabled: false, key: "myapex.key", java_libs: ["libfoo"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", prefer: true, jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) } func TestApexWithTests(t *testing.T) { ctx, config := testApex(t, ` apex_test { Loading Loading @@ -6002,6 +6211,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreopt "build/make/target/product/security": nil, "apex_manifest.json": nil, "AndroidManifest.xml": nil, "system/sepolicy/apex/myapex-file_contexts": nil, "system/sepolicy/apex/some-updatable-apex-file_contexts": nil, "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil, "system/sepolicy/apex/com.android.art.debug-file_contexts": nil, Loading java/boot_jars.go +30 −4 Original line number Diff line number Diff line Loading @@ -49,14 +49,36 @@ func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex return true } // isActiveModule returns true if the given module should be considered for boot // jars, i.e. if it's enabled and the preferred one in case of source and // prebuilt alternatives. func isActiveModule(module android.Module) bool { if !module.Enabled() { return false } if module.IsReplacedByPrebuilt() { // A source module that has been replaced by a prebuilt counterpart. return false } if prebuilt, ok := module.(android.PrebuiltInterface); ok { if p := prebuilt.Prebuilt(); p != nil { return p.UsePrebuilt() } } return true } func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) { config := ctx.Config() if config.SkipBootJarsCheck() { return } // Populate a map from module name to APEX from the boot jars. If there is a problem // such as duplicate modules then fail and return immediately. // Populate a map from module name to APEX from the boot jars. If there is a // problem such as duplicate modules then fail and return immediately. Note // that both module and APEX names are tracked by base names here, so we need // to be careful to remove "prebuilt_" prefixes when comparing them with // actual modules and APEX bundles. moduleToApex := make(map[string]string) if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") || !populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") { Loading @@ -69,10 +91,14 @@ func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) { // Scan all the modules looking for the module/apex variants corresponding to the // boot jars. ctx.VisitAllModules(func(module android.Module) { name := ctx.ModuleName(module) if !isActiveModule(module) { return } name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module)) if apex, ok := moduleToApex[name]; ok { apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApex(apex) { if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexByBaseName(apex) { // The module name/apex variant should be unique in the system but double check // just in case something has gone wrong. if existing, ok := nameToApexVariant[name]; ok { Loading java/dexpreopt_bootjars.go +10 −11 Original line number Diff line number Diff line Loading @@ -486,7 +486,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul // A platform variant is required but this is for an apex so ignore it. return -1, nil } } else if !android.InList(requiredApex, apexInfo.InApexes) { } else if !apexInfo.InApexByBaseName(requiredApex) { // An apex variant for a specific apex is required but this is the wrong apex. return -1, nil } Loading @@ -496,7 +496,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul switch image.name { case artBootImageName: if len(apexInfo.InApexes) > 0 && allHavePrefix(apexInfo.InApexes, "com.android.art") { if apexInfo.InApexByBaseName("com.android.art") || apexInfo.InApexByBaseName("com.android.art.debug") || apexInfo.InApexByBaseName("com.android.art,testing") { // ok: found the jar in the ART apex } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { // exception (skip and continue): Jacoco platform variant for a coverage build Loading @@ -523,21 +523,17 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul return index, jar.DexJarBuildPath() } func allHavePrefix(list []string, prefix string) bool { for _, s := range list { if s != prefix && !strings.HasPrefix(s, prefix+".") { return false } } return true } // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image. func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig { // Collect dex jar paths for the boot image modules. // This logic is tested in the apex package to avoid import cycle apex <-> java. bootDexJars := make(android.Paths, image.modules.Len()) ctx.VisitAllModules(func(module android.Module) { if !isActiveModule(module) { return } if i, j := getBootImageJar(ctx, image, module); i != -1 { if existing := bootDexJars[i]; existing != nil { ctx.Errorf("Multiple dex jars found for %s:%s - %s and %s", Loading Loading @@ -867,6 +863,9 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string ctx.VisitAllModules(func(module android.Module) { if !isActiveModule(module) { return } if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok { name := ctx.ModuleName(module) if i := android.IndexList(name, updatableModules); i != -1 { Loading Loading
android/apex.go +13 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,19 @@ func (i ApexInfo) InApex(apex string) bool { return false } // InApexByBaseName tells whether this apex variant of the module is part of the given APEX or not, // where the APEX is specified by its canonical base name, i.e. typically beginning with // "com.android.". In particular this function doesn't differentiate between source and prebuilt // APEXes, where the latter may have "prebuilt_" prefixes. func (i ApexInfo) InApexByBaseName(apex string) bool { for _, a := range i.InApexes { if RemoveOptionalPrebuiltPrefix(a) == apex { return true } } return false } // ApexTestForInfo stores the contents of APEXes for which this module is a test - although this // module is not part of the APEX - and thus has access to APEX internals. type ApexTestForInfo struct { Loading
apex/apex_test.go +211 −1 Original line number Diff line number Diff line Loading @@ -4398,6 +4398,215 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { }) } func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { transform := func(config *dexpreopt.GlobalConfig) { config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"}) } checkBootDexJarPath := func(ctx *android.TestContext, bootDexJarPath string) { s := ctx.SingletonForTests("dex_bootjars") foundLibfooJar := false for _, output := range s.AllOutputs() { if strings.HasSuffix(output, "/libfoo.jar") { foundLibfooJar = true buildRule := s.Output(output) actual := android.NormalizePathForTesting(buildRule.Input) if actual != bootDexJarPath { t.Errorf("Incorrect boot dex jar path '%s', expected '%s'", actual, bootDexJarPath) } } } if !foundLibfooJar { t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs") } } t.Run("prebuilt only", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source library preferred", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` // In this test the source (java_library) libfoo is active since the // prebuilt (java_import) defaults to prefer:false. However the // prebuilt_apex module always depends on the prebuilt, and so it doesn't // find the dex boot jar in it. We either need to disable the source libfoo // or make the prebuilt libfoo preferred. testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", transform) }) t.Run("prebuilt library preferred with source", func(t *testing.T) { bp := ` prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", prefer: true, jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source apex preferred", func(t *testing.T) { bp := ` apex { name: "myapex", key: "myapex.key", java_libs: ["libfoo"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/libfoo/android_common_apex10000/aligned/libfoo.jar") }) t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) { bp := ` apex { name: "myapex", enabled: false, key: "myapex.key", java_libs: ["libfoo"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } prebuilt_apex { name: "myapex", arch: { arm64: { src: "myapex-arm64.apex", }, arm: { src: "myapex-arm.apex", }, }, exported_java_libs: ["libfoo"], } java_import { name: "libfoo", prefer: true, jars: ["libfoo.jar"], apex_available: ["myapex"], } java_library { name: "libfoo", srcs: ["foo/bar/MyClass.java"], apex_available: ["myapex"], } ` ctx := testDexpreoptWithApexes(t, bp, "", transform) checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) } func TestApexWithTests(t *testing.T) { ctx, config := testApex(t, ` apex_test { Loading Loading @@ -6002,6 +6211,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreopt "build/make/target/product/security": nil, "apex_manifest.json": nil, "AndroidManifest.xml": nil, "system/sepolicy/apex/myapex-file_contexts": nil, "system/sepolicy/apex/some-updatable-apex-file_contexts": nil, "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil, "system/sepolicy/apex/com.android.art.debug-file_contexts": nil, Loading
java/boot_jars.go +30 −4 Original line number Diff line number Diff line Loading @@ -49,14 +49,36 @@ func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex return true } // isActiveModule returns true if the given module should be considered for boot // jars, i.e. if it's enabled and the preferred one in case of source and // prebuilt alternatives. func isActiveModule(module android.Module) bool { if !module.Enabled() { return false } if module.IsReplacedByPrebuilt() { // A source module that has been replaced by a prebuilt counterpart. return false } if prebuilt, ok := module.(android.PrebuiltInterface); ok { if p := prebuilt.Prebuilt(); p != nil { return p.UsePrebuilt() } } return true } func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) { config := ctx.Config() if config.SkipBootJarsCheck() { return } // Populate a map from module name to APEX from the boot jars. If there is a problem // such as duplicate modules then fail and return immediately. // Populate a map from module name to APEX from the boot jars. If there is a // problem such as duplicate modules then fail and return immediately. Note // that both module and APEX names are tracked by base names here, so we need // to be careful to remove "prebuilt_" prefixes when comparing them with // actual modules and APEX bundles. moduleToApex := make(map[string]string) if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") || !populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") { Loading @@ -69,10 +91,14 @@ func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) { // Scan all the modules looking for the module/apex variants corresponding to the // boot jars. ctx.VisitAllModules(func(module android.Module) { name := ctx.ModuleName(module) if !isActiveModule(module) { return } name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module)) if apex, ok := moduleToApex[name]; ok { apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApex(apex) { if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexByBaseName(apex) { // The module name/apex variant should be unique in the system but double check // just in case something has gone wrong. if existing, ok := nameToApexVariant[name]; ok { Loading
java/dexpreopt_bootjars.go +10 −11 Original line number Diff line number Diff line Loading @@ -486,7 +486,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul // A platform variant is required but this is for an apex so ignore it. return -1, nil } } else if !android.InList(requiredApex, apexInfo.InApexes) { } else if !apexInfo.InApexByBaseName(requiredApex) { // An apex variant for a specific apex is required but this is the wrong apex. return -1, nil } Loading @@ -496,7 +496,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul switch image.name { case artBootImageName: if len(apexInfo.InApexes) > 0 && allHavePrefix(apexInfo.InApexes, "com.android.art") { if apexInfo.InApexByBaseName("com.android.art") || apexInfo.InApexByBaseName("com.android.art.debug") || apexInfo.InApexByBaseName("com.android.art,testing") { // ok: found the jar in the ART apex } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { // exception (skip and continue): Jacoco platform variant for a coverage build Loading @@ -523,21 +523,17 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul return index, jar.DexJarBuildPath() } func allHavePrefix(list []string, prefix string) bool { for _, s := range list { if s != prefix && !strings.HasPrefix(s, prefix+".") { return false } } return true } // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image. func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig { // Collect dex jar paths for the boot image modules. // This logic is tested in the apex package to avoid import cycle apex <-> java. bootDexJars := make(android.Paths, image.modules.Len()) ctx.VisitAllModules(func(module android.Module) { if !isActiveModule(module) { return } if i, j := getBootImageJar(ctx, image, module); i != -1 { if existing := bootDexJars[i]; existing != nil { ctx.Errorf("Multiple dex jars found for %s:%s - %s and %s", Loading Loading @@ -867,6 +863,9 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string ctx.VisitAllModules(func(module android.Module) { if !isActiveModule(module) { return } if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok { name := ctx.ModuleName(module) if i := android.IndexList(name, updatableModules); i != -1 { Loading