summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Colin Cross <ccross@android.com> 2024-12-03 16:40:08 -0800
committer Colin Cross <ccross@android.com> 2025-02-10 19:55:26 -0800
commit1cea5308a7915665d8d3480021ca2da00f5206eb (patch)
tree67c5a61b9257166cced772791550e28db4487b5e
parent92b0eb18e199f44ddc26b32ae993d9909f1fd7fa (diff)
Convert android.TransitionMutator to TransitionInfo
Use the ApexInfo instead of a string as the TransitionInfo for apex variations. This removes the need for apexInfoMutator, which is the last remaining top down mutator. This has a variety of ramifications. One is that it is no longer possible to add a dependency onto the apex variation of a module, as that would require constructing a matching ApexInfo. Instead, anything that wants to add a dependency on the apex variation has to depend on the apex instead, and get to the module by walking its transistive dependencies. Another ramification is that modules in apexes can no longer determine which apexes they are in (unless they set UniqueApexVariations so that each variation is in exactly one apex). This prevents some of the existing container violation checks from working after this CL, tracked in b/394955484. It also requires using unique variation names for the prebuilt and source dependencies of apexes, so the apex variations for dependencies of prebuilts now have a prebuilt_ prefix. Bug: 372543712 Bug: 394955484 Test: go test ./... Change-Id: I3d08aca1ac956ab0e343ec3f235a736cd93be0e1
-rw-r--r--android/Android.bp1
-rw-r--r--android/apex.go315
-rw-r--r--android/apex_test.go277
-rw-r--r--android/api_levels.go6
-rw-r--r--android/container.go14
-rw-r--r--android/deapexer.go2
-rw-r--r--apex/apex.go168
-rw-r--r--apex/apex_test.go94
-rw-r--r--apex/bootclasspath_fragment_test.go7
-rw-r--r--apex/builder.go2
-rw-r--r--apex/container_test.go3
-rw-r--r--apex/dexpreopt_bootjars_test.go6
-rw-r--r--apex/platform_bootclasspath_test.go32
-rw-r--r--apex/prebuilt.go121
-rw-r--r--apex/systemserver_classpath_fragment_test.go12
-rw-r--r--cc/cc.go4
-rw-r--r--java/bootclasspath_fragment.go12
-rw-r--r--java/dexpreopt.go3
-rw-r--r--java/hiddenapi_singleton.go4
-rw-r--r--java/java.go1
-rw-r--r--java/platform_bootclasspath.go2
-rw-r--r--java/systemserver_classpath_fragment.go1
-rw-r--r--java/testing.go53
-rw-r--r--rust/rust.go3
-rw-r--r--sdk/bootclasspath_fragment_sdk_test.go5
-rw-r--r--sdk/testing.go7
26 files changed, 344 insertions, 811 deletions
diff --git a/android/Android.bp b/android/Android.bp
index d27a8facf..babc91341 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -125,7 +125,6 @@ bootstrap_go_package {
"all_teams_test.go",
"android_test.go",
"androidmk_test.go",
- "apex_test.go",
"arch_test.go",
"blueprint_e2e_test.go",
"build_prop_test.go",
diff --git a/android/apex.go b/android/apex.go
index 4917149dd..68d0ce8a2 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -17,7 +17,6 @@ package android
import (
"fmt"
"slices"
- "sort"
"strconv"
"strings"
"sync"
@@ -55,18 +54,30 @@ type ApexInfo struct {
// to true.
UsePlatformApis bool
- // List of Apex variant names that this module is associated with. This initially is the
- // same as the `ApexVariationName` field. Then when multiple apex variants are merged in
- // mergeApexVariations, ApexInfo struct of the merged variant holds the list of apexBundles
- // that are merged together.
- InApexVariants []string
-
// True if this is for a prebuilt_apex.
//
// If true then this will customize the apex processing to make it suitable for handling
// prebuilt_apex, e.g. it will prevent ApexInfos from being merged together.
//
- // See Prebuilt.ApexInfoMutator for more information.
+ // Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
+ // across prebuilt_apex modules. That is because there is no way to determine whether two
+ // prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
+ // been built from different source at different times or they could have been built with different
+ // build options that affect the libraries.
+ //
+ // While it may be possible to provide sufficient information to determine whether two prebuilt_apex
+ // modules were compatible it would be a lot of work and would not provide much benefit for a couple
+ // of reasons:
+ // - The number of prebuilt_apex modules that will be exporting files for the same module will be
+ // low as the prebuilt_apex only exports files for the direct dependencies that require it and
+ // very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
+ // few com.android.art* apex files that contain the same contents and could export files for the
+ // same modules but only one of them needs to do so. Contrast that with source apex modules which
+ // need apex specific variants for every module that contributes code to the apex, whether direct
+ // or indirect.
+ // - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
+ // extra copying of files. Contrast that with source apex modules that has to build each variant
+ // from source.
ForPrebuiltApex bool
// Returns the name of the overridden apex (com.android.foo)
@@ -74,24 +85,36 @@ type ApexInfo struct {
// Returns the value of `apex_available_name`
ApexAvailableName string
+}
- // Returns the apex names that this module is available for
- ApexAvailableFor []string
+func (a ApexInfo) Variation() string {
+ return a.ApexVariationName
}
-// AllApexInfo holds the ApexInfo of all apexes that include this module.
-type AllApexInfo struct {
- ApexInfos []ApexInfo
+// Minimize is called during a transition from a module with a unique variation per apex to a module that should
+// share variations between apexes. It returns a minimized ApexInfo that removes any apex names and replaces
+// the variation name with one computed from the remaining properties.
+func (a ApexInfo) Minimize() ApexInfo {
+ info := ApexInfo{
+ MinSdkVersion: a.MinSdkVersion,
+ UsePlatformApis: a.UsePlatformApis,
+ }
+ info.ApexVariationName = info.mergedName()
+ return info
+}
+
+type ApexAvailableInfo struct {
+ // Returns the apex names that this module is available for
+ ApexAvailableFor []string
}
var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex_mutate")
-var AllApexInfoProvider = blueprint.NewMutatorProvider[*AllApexInfo]("apex_info")
+var ApexAvailableInfoProvider = blueprint.NewMutatorProvider[ApexAvailableInfo]("apex_mutate")
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
(*d)["Apex"] = map[string]interface{}{
"ApexVariationName": i.ApexVariationName,
"MinSdkVersion": i.MinSdkVersion,
- "InApexVariants": i.InApexVariants,
"ForPrebuiltApex": i.ForPrebuiltApex,
}
}
@@ -117,32 +140,20 @@ func (i ApexInfo) IsForPlatform() bool {
return i.ApexVariationName == ""
}
-// InApexVariant tells whether this apex variant of the module is part of the given apexVariant or
-// not.
-func (i ApexInfo) InApexVariant(apexVariant string) bool {
- for _, a := range i.InApexVariants {
- if a == apexVariant {
- return true
- }
- }
- return false
-}
-
// To satisfy the comparable interface
func (i ApexInfo) Equal(other any) bool {
otherApexInfo, ok := other.(ApexInfo)
return ok && i.ApexVariationName == otherApexInfo.ApexVariationName &&
i.MinSdkVersion == otherApexInfo.MinSdkVersion &&
i.Updatable == otherApexInfo.Updatable &&
- i.UsePlatformApis == otherApexInfo.UsePlatformApis &&
- slices.Equal(i.InApexVariants, otherApexInfo.InApexVariants)
+ i.UsePlatformApis == otherApexInfo.UsePlatformApis
}
// ApexBundleInfo contains information about the dependencies of an apex
type ApexBundleInfo struct {
}
-var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info")
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_mutate")
// DepIsInSameApex defines an interface that should be used to determine whether a given dependency
// should be considered as part of the same APEX as the current module or not. Note: this was
@@ -315,6 +326,61 @@ type ApexModuleBase struct {
apexInfosLock sync.Mutex // protects apexInfos during parallel apexInfoMutator
}
+func (m *ApexModuleBase) ApexTransitionMutatorSplit(ctx BaseModuleContext) []ApexInfo {
+ return []ApexInfo{{}}
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorOutgoing(ctx OutgoingTransitionContext, info ApexInfo) ApexInfo {
+ if !ctx.Module().(DepIsInSameApex).OutgoingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorIncoming(ctx IncomingTransitionContext, info ApexInfo) ApexInfo {
+ module := ctx.Module().(ApexModule)
+ if !module.CanHaveApexVariants() {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(DepIsInSameApex).IncomingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+
+ if info.ApexVariationName == "" {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps && !info.ForPrebuiltApex {
+ return info.Minimize()
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorMutate(ctx BottomUpMutatorContext, info ApexInfo) {
+ SetProvider(ctx, ApexInfoProvider, info)
+
+ module := ctx.Module().(ApexModule)
+ base := module.apexModuleBase()
+
+ platformVariation := info.ApexVariationName == ""
+ if !platformVariation {
+ // Do some validity checks.
+ // TODO(jiyong): is this the right place?
+ base.checkApexAvailableProperty(ctx)
+
+ SetProvider(ctx, ApexAvailableInfoProvider, ApexAvailableInfo{
+ ApexAvailableFor: module.ApexAvailableFor(),
+ })
+ }
+ if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
+ // Do not install the module for platform, but still allow it to output
+ // uninstallable AndroidMk entries in certain cases when they have side
+ // effects. TODO(jiyong): move this routine to somewhere else
+ module.MakeUninstallable()
+ }
+}
+
// Initializes ApexModuleBase struct. Not calling this (even when inheriting from ApexModuleBase)
// prevents the module from being mutated for apexBundle.
func InitApexModule(m ApexModule) {
@@ -514,195 +580,14 @@ func AvailableToSameApexes(mod1, mod2 ApexModule) bool {
return true
}
-// mergeApexVariations deduplicates apex variations that would build identically into a common
-// variation. It returns the reduced list of variations and a list of aliases from the original
-// variation names to the new variation names.
-func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
- seen := make(map[string]int)
- for _, apexInfo := range apexInfos {
- // If this is for a prebuilt apex then use the actual name of the apex variation to prevent this
- // from being merged with other ApexInfo. See Prebuilt.ApexInfoMutator for more information.
- if apexInfo.ForPrebuiltApex {
- merged = append(merged, apexInfo)
- continue
- }
-
- // Merge the ApexInfo together. If a compatible ApexInfo exists then merge the information from
- // this one into it, otherwise create a new merged ApexInfo from this one and save it away so
- // other ApexInfo instances can be merged into it.
- variantName := apexInfo.ApexVariationName
- mergedName := apexInfo.mergedName()
- if index, exists := seen[mergedName]; exists {
- // Variants having the same mergedName are deduped
- merged[index].InApexVariants = append(merged[index].InApexVariants, variantName)
- merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
- // Platform APIs is allowed for this module only when all APEXes containing
- // the module are with `use_platform_apis: true`.
- merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
- } else {
- seen[mergedName] = len(merged)
- apexInfo.ApexVariationName = mergedName
- apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
- merged = append(merged, apexInfo)
- }
- aliases = append(aliases, [2]string{variantName, mergedName})
- }
- return merged, aliases
-}
-
-// IncomingApexTransition is called by apexTransitionMutator.IncomingTransition on modules that can be in apexes.
-// The incomingVariation can be either the name of an apex if the dependency is coming directly from an apex
-// module, or it can be the name of an apex variation (e.g. apex10000) if it is coming from another module that
-// is in the apex.
-func IncomingApexTransition(ctx IncomingTransitionContext, incomingVariation string) string {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- // Dependencies from platform variations go to the platform variation.
- if incomingVariation == "" {
- return ""
- }
-
- if len(apexInfos) == 0 {
- if ctx.IsAddingDependency() {
- // If this module has no apex variations we can't do any mapping on the incoming variation, just return it
- // and let the caller get a "missing variant" error.
- return incomingVariation
- } else {
- // If this module has no apex variations the use the platform variation.
- return ""
- }
- }
-
- // Convert the list of apex infos into from the AllApexInfoProvider into the merged list
- // of apex variations and the aliases from apex names to apex variations.
- var aliases [][2]string
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, aliases = mergeApexVariations(apexInfos)
- }
-
- // Check if the incoming variation matches an apex name, and if so use the corresponding
- // apex variation.
- aliasIndex := slices.IndexFunc(aliases, func(alias [2]string) bool {
- return alias[0] == incomingVariation
- })
- if aliasIndex >= 0 {
- return aliases[aliasIndex][1]
- }
-
- // Check if the incoming variation matches an apex variation.
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == incomingVariation
- })
- if apexIndex >= 0 {
- return incomingVariation
- }
-
- return ""
-}
-
-func MutateApexTransition(ctx BaseModuleContext, variation string) {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
- platformVariation := variation == ""
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
- // Do not install the module for platform, but still allow it to output
- // uninstallable AndroidMk entries in certain cases when they have side
- // effects. TODO(jiyong): move this routine to somewhere else
- module.MakeUninstallable()
- }
-
- // Do some validity checks.
- // TODO(jiyong): is this the right place?
- base.checkApexAvailableProperty(ctx)
-
- // Shortcut
- if len(apexInfos) == 0 {
- return
- }
-
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, _ = mergeApexVariations(apexInfos)
- }
-
- if !platformVariation {
- var thisApexInfo ApexInfo
-
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == variation
- })
- if apexIndex >= 0 {
- thisApexInfo = apexInfos[apexIndex]
- } else {
- panic(fmt.Errorf("failed to find apexInfo for incoming variation %q", variation))
- }
- thisApexInfo.ApexAvailableFor = module.ApexAvailableFor()
-
- SetProvider(ctx, ApexInfoProvider, thisApexInfo)
- }
-}
-
-func ApexInfoMutator(ctx TopDownMutatorContext, module ApexModule) {
- base := module.apexModuleBase()
- if len(base.apexInfos) > 0 {
- apexInfos := slices.Clone(base.apexInfos)
- slices.SortFunc(apexInfos, func(a, b ApexInfo) int {
- return strings.Compare(a.ApexVariationName, b.ApexVariationName)
- })
- SetProvider(ctx, AllApexInfoProvider, &AllApexInfo{apexInfos})
- // base.apexInfos is only needed to propagate the list of apexes from the apex module to its
- // contents within apexInfoMutator. Clear it so it doesn't accidentally get used later.
- base.apexInfos = nil
- }
-}
-
// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies that are
// in the same APEX have unique APEX variations so that the module can link against the right
// variant.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
- // anyInSameApex returns true if the two ApexInfo lists contain any values in an
- // InApexVariants list in common. It is used instead of OutgoingDepIsInSameApex because it needs to
- // determine if the dep is in the same APEX due to being directly included, not only if it
- // is included _because_ it is a dependency.
- anyInSameApex := func(a, b ApexModule) bool {
- collectApexes := func(m ApexModule) []string {
- if allApexInfo, ok := OtherModuleProvider(mctx, m, AllApexInfoProvider); ok {
- var ret []string
- for _, info := range allApexInfo.ApexInfos {
- ret = append(ret, info.InApexVariants...)
- }
- return ret
- }
- return nil
- }
-
- aApexes := collectApexes(a)
- bApexes := collectApexes(b)
- sort.Strings(bApexes)
- for _, aApex := range aApexes {
- index := sort.SearchStrings(bApexes, aApex)
- if index < len(bApexes) && bApexes[index] == aApex {
- return true
- }
- }
- return false
- }
-
// If any of the dependencies requires unique apex variations, so does this module.
mctx.VisitDirectDeps(func(dep Module) {
if depApexModule, ok := dep.(ApexModule); ok {
- if anyInSameApex(depApexModule, am) &&
+ if IsDepInSameApex(mctx, am, depApexModule) &&
(depApexModule.UniqueApexVariations() ||
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
@@ -849,8 +734,14 @@ func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayl
})
}
+type MinSdkVersionFromValueContext interface {
+ Config() Config
+ DeviceConfig() DeviceConfig
+ ModuleErrorContext
+}
+
// Construct ApiLevel object from min_sdk_version string value
-func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
+func MinSdkVersionFromValue(ctx MinSdkVersionFromValueContext, value string) ApiLevel {
if value == "" {
return NoneApiLevel
}
diff --git a/android/apex_test.go b/android/apex_test.go
deleted file mode 100644
index acc195de2..000000000
--- a/android/apex_test.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// 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 (
- "reflect"
- "testing"
-)
-
-func Test_mergeApexVariations(t *testing.T) {
- const (
- ForPrebuiltApex = true
- NotForPrebuiltApex = false
- )
- tests := []struct {
- name string
- in []ApexInfo
- wantMerged []ApexInfo
- wantAliases [][2]string
- }{
- {
- name: "single",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- },
- },
- {
- name: "merge",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo", "bar"},
- }},
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge version",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "apex30",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex30"},
- },
- },
- {
- name: "merge updatable",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge when for prebuilt_apex",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- // This one should not be merged in with the others because it is for
- // a prebuilt_apex.
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge different UsePlatformApis",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "apex10000_p",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000_p"},
- },
- },
- {
- name: "merge same UsePlatformApis and allow using platform api",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000_p",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000_p"},
- {"bar", "apex10000_p"},
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- gotMerged, gotAliases := mergeApexVariations(tt.in)
- if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
- t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
- }
- if !reflect.DeepEqual(gotAliases, tt.wantAliases) {
- t.Errorf("mergeApexVariations() gotAliases = %v, want %v", gotAliases, tt.wantAliases)
- }
- })
- }
-}
diff --git a/android/api_levels.go b/android/api_levels.go
index 2b1d01d8b..b4fa251bc 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -311,7 +311,7 @@ func ReplaceFinalizedCodenames(config Config, raw string) (string, error) {
// ApiLevelFrom converts the given string `raw` to an ApiLevel.
// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
-func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
+func ApiLevelFrom(ctx ConfigContext, raw string) ApiLevel {
ret, err := ApiLevelFromUser(ctx, raw)
if err != nil {
return NewInvalidApiLevel(raw)
@@ -333,7 +333,7 @@ func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
//
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
-func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
+func ApiLevelFromUser(ctx ConfigContext, raw string) (ApiLevel, error) {
return ApiLevelFromUserWithConfig(ctx.Config(), raw)
}
@@ -413,7 +413,7 @@ func ApiLevelForTest(raw string) ApiLevel {
// Converts an API level string `raw` into an ApiLevel in the same method as
// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors
// will panic instead of returning an error.
-func ApiLevelOrPanic(ctx PathContext, raw string) ApiLevel {
+func ApiLevelOrPanic(ctx ConfigContext, raw string) ApiLevel {
value, err := ApiLevelFromUser(ctx, raw)
if err != nil {
panic(err.Error())
diff --git a/android/container.go b/android/container.go
index eb2fc1874..5dc97d38e 100644
--- a/android/container.go
+++ b/android/container.go
@@ -167,8 +167,8 @@ var productContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext
}
var apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
- _, ok := ModuleProvider(mctx, AllApexInfoProvider)
- return ok
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ return false
}
var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
@@ -380,7 +380,7 @@ func (c *ContainersInfo) BelongingContainers() []*container {
func (c *ContainersInfo) ApexNames() (ret []string) {
for _, apex := range c.belongingApexes {
- ret = append(ret, apex.InApexVariants...)
+ ret = append(ret, apex.BaseApexName)
}
slices.Sort(ret)
return ret
@@ -441,14 +441,10 @@ func generateContainerInfo(ctx ModuleContext) ContainersInfo {
}
}
- var belongingApexes []ApexInfo
- if apexInfo, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- belongingApexes = apexInfo.ApexInfos
- }
-
return ContainersInfo{
belongingContainers: containers,
- belongingApexes: belongingApexes,
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ belongingApexes: nil,
}
}
diff --git a/android/deapexer.go b/android/deapexer.go
index 4049d2b2a..6d00dcd72 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -75,8 +75,6 @@ type DeapexerInfo struct {
// map from the name of an exported file from a prebuilt_apex to the path to that file. The
// exported file name is the apex relative path, e.g. javalib/core-libart.jar.
- //
- // See Prebuilt.ApexInfoMutator for more information.
exports map[string]WritablePath
// name of the java libraries exported from the apex
diff --git a/apex/apex.go b/apex/apex.go
index 24b3118a4..33538fb13 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -61,12 +61,11 @@ func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_info", apexInfoMutator)
ctx.BottomUp("apex_unique", apexUniqueVariationsMutator)
// Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
// it should create a platform variant.
ctx.BottomUp("mark_platform_availability", markPlatformAvailability)
- ctx.Transition("apex", &apexTransitionMutator{})
+ ctx.InfoBasedTransition("apex", android.NewGenericTransitionMutatorAdapter(&apexTransitionMutator{}))
}
type apexBundleProperties struct {
@@ -996,45 +995,29 @@ func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato
}
}
-var _ ApexInfoMutator = (*apexBundle)(nil)
+var _ ApexTransitionMutator = (*apexBundle)(nil)
func (a *apexBundle) ApexVariationName() string {
return a.properties.ApexVariationName
}
-// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
-// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
-// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
-// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
-// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles.
-//
-// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex
-// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list.
-// The apexMutator uses that list to create module variants for the apexes to which it belongs.
-// The relationship between module variants and apexes is not one-to-one as variants will be
-// shared between compatible apexes.
-func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
+type generateApexInfoContext interface {
+ android.MinSdkVersionFromValueContext
+ Module() android.Module
+ ModuleName() string
+}
+// generateApexInfo returns an android.ApexInfo configuration that should be used for dependencies of this apex.
+func (a *apexBundle) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
// The VNDK APEX is special. For the APEX, the membership is described in a very different
// way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
// libraries are self-identified by their vndk.enabled properties. There is no need to run
- // this mutator for the APEX as nothing will be collected. So, let's return fast.
+ // this mutator for the APEX as nothing will be collected so return an empty ApexInfo.
if a.vndkApex {
- return
- }
-
- continueApexDepsWalk := func(child, parent android.Module) bool {
- am, ok := child.(android.ApexModule)
- if !ok || !am.CanHaveApexVariants() {
- return false
- }
-
- return android.IsDepInSameApex(mctx, parent, child)
+ return android.ApexInfo{}
}
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- minSdkVersion := a.minSdkVersion(mctx)
+ minSdkVersion := a.minSdkVersion(ctx)
// When min_sdk_version is not set, the apex is built against FutureApiLevel.
if minSdkVersion.IsNone() {
minSdkVersion = android.FutureApiLevel
@@ -1043,62 +1026,45 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
- apexVariationName := mctx.ModuleName() // could be com.android.foo
+ apexVariationName := ctx.ModuleName() // could be com.android.foo
if a.GetOverriddenBy() != "" {
// use the overridden name com.mycompany.android.foo
apexVariationName = a.GetOverriddenBy()
}
- a.properties.ApexVariationName = apexVariationName
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: minSdkVersion,
Updatable: a.Updatable(),
UsePlatformApis: a.UsePlatformApis(),
- InApexVariants: []string{apexVariationName},
- BaseApexName: mctx.ModuleName(),
+ BaseApexName: ctx.ModuleName(),
ApexAvailableName: proptools.String(a.properties.Apex_available_name),
}
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if parent == mctx.Module() {
- tag := mctx.OtherModuleDependencyTag(child)
- if _, ok := tag.(*dependencyTag); !ok {
- return false
- }
- }
- if !continueApexDepsWalk(child, parent) {
- return false
- }
- child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark!
- return true
- })
+ return apexInfo
}
-type ApexInfoMutator interface {
- // ApexVariationName returns the name of the APEX variation to use in the apex
- // mutator etc. It is the same name as ApexInfo.ApexVariationName.
- ApexVariationName() string
+func (a *apexBundle) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
+}
- // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
- // depended upon by an apex and which require an apex specific variant.
- ApexInfoMutator(android.TopDownMutatorContext)
+func (a *apexBundle) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
}
-// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
-// specific variant to modules that support the ApexInfoMutator.
-// It also propagates updatable=true to apps of updatable apexes
-func apexInfoMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
+func (a *apexBundle) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
- if a, ok := mctx.Module().(ApexInfoMutator); ok {
- a.ApexInfoMutator(mctx)
- }
+func (a *apexBundle) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
+ a.properties.ApexVariationName = info.ApexVariationName
+}
- if am, ok := mctx.Module().(android.ApexModule); ok {
- android.ApexInfoMutator(mctx, am)
- }
+type ApexTransitionMutator interface {
+ ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo
+ ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo)
}
// TODO: b/215736885 Whittle the denylist
@@ -1213,49 +1179,35 @@ func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
type apexTransitionMutator struct{}
-func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
- // apexBundle itself is mutated so that it and its dependencies have the same apex variant.
- if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return []string{overridable.GetOverriddenBy()}
- }
- return []string{ai.ApexVariationName()}
+func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorSplit(ctx)
}
- return []string{""}
+ return []android.ApexInfo{{}}
}
-func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
- return sourceVariation
-}
-
-func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- return android.IncomingApexTransition(ctx, incomingVariation)
- } else if ai, ok := ctx.Module().(ApexInfoMutator); ok {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return overridable.GetOverriddenBy()
- }
- return ai.ApexVariationName()
+func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorOutgoing(ctx, sourceInfo)
}
-
- return ""
+ return android.ApexInfo{}
}
-func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- android.MutateApexTransition(ctx, variation)
+func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorIncoming(ctx, outgoingInfo)
}
+ return android.ApexInfo{}
}
-// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
-// variant.
-func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
- if a, ok := module.(*apexBundle); ok {
- // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
- return !a.vndkApex
+func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ ai.ApexTransitionMutatorMutate(ctx, info)
}
+}
- return true
+func (a *apexTransitionMutator) TransitionInfoFromVariation(variation string) android.ApexInfo {
+ panic(fmt.Errorf("adding dependencies on explicit apex variations is not supported"))
}
const (
@@ -1677,10 +1629,6 @@ func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path
// to the child modules. Returning false makes the visit to continue in the sibling or the parent
// modules. This is used in check* functions below.
func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
- apexVariationName := ctx.ModuleName()
- if overrideName := a.GetOverriddenBy(); overrideName != "" {
- apexVariationName = overrideName
- }
ctx.WalkDeps(func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
@@ -1699,8 +1647,7 @@ func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.P
return false
}
- ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- externalDep := !android.InList(apexVariationName, ai.InApexVariants)
+ externalDep := !android.IsDepInSameApex(ctx, parent, child)
// Visit actually
return do(ctx, parent, am, externalDep)
@@ -1725,8 +1672,7 @@ func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext,
return false
}
- ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
+ externalDep := !android.IsDepInSameApex(ctx, parent, child)
// Visit actually
return do(ctx, parent, child, externalDep)
@@ -2573,7 +2519,7 @@ func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
}
// Returns apex's min_sdk_version string value, honoring overrides
-func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
+func (a *apexBundle) minSdkVersionValue(ctx android.MinSdkVersionFromValueContext) string {
// Only override the minSdkVersion value on Apexes which already specify
// a min_sdk_version (it's optional for non-updatable apexes), and that its
// min_sdk_version value is lower than the one to override with.
@@ -2597,7 +2543,7 @@ func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLe
}
// Returns apex's min_sdk_version ApiLevel, honoring overrides
-func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (a *apexBundle) minSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
}
@@ -2613,7 +2559,7 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext
librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
})
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
if info, ok := android.OtherModuleProvider(ctx, to, cc.LinkableInfoProvider); ok {
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
@@ -2727,7 +2673,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
return
}
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
if externalDep {
return false
@@ -2745,7 +2691,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
toName := ctx.OtherModuleName(to)
if android.CheckAvailableForApex(apexName,
- android.OtherModuleProviderOrDefault(ctx, to, android.ApexInfoProvider).ApexAvailableFor) {
+ android.OtherModuleProviderOrDefault(ctx, to, android.ApexAvailableInfoProvider).ApexAvailableFor) {
return true
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0d6d31999..f88c09ebd 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5190,7 +5190,7 @@ func TestPrebuilt(t *testing.T) {
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
prebuilt := testingModule.Module().(*Prebuilt)
expectedInput := "myapex-arm64.apex"
@@ -5211,7 +5211,7 @@ func TestPrebuilt(t *testing.T) {
func TestPrebuiltMissingSrc(t *testing.T) {
t.Parallel()
- testApexError(t, `module "myapex" variant "android_common_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
+ testApexError(t, `module "myapex" variant "android_common_prebuilt_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
prebuilt_apex {
name: "myapex",
}
@@ -5228,7 +5228,7 @@ func TestPrebuiltFilenameOverride(t *testing.T) {
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
p := testingModule.Module().(*Prebuilt)
expected := "notmyapex.apex"
@@ -5251,7 +5251,7 @@ func TestApexSetFilenameOverride(t *testing.T) {
set: "company-myapex.apks",
filename: "com.company.android.myapex.apex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5260,7 +5260,7 @@ func TestApexSetFilenameOverride(t *testing.T) {
set: "company-myapex.apks",
filename: "com.company.android.myapex.capex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApexError(t, `filename should end in .apex or .capex for apex_set`, `
apex_set {
@@ -5284,7 +5284,7 @@ func TestPrebuiltOverrides(t *testing.T) {
}
`)
- testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt")
+ testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_prebuilt_myapex.prebuilt")
p := testingModule.Module().(*Prebuilt)
expected := []string{"myapex"}
@@ -5307,7 +5307,7 @@ func TestPrebuiltApexName(t *testing.T) {
apex_name: "com.android.myapex",
src: "company-myapex-arm.apex",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5315,7 +5315,7 @@ func TestPrebuiltApexName(t *testing.T) {
apex_name: "com.android.myapex",
set: "company-myapex.apks",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
}
func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
@@ -5555,7 +5555,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
- myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
+ myApex := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex").Module()
overrideNames := []string{
"",
@@ -5639,7 +5639,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
// 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, `module "platform-bootclasspath" variant ".*": module "libfoo" from platform is not allowed in the apex boot jars list`, preparer, fragment)
+ testDexpreoptWithApexes(t, bp, `module "platform-bootclasspath" variant ".*": module libfoo{.*} does not provide a dex jar`, preparer, fragment)
// dexbootjar check is skipped if AllowMissingDependencies is true
preparerAllowMissingDeps := android.GroupFixturePreparers(
preparer,
@@ -5675,6 +5675,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
prebuilt_apex {
name: "myapex",
+ prefer: true,
arch: {
arm64: {
src: "myapex-arm64.apex",
@@ -6609,16 +6610,10 @@ func TestApexAvailable_IndirectDep(t *testing.T) {
testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
.*via tag apex\.dependencyTag\{"sharedLib"\}
.*-> libfoo.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libfoo.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
.*-> libbar.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libbar.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
-.*-> libbaz.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libbaz.*link:static.*`, `
+.*-> libbaz.*link:shared.*`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7878,7 +7873,7 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) {
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+ barLibrary := ctx.ModuleForTests("bar", "android_common_apex10000").Rule("javac")
if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
@@ -8024,7 +8019,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+ barLibrary := ctx.ModuleForTests("bar", "android_common_apex10000").Rule("javac")
if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
@@ -8504,31 +8499,6 @@ func TestApexWithJniLibs(t *testing.T) {
ensureListContains(t, names(rule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
}
-func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
- t.Parallel()
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `,
- android.FixtureModifyConfig(func(config android.Config) {
- delete(config.Targets, android.Android)
- config.AndroidCommonTarget = android.Target{}
- }),
- )
-
- if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
- t.Errorf("Expected variants: %v, but got: %v", expected, got)
- }
-}
-
func TestAppBundle(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
@@ -8615,16 +8585,16 @@ func TestAppSetBundlePrebuilt(t *testing.T) {
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
// Ditto for the apex.
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
- copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_myapex/foo_v2.apex")
+ m = ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
+ copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_prebuilt_myapex/foo_v2.apex")
android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
}
@@ -8643,10 +8613,10 @@ func TestApexSetApksModuleAssignment(t *testing.T) {
}
`)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -9035,7 +9005,7 @@ func TestApexSet(t *testing.T) {
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -9050,7 +9020,7 @@ func TestApexSet(t *testing.T) {
t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
}
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
+ m = ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
a := m.Module().(*ApexSet)
expectedOverrides := []string{"foo"}
actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
@@ -9077,7 +9047,7 @@ func TestApexSet_NativeBridge(t *testing.T) {
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -9185,7 +9155,7 @@ func TestApexKeysTxtOverrides(t *testing.T) {
ctx.ModuleForTests("myapex", "android_common_myapex").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
content = android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex_set", "android_common_myapex_set").Output("apexkeys.txt"))
+ ctx.ModuleForTests("myapex_set", "android_common_prebuilt_myapex_set").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
}
@@ -9364,7 +9334,7 @@ func TestApexSet_ShouldRespectCompressedApexFlag(t *testing.T) {
}),
)
- build := ctx.ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex").Output("com.company.android.myapex.apex")
+ build := ctx.ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex").Output("com.company.android.myapex.apex")
if compressionEnabled {
ensureEquals(t, build.Rule.String(), "android/soong/android.Cp")
} else {
@@ -11311,12 +11281,12 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
{
desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.contributions",
- expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions",
- expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
}
@@ -11361,7 +11331,7 @@ func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) {
// for a mainline module family, check that only the flagged soong module is visible to make
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
- ret := "android_common_com.android.foo"
+ ret := "android_common_prebuilt_com.android.foo"
if moduleName == "com.google.android.foo" {
ret = "android_common_com.google.android.foo"
}
@@ -11508,8 +11478,8 @@ func TestInstallationRulesForMultipleApexPrebuiltsWithoutSource(t *testing.T) {
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleNames []string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
ret := "android_common_com.android.adservices"
- if moduleName == "com.google.android.foo" {
- ret = "android_common_com.google.android.foo_com.google.android.foo"
+ if moduleName == "com.google.android.adservices" || moduleName == "com.google.android.adservices.v2" {
+ ret = "android_common_prebuilt_com.android.adservices"
}
return ret
}
@@ -11584,13 +11554,13 @@ func TestInstallationRulesForMultipleApexPrebuiltsWithoutSource(t *testing.T) {
expectedHiddenModuleNames: []string{"com.google.android.adservices", "com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices is selected",
selectedApexContributions: "adservices.prebuilt.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices"},
expectedHiddenModuleNames: []string{"com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices.v2 is selected",
selectedApexContributions: "adservices.prebuilt.v2.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices.v2"},
expectedHiddenModuleNames: []string{"com.google.android.adservices"},
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index e8e45adfc..60d111f67 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -292,6 +292,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
apex_available: [
"com.android.art",
],
+ min_sdk_version: "33",
compile_dex: true,
}
`, content, prefer)
@@ -420,7 +421,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_prebuilt_com.android.art", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -590,13 +591,13 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
t.Parallel()
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
- java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
})
- java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_bar`,
diff --git a/apex/builder.go b/apex/builder.go
index b40fd0991..b34dc84a6 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1104,7 +1104,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
}
depInfos := android.DepNameToDepInfoMap{}
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
// As soon as the dependency graph crosses the APEX boundary, don't go further.
diff --git a/apex/container_test.go b/apex/container_test.go
index 395793f61..bf9445b49 100644
--- a/apex/container_test.go
+++ b/apex/container_test.go
@@ -29,6 +29,7 @@ var checkContainerMatch = func(t *testing.T, name string, container string, expe
func TestApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -166,6 +167,7 @@ func TestApexDepsContainers(t *testing.T) {
func TestNonUpdatableApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -281,6 +283,7 @@ func TestNonUpdatableApexDepsContainers(t *testing.T) {
func TestUpdatableAndNonUpdatableApexesIdenticalMinSdkVersion(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 6fa1fe225..5abad81fc 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -215,7 +215,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
}
@@ -401,12 +401,12 @@ func TestDexpreoptProfileWithMultiplePrebuiltArtApexes(t *testing.T) {
{
desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.contributions",
- expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
{
desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.v2.contributions",
- expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index cd8c320ed..d79af8660 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -23,7 +23,6 @@ import (
"android/soong/dexpreopt"
"android/soong/java"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -240,8 +239,8 @@ func TestPlatformBootclasspath_LegacyPrebuiltFragment(t *testing.T) {
pbcp := result.Module("myplatform-bootclasspath", "android_common")
info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
- android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
- android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
}
func TestPlatformBootclasspathDependencies(t *testing.T) {
@@ -388,7 +387,7 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -479,6 +478,7 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
name: "myapex",
src: "myapex.apex",
exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
+ prefer: true,
}
// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
@@ -544,11 +544,11 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
// The configured contents of BootJars.
- "myapex:prebuilt_foo",
+ "prebuilt_myapex:prebuilt_foo",
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -561,32 +561,16 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
"platform:legacy.core.platform.api.stubs.exportable",
// The prebuilt library via the apex.
- "platform:myapex",
+ "platform:prebuilt_myapex",
// The fragments via the apex.
- "platform:myapex",
+ "platform:prebuilt_myapex",
// Impl lib of sdk_library for transitive srcjar generation
"platform:foo.impl",
})
}
-// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
-//
-// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
-// name of the apex, or platform is it is not part of an apex and <module> is the module name.
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
- t.Helper()
- module := ctx.ModuleForTests(name, variant).Module()
- modules := []android.Module{}
- ctx.VisitDirectDeps(module, func(m blueprint.Module) {
- modules = append(modules, m.(android.Module))
- })
-
- pairs := java.ApexNamePairsFromModules(ctx, modules)
- android.AssertDeepEquals(t, "module dependencies", expected, pairs)
-}
-
// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
// by setting generate_classpaths_proto property to false.
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 85b64e743..e7d92c3a4 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -310,89 +310,34 @@ func (p *prebuiltCommon) IncomingDepIsInSameApex(tag blueprint.DependencyTag) bo
return true
}
-// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
-// specific variant and checks that they are supported.
-//
-// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
-// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
-//
-// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
-// across prebuilt_apex modules. That is because there is no way to determine whether two
-// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
-// been built from different source at different times or they could have been built with different
-// build options that affect the libraries.
-//
-// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
-// modules were compatible it would be a lot of work and would not provide much benefit for a couple
-// of reasons:
-// - The number of prebuilt_apex modules that will be exporting files for the same module will be
-// low as the prebuilt_apex only exports files for the direct dependencies that require it and
-// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
-// few com.android.art* apex files that contain the same contents and could export files for the
-// same modules but only one of them needs to do so. Contrast that with source apex modules which
-// need apex specific variants for every module that contributes code to the apex, whether direct
-// or indirect.
-// - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
-// extra copying of files. Contrast that with source apex modules that has to build each variant
-// from source.
-func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
- // Collect the list of dependencies.
- var dependencies []android.ApexModule
- mctx.WalkDeps(func(child, parent android.Module) bool {
- // If the child is not in the same apex as the parent then exit immediately and do not visit
- // any of the child's dependencies.
- if !android.IsDepInSameApex(mctx, parent, child) {
- return false
- }
-
- tag := mctx.OtherModuleDependencyTag(child)
- depName := mctx.OtherModuleName(child)
+func (p *prebuiltCommon) checkExportedDependenciesArePrebuilts(ctx android.ModuleContext) {
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ depName := ctx.OtherModuleName(dep)
if exportedTag, ok := tag.(exportedDependencyTag); ok {
propertyName := exportedTag.name
// It is an error if the other module is not a prebuilt.
- if !android.IsModulePrebuilt(child) {
- mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
- return false
+ if !android.IsModulePrebuilt(dep) {
+ ctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
}
// It is an error if the other module is not an ApexModule.
- if _, ok := child.(android.ApexModule); !ok {
- mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
- return false
+ if _, ok := dep.(android.ApexModule); !ok {
+ ctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
}
}
- // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
- // variant.
- if _, ok := child.(android.ApexModule); !ok {
- return false
- }
-
- // Strip off the prebuilt_ prefix if present before storing content to ensure consistent
- // behavior whether there is a corresponding source module present or not.
- depName = android.RemoveOptionalPrebuiltPrefix(depName)
-
- // Add the module to the list of dependencies that need to have an APEX variant.
- dependencies = append(dependencies, child.(android.ApexModule))
-
- return true
})
+}
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- // Create an ApexInfo for the prebuilt_apex.
- apexVariationName := p.ApexVariationName()
- apexInfo := android.ApexInfo{
- ApexVariationName: apexVariationName,
- InApexVariants: []string{apexVariationName},
+// generateApexInfo returns an android.ApexInfo configuration suitable for dependencies of this apex.
+func (p *prebuiltCommon) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
+ return android.ApexInfo{
+ ApexVariationName: "prebuilt_" + p.ApexVariationName(),
+ BaseApexName: p.ApexVariationName(),
ForPrebuiltApex: true,
}
-
- // Mark the dependencies of this module as requiring a variant for this module.
- for _, am := range dependencies {
- am.BuildForApex(apexInfo)
- }
}
type Prebuilt struct {
@@ -596,10 +541,22 @@ func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
p.prebuiltApexContentsDeps(ctx)
}
-var _ ApexInfoMutator = (*Prebuilt)(nil)
+var _ ApexTransitionMutator = (*Prebuilt)(nil)
+
+func (p *Prebuilt) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{p.generateApexInfo(ctx)}
+}
+
+func (p *Prebuilt) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (p *Prebuilt) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return p.generateApexInfo(ctx)
+}
-func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- p.apexInfoMutator(mctx)
+func (p *Prebuilt) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
// creates the build rules to deapex the prebuilt, and returns a deapexerInfo
@@ -665,6 +622,8 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validateApexClasspathFragments(ctx)
}
+ p.checkExportedDependenciesArePrebuilts(ctx)
+
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module()))
@@ -825,10 +784,22 @@ func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
a.prebuiltApexContentsDeps(ctx)
}
-var _ ApexInfoMutator = (*ApexSet)(nil)
+var _ ApexTransitionMutator = (*ApexSet)(nil)
+
+func (a *ApexSet) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
+}
+
+func (a *ApexSet) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (a *ApexSet) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
-func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- a.apexInfoMutator(mctx)
+func (a *ApexSet) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index c643a8c98..81f287fd6 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -280,19 +280,19 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_mysystemserverclasspathfragment`,
})
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -440,13 +440,13 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -465,7 +465,7 @@ func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName stri
}
func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
- dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+ dexpreopt := ctx.ModuleForTests(apexName, "android_common_prebuilt_"+apexName).Rule("dexpreopt." + moduleName)
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
if expected != actual {
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
diff --git a/cc/cc.go b/cc/cc.go
index dd557b58f..cb11fb845 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -4084,6 +4084,9 @@ func (c *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
}
func (c *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if c.Host() {
+ return false
+ }
if c.HasStubsVariants() {
if IsSharedDepTag(depTag) && !IsExplicitImplSharedDepTag(depTag) {
// dynamic dep to a stubs lib crosses APEX boundary
@@ -4224,7 +4227,6 @@ func (c *Module) typ() moduleType {
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// cc_defaults provides a set of properties that can be inherited by other cc
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fd4b0a305..65a05798a 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -423,6 +423,9 @@ func (b *BootclasspathFragmentModule) OutgoingDepIsInSameApex(tag blueprint.Depe
// Cross-cutting metadata dependencies are metadata.
return false
}
+ if tag == moduleInFragmentDepTag {
+ return true
+ }
// Dependency to the bootclasspath fragment of another apex
// e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment
if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
@@ -431,6 +434,15 @@ func (b *BootclasspathFragmentModule) OutgoingDepIsInSameApex(tag blueprint.Depe
if tag == moduleInFragmentDepTag {
return false
}
+ if tag == dexpreopt.Dex2oatDepTag {
+ return false
+ }
+ if tag == android.PrebuiltDepTag {
+ return false
+ }
+ if _, ok := tag.(hiddenAPIStubsDependencyTag); ok {
+ return false
+ }
panic(fmt.Errorf("boot_image module %q should not have a dependency tag %s", b, android.PrettyPrintTag(tag)))
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 15e40ba0d..5755dec23 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -177,10 +177,7 @@ func disableSourceApexVariant(ctx android.BaseModuleContext) bool {
// Find the apex variant for this module
apexVariants := []string{}
if apexInfo.BaseApexName != "" {
- // This is a transitive dependency of an override_apex
apexVariants = append(apexVariants, apexInfo.BaseApexName)
- } else {
- apexVariants = append(apexVariants, apexInfo.InApexVariants...)
}
if apexInfo.ApexAvailableName != "" {
apexVariants = append(apexVariants, apexInfo.ApexAvailableName)
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 7d21b7a61..2c8694237 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -171,11 +171,11 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
if android.IsConfiguredJarForPlatform(requiredApex) {
- if len(apexInfo.InApexVariants) != 0 {
+ if apexInfo.ApexVariationName != "" {
// A platform variant is required but this is for an apex so ignore it.
return false
}
- } else if !apexInfo.InApexVariant(requiredApex) {
+ } else if apexInfo.BaseApexName != requiredApex {
// An apex variant for a specific apex is required but this is the wrong apex.
return false
}
diff --git a/java/java.go b/java/java.go
index d32133972..9e1959a8d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -3513,7 +3513,6 @@ func DexImportFactory() android.Module {
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// java_defaults provides a set of properties that can be inherited by other java or android modules.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 39b54e3e8..155afc6c2 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -258,7 +258,7 @@ func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleCon
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
- ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.InApexVariants)
+ ctx.ModuleErrorf("module %q from updatable apex %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.BaseApexName)
} else {
// ok: this jar is part of the platform or a non-updatable apex
}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index f3074ed0a..6f746b45a 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -119,6 +119,7 @@ func systemServerClasspathFactory() android.Module {
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
+
func (m *SystemServerClasspathModule) UniqueApexVariations() bool {
return true
}
diff --git a/java/testing.go b/java/testing.go
index 5ee659c81..b3e552658 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -651,7 +651,7 @@ func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, nam
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules)
+ pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex)
android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs)
}
@@ -666,23 +666,54 @@ func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *androi
android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir)
}
-// ApexNamePairsFromModules returns the apex:module pair for the supplied modules.
-func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string {
+// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list.
+//
+// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
+// name of the apex, or platform is it is not part of an apex and <module> is the module name.
+func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ t.Helper()
+ platformBootclasspath := ctx.ModuleForTests(name, variant).Module().(*platformBootclasspathModule)
+ modules := []android.Module{}
+ ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) {
+ modules = append(modules, m.(android.Module))
+ })
+
+ pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex)
+ android.AssertDeepEquals(t, "module dependencies", expected, pairs)
+}
+
+// apexNamePairsFromModules returns the apex:module pair for the supplied modules.
+func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string {
pairs := []string{}
for _, module := range modules {
- pairs = append(pairs, apexNamePairFromModule(ctx, module))
+ pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex))
+ }
+ return pairs
+}
+
+// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments.
+func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string {
+ pairs := []string{}
+ for _, fragment := range fragments {
+ found := false
+ for apex, apexFragment := range apexNameToFragment {
+ if apexFragment == fragment {
+ pairs = append(pairs, apex+":"+ctx.ModuleName(fragment))
+ found = true
+ }
+ }
+ if !found {
+ pairs = append(pairs, "platform:"+ctx.ModuleName(fragment))
+ }
}
return pairs
}
-func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
+func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string {
name := module.Name()
- var apex string
- apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
- if apexInfo.IsForPlatform() {
+ apex := modulesToApex[module]
+ if apex == "" {
apex = "platform"
- } else {
- apex = apexInfo.InApexVariants[0]
}
return fmt.Sprintf("%s:%s", apex, name)
@@ -693,7 +724,7 @@ func apexNamePairFromModule(ctx *android.TestContext, module android.Module) str
func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments)
+ pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment)
android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
}
diff --git a/rust/rust.go b/rust/rust.go
index 90e5277b0..94f0a683d 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -2124,6 +2124,9 @@ func (mod *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool
}
func (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if mod.Host() {
+ return false
+ }
// TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
if mod.ApexExclude() {
return false
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 05915beef..ca630202a 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -66,6 +66,7 @@ func fixtureAddPrebuiltApexForBootclasspathFragment(apex, fragment string) andro
exported_bootclasspath_fragments: [
"%s",
],
+ prefer: false,
}
`, apex, apexFile, fragment)),
android.FixtureAddFile(filepath.Join(dir, apexFile), nil),
@@ -226,8 +227,8 @@ java_import {
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
diff --git a/sdk/testing.go b/sdk/testing.go
index f5518c46f..cd7bbf58e 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -281,7 +281,7 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st
// Run the snapshot with the snapshot preparer and the extra preparer, which must come after as
// it may need to modify parts of the MockFS populated by the snapshot preparer.
- result := android.GroupFixturePreparers(snapshotPreparer, extraPreparer, customizedPreparers).
+ result := android.GroupFixturePreparers(snapshotPreparer, customizedPreparers, extraPreparer).
ExtendWithErrorHandler(customization.errorHandler).
RunTest(t)
@@ -314,6 +314,11 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st
snapshotBpFile := filepath.Join(snapshotSubDir, "Android.bp")
unpreferred := string(fs[snapshotBpFile])
fs[snapshotBpFile] = []byte(strings.ReplaceAll(unpreferred, "prefer: false,", "prefer: true,"))
+
+ prebuiltApexBpFile := "prebuilts/apex/Android.bp"
+ if prebuiltApexBp, ok := fs[prebuiltApexBpFile]; ok {
+ fs[prebuiltApexBpFile] = []byte(strings.ReplaceAll(string(prebuiltApexBp), "prefer: false,", "prefer: true,"))
+ }
})
runSnapshotTestWithCheckers(t, checkSnapshotPreferredWithSource, preferPrebuilts)