summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/apex.go46
-rw-r--r--apex/apex.go10
-rw-r--r--apex/apex_test.go152
3 files changed, 206 insertions, 2 deletions
diff --git a/android/apex.go b/android/apex.go
index 99b13ab72..557febfc9 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -78,12 +78,23 @@ type ApexModule interface {
// Return the no_apex property
NoApex() bool
+
+ // Tests if this module is available for the specified APEX or ":platform"
+ AvailableFor(what string) bool
}
type ApexProperties struct {
// Whether this module should not be part of any APEX. Default is false.
+ // TODO(b/128708192): remove this as this is equal to apex_available: [":platform"]
No_apex *bool
+ // Availability of this module in APEXes. Only the listed APEXes can include this module.
+ // "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
+ // "//apex_available:platform" refers to non-APEX partitions like "system.img".
+ // Default is ["//apex_available:platform", "//apex_available:anyapex"].
+ // TODO(b/128708192) change the default to ["//apex_available:platform"]
+ Apex_available []string
+
// Name of the apex variant that this module is mutated into
ApexName string `blueprint:"mutated"`
}
@@ -136,15 +147,46 @@ func (m *ApexModuleBase) NoApex() bool {
return proptools.Bool(m.ApexProperties.No_apex)
}
+const (
+ availableToPlatform = "//apex_available:platform"
+ availableToAnyApex = "//apex_available:anyapex"
+)
+
+func (m *ApexModuleBase) AvailableFor(what string) bool {
+ if len(m.ApexProperties.Apex_available) == 0 {
+ // apex_available defaults to ["//apex_available:platform", "//apex_available:anyapex"],
+ // which means 'available to everybody'.
+ return true
+ }
+ return InList(what, m.ApexProperties.Apex_available) ||
+ (what != availableToPlatform && InList(availableToAnyApex, m.ApexProperties.Apex_available))
+}
+
+func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
+ for _, n := range m.ApexProperties.Apex_available {
+ if n == availableToPlatform || n == availableToAnyApex {
+ continue
+ }
+ if !mctx.OtherModuleExists(n) {
+ mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
+ }
+ }
+}
+
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
if len(m.apexVariations) > 0 {
+ m.checkApexAvailableProperty(mctx)
sort.Strings(m.apexVariations)
- variations := []string{""} // Original variation for platform
+ variations := []string{}
+ availableForPlatform := m.AvailableFor(availableToPlatform)
+ if availableForPlatform {
+ variations = append(variations, "") // Original variation for platform
+ }
variations = append(variations, m.apexVariations...)
modules := mctx.CreateVariations(variations...)
for i, m := range modules {
- if i == 0 {
+ if availableForPlatform && i == 0 {
continue
}
m.(ApexModule).setApexName(variations[i])
diff --git a/apex/apex.go b/apex/apex.go
index 220eb0043..aff8d50b6 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1215,6 +1215,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
+ // check apex_available requirements
+ for _, fi := range filesInfo {
+ if am, ok := fi.module.(android.ApexModule); ok {
+ if !am.AvailableFor(ctx.ModuleName()) {
+ ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
+ return
+ }
+ }
+ }
+
// prepend the name of this APEX to the module names. These names will be the names of
// modules that will be defined if the APEX is flattened.
for i := range filesInfo {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 114d89ff9..ecfa46fa5 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2422,6 +2422,158 @@ func TestApexWithApps(t *testing.T) {
}
+func TestApexAvailable(t *testing.T) {
+ // libfoo is not available to myapex, but only to otherapex
+ testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ // libbar is an indirect dep
+ testApexError(t, "requires \"libbar\" that is not available for the APEX", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["myapex", "otherapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ testApexError(t, "\"otherapex\" is not a valid module name", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo", "libbar"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["//apex_available:anyapex"],
+ }`)
+
+ // check that libfoo and libbar are created only for myapex, but not for the platform
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared")
+
+ ctx, _ = testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["//apex_available:platform"],
+ }`)
+
+ // check that libfoo is created only for the platform
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()