summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Mortimer <sam@mortimer.me.uk>2019-10-07 11:41:14 -0700
committerMichael Bestas <mkbestas@lineageos.org>2020-12-08 22:28:30 +0200
commitddf5458d148e20b325182f1ee7d80ab8aed86e2d (patch)
treefc765e3a43d63eab23435deda5ae6ed956ff36ba
parent90783142d5e53e22fead18d736a64e54e05bcd82 (diff)
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/Android.bp1
-rw-r--r--android/bootjar.go117
-rw-r--r--android/module.go7
-rw-r--r--apex/apex_test.go3
-rw-r--r--java/dexpreopt_bootjars.go4
-rw-r--r--java/dexpreopt_bootjars_test.go2
-rw-r--r--java/hiddenapi.go9
7 files changed, 142 insertions, 1 deletions
diff --git a/android/Android.bp b/android/Android.bp
index e0664a13c..e0cf40243 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@ bootstrap_go_package {
"apex.go",
"api_levels.go",
"arch.go",
+ "bootjar.go",
"config.go",
"csuite_config.go",
"defaults.go",
diff --git a/android/bootjar.go b/android/bootjar.go
new file mode 100644
index 000000000..ea04dc8f4
--- /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 285702965..35eb17535 100644
--- a/android/module.go
+++ b/android/module.go
@@ -530,6 +530,9 @@ type commonProperties struct {
// set by ImageMutator
ImageVariation string `blueprint:"mutated"`
+
+ // Whether this module provides a boot jar
+ BootJarProvider bool `blueprint:"mutated"`
}
type hostAndDeviceProperties struct {
@@ -795,6 +798,10 @@ func (m *ModuleBase) String() string {
return sb.String()
}
+func (a *ModuleBase) BootJarProvider() bool {
+ return a.commonProperties.BootJarProvider
+}
+
// BaseModuleName returns the name of the module as specified in the blueprints file.
func (m *ModuleBase) BaseModuleName() string {
return String(m.nameProperties.Name)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index fe2de4754..ebe8cfbf5 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -199,6 +199,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
// from android package
android.RegisterPackageBuildComponents(ctx)
+ ctx.PreArchMutators(android.RegisterBootJarMutators)
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
ctx.RegisterModuleType("apex", BundleFactory)
@@ -4704,6 +4705,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg, bp string, transformDe
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+ ctx.PreArchMutators(android.RegisterBootJarMutators)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterJavaBuildComponents(ctx)
@@ -4914,6 +4916,7 @@ func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, apexBootJar
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+ ctx.PreArchMutators(android.RegisterBootJarMutators)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterJavaBuildComponents(ctx)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index e0609a035..d40d72e09 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -310,6 +310,10 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
// This logic is tested in the apex package to avoid import cycle apex <-> java.
bootDexJars := make(android.Paths, len(image.modules))
ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(interface{ BootJarProvider() bool }); !ok ||
+ !m.BootJarProvider() {
+ return
+ }
if i, j := getBootImageJar(ctx, image, module); i != -1 {
bootDexJars[i] = j
}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index e7b3c3ba9..b685e9b3f 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -53,6 +53,8 @@ func TestDexpreoptBootJars(t *testing.T) {
ctx := testContext()
+ ctx.PreArchMutators(android.RegisterBootJarMutators)
+
RegisterDexpreoptBootJarsComponents(ctx)
run(t, ctx, config)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index b5a021785..36ac0619f 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -77,7 +77,14 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bo
// 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")