diff options
author | Sam Mortimer <sam@mortimer.me.uk> | 2019-10-07 11:41:14 -0700 |
---|---|---|
committer | Michael Bestas <mkbestas@lineageos.org> | 2019-12-11 19:03:43 +0200 |
commit | efa6a129b0954708e575069bef56fce1e234f0da (patch) | |
tree | b3d135cc5e3da7b5cc8f1886ce3765028367c796 | |
parent | 094c1b049a74506798c33d023a2a0df3506947c9 (diff) | |
download | build_soong-efa6a129b0954708e575069bef56fce1e234f0da.tar.gz build_soong-efa6a129b0954708e575069bef56fce1e234f0da.tar.bz2 build_soong-efa6a129b0954708e575069bef56fce1e234f0da.zip |
soong: Give priority to modules in exported namespaces for bootjars
* Looking for modules that provide a boot jar is currently
done by module name match only. This breaks when you
have multiple copies of the same module in your build
tree (eg in another device).
* Add a new mutator that marks the modules that should be used
for bootjar content.
* The logic is simple: give priority to modules that are in
exported soong namespace.
Change-Id: I2476174b892475c14a9f10b5e66b8496186f81c0
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | android/bootjar.go | 117 | ||||
-rw-r--r-- | android/module.go | 7 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 4 | ||||
-rw-r--r-- | java/dexpreopt_bootjars_test.go | 2 | ||||
-rw-r--r-- | java/hiddenapi.go | 9 |
6 files changed, 139 insertions, 1 deletions
@@ -44,6 +44,7 @@ bootstrap_go_package { "android/apex.go", "android/api_levels.go", "android/arch.go", + "android/bootjar.go", "android/config.go", "android/defaults.go", "android/defs.go", diff --git a/android/bootjar.go b/android/bootjar.go new file mode 100644 index 00000000..ea04dc8f --- /dev/null +++ b/android/bootjar.go @@ -0,0 +1,117 @@ +// Copyright (C) 2019 The LineageOS Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "strings" +) + +// Keys are bootjar name, value is whether or not +// we've marked a module as being a provider for it. +var jarMap map[string]bool + +func init() { + PreArchMutators(RegisterBootJarMutators) +} + +// Note: registration function is structured this way so that it can be included +// from soong module tests. +func RegisterBootJarMutators(ctx RegisterMutatorsContext) { + // Note: can't use Parallel() since we touch global jarMap + ctx.TopDown("bootjar_exportednamespace", bootJarMutatorExportedNamespace) + ctx.TopDown("bootjar_anynamespace", bootJarMutatorAnyNamespace) +} + +func mutatorInit(mctx TopDownMutatorContext) { + // Did we init already ? + if jarMap != nil { + return + } + + jarMap = make(map[string]bool) + for _, moduleName := range mctx.Config().BootJars() { + jarMap[moduleName] = false + } +} + +// Mark modules in soong exported namespace as providing a boot jar. +func bootJarMutatorExportedNamespace(mctx TopDownMutatorContext) { + bootJarMutator(mctx, true) +} + +// Mark modules in any namespace (incl root) as providing a boot jar. +func bootJarMutatorAnyNamespace(mctx TopDownMutatorContext) { + bootJarMutator(mctx, false) +} + +func bootJarMutator(mctx TopDownMutatorContext, requireExportedNamespace bool) { + mutatorInit(mctx) + + module, ok := mctx.Module().(Module) + if !ok { + // Not a proper module + return + } + + // Does this module produce a dex jar ? + if _, ok := module.(interface{ DexJar() Path }); !ok { + // No + return + } + + // If jarMap is empty we must be running in a test so + // set boot jar provide to true for all modules. + if len(jarMap) == 0 { + module.base().commonProperties.BootJarProvider = true + return + } + + name := mctx.ModuleName() + dir := mctx.ModuleDir() + + // Special treatment for hiddenapi modules - create extra + // jarMap entries if needed. + baseName := strings.TrimSuffix(name, "-hiddenapi") + if name != baseName { + _, baseIsBootJar := jarMap[baseName] + _, alreadyExists := jarMap[name] + if baseIsBootJar && !alreadyExists { + // This is a hidden api module whose base name exists in the boot jar list + // and we've not visited it before. Create a map entry for it. + jarMap[name] = false + } + } + + // Does this module match the name of a boot jar ? + if found, exists := jarMap[name]; !exists || found { + // No + return + } + + if requireExportedNamespace { + for _, n := range mctx.Config().ExportedNamespaces() { + if strings.HasPrefix(dir, n) { + jarMap[name] = true + module.base().commonProperties.BootJarProvider = true + break + } + } + } else { + jarMap[name] = true + module.base().commonProperties.BootJarProvider = true + } + + return +} diff --git a/android/module.go b/android/module.go index 495efbe1..17ddb050 100644 --- a/android/module.go +++ b/android/module.go @@ -304,6 +304,9 @@ type commonProperties struct { SkipInstall bool `blueprint:"mutated"` NamespaceExportedToMake bool `blueprint:"mutated"` + + // Whether this module provides a boot jar + BootJarProvider bool `blueprint:"mutated"` } type hostAndDeviceProperties struct { @@ -521,6 +524,10 @@ func (a *ModuleBase) Name() string { return String(a.nameProperties.Name) } +func (a *ModuleBase) BootJarProvider() bool { + return a.commonProperties.BootJarProvider +} + // BaseModuleName returns the name of the module as specified in the blueprints file. func (a *ModuleBase) BaseModuleName() string { return String(a.nameProperties.Name) diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 4d87b2f7..87d8428d 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -151,6 +151,10 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI bootDexJars := make(android.Paths, len(image.modules)) ctx.VisitAllModules(func(module android.Module) { + if m, ok := module.(interface{ BootJarProvider() bool }); !ok || + !m.BootJarProvider() { + return + } // Collect dex jar paths for the modules listed above. if j, ok := module.(interface{ DexJar() android.Path }); ok { name := ctx.ModuleName(module) diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index cbb52f15..d4f84914 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -53,6 +53,8 @@ func TestDexpreoptBootJars(t *testing.T) { ctx := testContext(config, bp, nil) + ctx.PreArchMutators(android.RegisterBootJarMutators) + ctx.RegisterSingletonType("dex_bootjars", android.SingletonFactoryAdaptor(dexpreoptBootJarsFactory)) run(t, ctx, config) diff --git a/java/hiddenapi.go b/java/hiddenapi.go index 6020aba6..28724f2a 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -73,7 +73,14 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOu // to the hidden API for the bootclassloader. If information is gathered for modules // not on the list then that will cause failures in the CtsHiddenApiBlacklist... // tests. - if inList(bootJarName, ctx.Config().BootJars()) { + isBootJarProvider := false + ctx.VisitAllModuleVariants(func(module android.Module) { + if m, ok := module.(interface{ BootJarProvider() bool }); ok && + m.BootJarProvider() { + isBootJarProvider = true + } + }) + if isBootJarProvider && inList(bootJarName, ctx.Config().BootJars()) { // Derive the greylist from classes jar. flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv") metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv") |