Loading android/config.go +4 −0 Original line number Diff line number Diff line Loading @@ -941,6 +941,10 @@ func (c *config) EnforceRROForModule(name string) bool { return false } func (c *config) EnforceRROExemptedForModule(name string) bool { return InList(name, c.productVariables.EnforceRROExemptedTargets) } func (c *config) EnforceRROExcludedOverlay(path string) bool { excluded := c.productVariables.EnforceRROExcludedOverlays if len(excluded) > 0 { Loading java/aar.go +52 −7 Original line number Diff line number Diff line Loading @@ -34,10 +34,16 @@ type AndroidLibraryDependency interface { ExportedStaticPackages() android.Paths ExportedManifests() android.Paths ExportedAssets() android.OptionalPath SetRROEnforcedForDependent(enforce bool) IsRROEnforced(ctx android.BaseModuleContext) bool } func init() { RegisterAARBuildComponents(android.InitRegistrationContext) android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() }) } func RegisterAARBuildComponents(ctx android.RegistrationContext) { Loading Loading @@ -82,6 +88,9 @@ type aaptProperties struct { // do not include AndroidManifest from dependent libraries Dont_merge_manifests *bool // true if RRO is enforced for any of the dependent modules RROEnforcedForDependent bool `blueprint:"mutated"` } type aapt struct { Loading Loading @@ -117,6 +126,18 @@ type split struct { 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 { return a.exportPackage } Loading @@ -133,6 +154,17 @@ func (a *aapt) ExportedAssets() android.OptionalPath { 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, manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { Loading @@ -156,7 +188,7 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, dir: dir, files: androidResourceGlob(ctx, dir), }) resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir) resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir) overlayDirs = append(overlayDirs, resOverlayDirs...) rroDirs = append(rroDirs, resRRODirs...) } Loading Loading @@ -412,6 +444,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati assets = append(assets, aarDep.ExportedAssets().Path()) } if !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()) { outer: for _, d := range aarDep.ExportedRRODirs() { for _, e := range staticRRODirs { Loading @@ -423,6 +456,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati } } } } }) deps = append(deps, sharedLibs...) Loading Loading @@ -625,6 +659,17 @@ func (a *AARImport) ExportedAssets() 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 { return &a.prebuilt } Loading java/android_resources.go +2 −2 Original line number Diff line number Diff line Loading @@ -66,13 +66,13 @@ type globbedResourceDir struct { 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) { overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult) // 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 { files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String())) Loading java/app_test.go +113 −4 Original line number Diff line number Diff line Loading @@ -848,19 +848,17 @@ func TestAndroidResources(t *testing.T) { "lib": { buildDir + "/.intermediates/lib2/android_common/package-res.apk", "lib/res/res/values/strings.xml", "device/vendor/blah/overlay/lib/res/values/strings.xml", }, }, rroDirs: map[string][]string{ "foo": { "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", "device:device/vendor/blah/overlay/lib/res", }, "bar": nil, "lib": nil, "lib": {"device:device/vendor/blah/overlay/lib/res"}, }, }, { Loading Loading @@ -3382,3 +3380,114 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { 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) } } }) } } java/java_test.go +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ func testContext() *android.TestContext { dexpreopt.RegisterToolModulesForTest(ctx) ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() }) return ctx } Loading Loading
android/config.go +4 −0 Original line number Diff line number Diff line Loading @@ -941,6 +941,10 @@ func (c *config) EnforceRROForModule(name string) bool { return false } func (c *config) EnforceRROExemptedForModule(name string) bool { return InList(name, c.productVariables.EnforceRROExemptedTargets) } func (c *config) EnforceRROExcludedOverlay(path string) bool { excluded := c.productVariables.EnforceRROExcludedOverlays if len(excluded) > 0 { Loading
java/aar.go +52 −7 Original line number Diff line number Diff line Loading @@ -34,10 +34,16 @@ type AndroidLibraryDependency interface { ExportedStaticPackages() android.Paths ExportedManifests() android.Paths ExportedAssets() android.OptionalPath SetRROEnforcedForDependent(enforce bool) IsRROEnforced(ctx android.BaseModuleContext) bool } func init() { RegisterAARBuildComponents(android.InitRegistrationContext) android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() }) } func RegisterAARBuildComponents(ctx android.RegistrationContext) { Loading Loading @@ -82,6 +88,9 @@ type aaptProperties struct { // do not include AndroidManifest from dependent libraries Dont_merge_manifests *bool // true if RRO is enforced for any of the dependent modules RROEnforcedForDependent bool `blueprint:"mutated"` } type aapt struct { Loading Loading @@ -117,6 +126,18 @@ type split struct { 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 { return a.exportPackage } Loading @@ -133,6 +154,17 @@ func (a *aapt) ExportedAssets() android.OptionalPath { 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, manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { Loading @@ -156,7 +188,7 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, dir: dir, files: androidResourceGlob(ctx, dir), }) resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir) resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir) overlayDirs = append(overlayDirs, resOverlayDirs...) rroDirs = append(rroDirs, resRRODirs...) } Loading Loading @@ -412,6 +444,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati assets = append(assets, aarDep.ExportedAssets().Path()) } if !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()) { outer: for _, d := range aarDep.ExportedRRODirs() { for _, e := range staticRRODirs { Loading @@ -423,6 +456,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati } } } } }) deps = append(deps, sharedLibs...) Loading Loading @@ -625,6 +659,17 @@ func (a *AARImport) ExportedAssets() 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 { return &a.prebuilt } Loading
java/android_resources.go +2 −2 Original line number Diff line number Diff line Loading @@ -66,13 +66,13 @@ type globbedResourceDir struct { 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) { overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult) // 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 { files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String())) Loading
java/app_test.go +113 −4 Original line number Diff line number Diff line Loading @@ -848,19 +848,17 @@ func TestAndroidResources(t *testing.T) { "lib": { buildDir + "/.intermediates/lib2/android_common/package-res.apk", "lib/res/res/values/strings.xml", "device/vendor/blah/overlay/lib/res/values/strings.xml", }, }, rroDirs: map[string][]string{ "foo": { "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", "device:device/vendor/blah/overlay/lib/res", }, "bar": nil, "lib": nil, "lib": {"device:device/vendor/blah/overlay/lib/res"}, }, }, { Loading Loading @@ -3382,3 +3380,114 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { 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) } } }) } }
java/java_test.go +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ func testContext() *android.TestContext { dexpreopt.RegisterToolModulesForTest(ctx) ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() }) return ctx } Loading