Apply PRODUCT_ENFORCE_RRO_TARGETS to dependencies.
With this change, users don't need to figure out which libraries actually hold the resources to be overlaid when targetting apps with a core lib dependency (e.g. Settings, SystemUI). Fixes: 169898727 Test: app_test.go Change-Id: I3c3b9dc0a377b1828db1199858a73d080a173205
This commit is contained in:
parent
3c72ce8696
commit
c779cd403f
|
@ -916,6 +916,10 @@ func (c *config) EnforceRROForModule(name string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *config) EnforceRROExemptedForModule(name string) bool {
|
||||||
|
return InList(name, c.productVariables.EnforceRROExemptedTargets)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *config) EnforceRROExcludedOverlay(path string) bool {
|
func (c *config) EnforceRROExcludedOverlay(path string) bool {
|
||||||
excluded := c.productVariables.EnforceRROExcludedOverlays
|
excluded := c.productVariables.EnforceRROExcludedOverlays
|
||||||
if len(excluded) > 0 {
|
if len(excluded) > 0 {
|
||||||
|
|
47
java/aar.go
47
java/aar.go
|
@ -34,10 +34,16 @@ type AndroidLibraryDependency interface {
|
||||||
ExportedStaticPackages() android.Paths
|
ExportedStaticPackages() android.Paths
|
||||||
ExportedManifests() android.Paths
|
ExportedManifests() android.Paths
|
||||||
ExportedAssets() android.OptionalPath
|
ExportedAssets() android.OptionalPath
|
||||||
|
SetRROEnforcedForDependent(enforce bool)
|
||||||
|
IsRROEnforced(ctx android.BaseModuleContext) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterAARBuildComponents(android.InitRegistrationContext)
|
RegisterAARBuildComponents(android.InitRegistrationContext)
|
||||||
|
|
||||||
|
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
|
ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterAARBuildComponents(ctx android.RegistrationContext) {
|
func RegisterAARBuildComponents(ctx android.RegistrationContext) {
|
||||||
|
@ -82,6 +88,9 @@ type aaptProperties struct {
|
||||||
|
|
||||||
// do not include AndroidManifest from dependent libraries
|
// do not include AndroidManifest from dependent libraries
|
||||||
Dont_merge_manifests *bool
|
Dont_merge_manifests *bool
|
||||||
|
|
||||||
|
// true if RRO is enforced for any of the dependent modules
|
||||||
|
RROEnforcedForDependent bool `blueprint:"mutated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type aapt struct {
|
type aapt struct {
|
||||||
|
@ -117,6 +126,18 @@ type split struct {
|
||||||
path android.Path
|
path android.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Propagate RRO enforcement flag to static lib dependencies transitively.
|
||||||
|
func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
|
||||||
|
m := ctx.Module()
|
||||||
|
if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
|
||||||
|
ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
|
||||||
|
if a, ok := d.(AndroidLibraryDependency); ok {
|
||||||
|
a.SetRROEnforcedForDependent(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *aapt) ExportPackage() android.Path {
|
func (a *aapt) ExportPackage() android.Path {
|
||||||
return a.exportPackage
|
return a.exportPackage
|
||||||
}
|
}
|
||||||
|
@ -133,6 +154,17 @@ func (a *aapt) ExportedAssets() android.OptionalPath {
|
||||||
return a.assetPackage
|
return a.assetPackage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
|
||||||
|
a.aaptProperties.RROEnforcedForDependent = enforce
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool {
|
||||||
|
// True if RRO is enforced for this module or...
|
||||||
|
return ctx.Config().EnforceRROForModule(ctx.ModuleName()) ||
|
||||||
|
// if RRO is enforced for any of its dependents, and this module is not exempted.
|
||||||
|
(a.aaptProperties.RROEnforcedForDependent && !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()))
|
||||||
|
}
|
||||||
|
|
||||||
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
|
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
|
||||||
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
|
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
|
||||||
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
|
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
|
||||||
|
@ -156,7 +188,7 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
files: androidResourceGlob(ctx, dir),
|
files: androidResourceGlob(ctx, dir),
|
||||||
})
|
})
|
||||||
resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
|
resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir)
|
||||||
overlayDirs = append(overlayDirs, resOverlayDirs...)
|
overlayDirs = append(overlayDirs, resOverlayDirs...)
|
||||||
rroDirs = append(rroDirs, resRRODirs...)
|
rroDirs = append(rroDirs, resRRODirs...)
|
||||||
}
|
}
|
||||||
|
@ -412,6 +444,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
||||||
assets = append(assets, aarDep.ExportedAssets().Path())
|
assets = append(assets, aarDep.ExportedAssets().Path())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()) {
|
||||||
outer:
|
outer:
|
||||||
for _, d := range aarDep.ExportedRRODirs() {
|
for _, d := range aarDep.ExportedRRODirs() {
|
||||||
for _, e := range staticRRODirs {
|
for _, e := range staticRRODirs {
|
||||||
|
@ -423,6 +456,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
deps = append(deps, sharedLibs...)
|
deps = append(deps, sharedLibs...)
|
||||||
|
@ -621,6 +655,17 @@ func (a *AARImport) ExportedAssets() android.OptionalPath {
|
||||||
return android.OptionalPath{}
|
return android.OptionalPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RRO enforcement is not available on aar_import since its RRO dirs are not
|
||||||
|
// exported.
|
||||||
|
func (a *AARImport) SetRROEnforcedForDependent(enforce bool) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// RRO enforcement is not available on aar_import since its RRO dirs are not
|
||||||
|
// exported.
|
||||||
|
func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (a *AARImport) Prebuilt() *android.Prebuilt {
|
func (a *AARImport) Prebuilt() *android.Prebuilt {
|
||||||
return &a.prebuilt
|
return &a.prebuilt
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,13 +66,13 @@ type globbedResourceDir struct {
|
||||||
files android.Paths
|
files android.Paths
|
||||||
}
|
}
|
||||||
|
|
||||||
func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
|
func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
|
||||||
rroDirs []rroDir) {
|
rroDirs []rroDir) {
|
||||||
|
|
||||||
overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
|
overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
|
||||||
|
|
||||||
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
|
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
|
||||||
rroEnabled := ctx.Config().EnforceRROForModule(ctx.ModuleName())
|
rroEnabled := a.IsRROEnforced(ctx)
|
||||||
|
|
||||||
for _, data := range overlayData {
|
for _, data := range overlayData {
|
||||||
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
|
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
|
||||||
|
|
117
java/app_test.go
117
java/app_test.go
|
@ -848,19 +848,17 @@ func TestAndroidResources(t *testing.T) {
|
||||||
"lib": {
|
"lib": {
|
||||||
buildDir + "/.intermediates/lib2/android_common/package-res.apk",
|
buildDir + "/.intermediates/lib2/android_common/package-res.apk",
|
||||||
"lib/res/res/values/strings.xml",
|
"lib/res/res/values/strings.xml",
|
||||||
"device/vendor/blah/overlay/lib/res/values/strings.xml",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
rroDirs: map[string][]string{
|
rroDirs: map[string][]string{
|
||||||
"foo": {
|
"foo": {
|
||||||
"device:device/vendor/blah/overlay/foo/res",
|
"device:device/vendor/blah/overlay/foo/res",
|
||||||
// Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
|
|
||||||
// "device/vendor/blah/overlay/lib/res",
|
|
||||||
"product:product/vendor/blah/overlay/foo/res",
|
"product:product/vendor/blah/overlay/foo/res",
|
||||||
|
"device:device/vendor/blah/overlay/lib/res",
|
||||||
},
|
},
|
||||||
"bar": nil,
|
"bar": nil,
|
||||||
"lib": nil,
|
"lib": {"device:device/vendor/blah/overlay/lib/res"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3401,3 +3399,114 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) {
|
||||||
checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
enforceRROTargets []string
|
||||||
|
enforceRROExemptTargets []string
|
||||||
|
rroDirs map[string][]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no RRO",
|
||||||
|
enforceRROTargets: nil,
|
||||||
|
enforceRROExemptTargets: nil,
|
||||||
|
rroDirs: map[string][]string{
|
||||||
|
"foo": nil,
|
||||||
|
"bar": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "enforce RRO on all",
|
||||||
|
enforceRROTargets: []string{"*"},
|
||||||
|
enforceRROExemptTargets: nil,
|
||||||
|
rroDirs: map[string][]string{
|
||||||
|
"foo": {"product/vendor/blah/overlay/lib2/res"},
|
||||||
|
"bar": {"product/vendor/blah/overlay/lib2/res"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "enforce RRO on foo",
|
||||||
|
enforceRROTargets: []string{"foo"},
|
||||||
|
enforceRROExemptTargets: nil,
|
||||||
|
rroDirs: map[string][]string{
|
||||||
|
"foo": {"product/vendor/blah/overlay/lib2/res"},
|
||||||
|
"bar": {"product/vendor/blah/overlay/lib2/res"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "enforce RRO on foo, bar exempted",
|
||||||
|
enforceRROTargets: []string{"foo"},
|
||||||
|
enforceRROExemptTargets: []string{"bar"},
|
||||||
|
rroDirs: map[string][]string{
|
||||||
|
"foo": {"product/vendor/blah/overlay/lib2/res"},
|
||||||
|
"bar": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
productResourceOverlays := []string{
|
||||||
|
"product/vendor/blah/overlay",
|
||||||
|
}
|
||||||
|
|
||||||
|
fs := map[string][]byte{
|
||||||
|
"lib2/res/values/strings.xml": nil,
|
||||||
|
"product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
bp := `
|
||||||
|
android_app {
|
||||||
|
name: "foo",
|
||||||
|
sdk_version: "current",
|
||||||
|
resource_dirs: [],
|
||||||
|
static_libs: ["lib"],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_app {
|
||||||
|
name: "bar",
|
||||||
|
sdk_version: "current",
|
||||||
|
resource_dirs: [],
|
||||||
|
static_libs: ["lib"],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_library {
|
||||||
|
name: "lib",
|
||||||
|
sdk_version: "current",
|
||||||
|
resource_dirs: [],
|
||||||
|
static_libs: ["lib2"],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_library {
|
||||||
|
name: "lib2",
|
||||||
|
sdk_version: "current",
|
||||||
|
resource_dirs: ["lib2/res"],
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
config := testAppConfig(nil, bp, fs)
|
||||||
|
config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
|
||||||
|
if testCase.enforceRROTargets != nil {
|
||||||
|
config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
|
||||||
|
}
|
||||||
|
if testCase.enforceRROExemptTargets != nil {
|
||||||
|
config.TestProductVariables.EnforceRROExemptedTargets = testCase.enforceRROExemptTargets
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := testContext()
|
||||||
|
run(t, ctx, config)
|
||||||
|
|
||||||
|
modules := []string{"foo", "bar"}
|
||||||
|
for _, moduleName := range modules {
|
||||||
|
module := ctx.ModuleForTests(moduleName, "android_common")
|
||||||
|
mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
|
||||||
|
actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
|
||||||
|
if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
|
||||||
|
t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
|
||||||
|
moduleName, testCase.rroDirs[moduleName], actualRRODirs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -102,6 +102,10 @@ func testContext() *android.TestContext {
|
||||||
|
|
||||||
dexpreopt.RegisterToolModulesForTest(ctx)
|
dexpreopt.RegisterToolModulesForTest(ctx)
|
||||||
|
|
||||||
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
|
ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
|
||||||
|
})
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue