diff --git a/android/config.go b/android/config.go index 7679f2970..fff77ca88 100644 --- a/android/config.go +++ b/android/config.go @@ -475,8 +475,12 @@ func (c *config) DeviceName() string { return *c.productVariables.DeviceName } -func (c *config) ResourceOverlays() []string { - return c.productVariables.ResourceOverlays +func (c *config) DeviceResourceOverlays() []string { + return c.productVariables.DeviceResourceOverlays +} + +func (c *config) ProductResourceOverlays() []string { + return c.productVariables.ProductResourceOverlays } func (c *config) PlatformVersionName() string { diff --git a/android/variable.go b/android/variable.go index 1b33f990a..aa8c80493 100644 --- a/android/variable.go +++ b/android/variable.go @@ -165,7 +165,8 @@ type productVariables struct { CrossHostArch *string `json:",omitempty"` CrossHostSecondaryArch *string `json:",omitempty"` - ResourceOverlays []string `json:",omitempty"` + DeviceResourceOverlays []string `json:",omitempty"` + ProductResourceOverlays []string `json:",omitempty"` EnforceRROTargets []string `json:",omitempty"` EnforceRROExcludedOverlays []string `json:",omitempty"` diff --git a/java/aar.go b/java/aar.go index 1a5ea4d2a..ba9e1873f 100644 --- a/java/aar.go +++ b/java/aar.go @@ -27,7 +27,7 @@ type AndroidLibraryDependency interface { Dependency ExportPackage() android.Path ExportedProguardFlagFiles() android.Paths - ExportedRRODirs() android.Paths + ExportedRRODirs() []rroDir ExportedStaticPackages() android.Paths ExportedManifest() android.Path } @@ -75,7 +75,7 @@ type aapt struct { exportPackage android.Path manifestPath android.Path proguardOptionsFile android.Path - rroDirs android.Paths + rroDirs []rroDir rTxt android.Path extraAaptPackagesFile android.Path isLibrary bool @@ -99,7 +99,7 @@ func (a *aapt) ExportPackage() android.Path { return a.exportPackage } -func (a *aapt) ExportedRRODirs() android.Paths { +func (a *aapt) ExportedRRODirs() []rroDir { return a.rroDirs } @@ -108,7 +108,7 @@ func (a *aapt) ExportedManifest() android.Path { } func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, manifestPath android.Path) (flags []string, - deps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs, resZips android.Paths) { + deps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { hasVersionCode := false hasVersionName := false @@ -286,8 +286,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex } // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths -func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, staticLibManifests, - staticRRODirs, deps android.Paths, flags []string) { +func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, staticLibManifests android.Paths, + staticRRODirs []rroDir, deps android.Paths, flags []string) { var sharedLibs android.Paths @@ -315,7 +315,16 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...) transitiveStaticLibs = append(transitiveStaticLibs, exportPackage) staticLibManifests = append(staticLibManifests, aarDep.ExportedManifest()) - staticRRODirs = append(staticRRODirs, aarDep.ExportedRRODirs()...) + + outer: + for _, d := range aarDep.ExportedRRODirs() { + for _, e := range staticRRODirs { + if d.path == e.path { + continue outer + } + } + staticRRODirs = append(staticRRODirs, d) + } } } }) @@ -332,7 +341,6 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati } transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs) - staticRRODirs = android.FirstUniquePaths(staticRRODirs) return transitiveStaticLibs, staticLibManifests, staticRRODirs, deps, flags } @@ -482,7 +490,7 @@ func (a *AARImport) ExportedProguardFlagFiles() android.Paths { return android.Paths{a.proguardFlags} } -func (a *AARImport) ExportedRRODirs() android.Paths { +func (a *AARImport) ExportedRRODirs() []rroDir { return nil } diff --git a/java/android_resources.go b/java/android_resources.go index 44cb709e4..c2bc746ab 100644 --- a/java/android_resources.go +++ b/java/android_resources.go @@ -41,9 +41,22 @@ func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Pa return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames) } +type overlayType int + +const ( + device overlayType = iota + 1 + product +) + +type rroDir struct { + path android.Path + overlayType overlayType +} + type overlayGlobResult struct { - dir string - paths android.DirectorySortedPaths + dir string + paths android.DirectorySortedPaths + overlayType overlayType } var overlayDataKey = android.NewOnceKey("overlayDataKey") @@ -54,7 +67,7 @@ type globbedResourceDir struct { } func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir, - rroDirs android.Paths) { + rroDirs []rroDir) { overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult) @@ -70,7 +83,7 @@ func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []glo // exclusion list, ignore the overlay. The list of ignored overlays will be // passed to Make to be turned into an RRO package. if rroEnabled && !ctx.Config().EnforceRROExcludedOverlay(overlayModuleDir.String()) { - rroDirs = append(rroDirs, overlayModuleDir) + rroDirs = append(rroDirs, rroDir{overlayModuleDir, data.overlayType}) } else { res = append(res, globbedResourceDir{ dir: overlayModuleDir, @@ -91,29 +104,34 @@ type overlaySingleton struct{} func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) { var overlayData []overlayGlobResult - overlayDirs := ctx.Config().ResourceOverlays() - for i := range overlayDirs { - // Iterate backwards through the list of overlay directories so that the later, lower-priority - // directories in the list show up earlier in the command line to aapt2. - overlay := overlayDirs[len(overlayDirs)-1-i] - var result overlayGlobResult - result.dir = overlay - files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames) - if err != nil { - ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error()) - continue - } - var paths android.Paths - for _, f := range files { - if !strings.HasSuffix(f, "/") { - paths = append(paths, android.PathForSource(ctx, f)) + appendOverlayData := func(overlayDirs []string, t overlayType) { + for i := range overlayDirs { + // Iterate backwards through the list of overlay directories so that the later, lower-priority + // directories in the list show up earlier in the command line to aapt2. + overlay := overlayDirs[len(overlayDirs)-1-i] + var result overlayGlobResult + result.dir = overlay + result.overlayType = t + + files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames) + if err != nil { + ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error()) + continue } + var paths android.Paths + for _, f := range files { + if !strings.HasSuffix(f, "/") { + paths = append(paths, android.PathForSource(ctx, f)) + } + } + result.paths = android.PathsToDirectorySortedPaths(paths) + overlayData = append(overlayData, result) } - result.paths = android.PathsToDirectorySortedPaths(paths) - overlayData = append(overlayData, result) } + appendOverlayData(ctx.Config().DeviceResourceOverlays(), device) + appendOverlayData(ctx.Config().ProductResourceOverlays(), product) ctx.Config().Once(overlayDataKey, func() interface{} { return overlayData }) diff --git a/java/androidmk.go b/java/androidmk.go index 0c3b1c768..5b4f738ac 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -257,10 +257,24 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true") } - if len(app.rroDirs) > 0 { + filterRRO := func(filter overlayType) android.Paths { + var paths android.Paths + for _, d := range app.rroDirs { + if d.overlayType == filter { + paths = append(paths, d.path) + } + } // Reverse the order, Soong stores rroDirs in aapt2 order (low to high priority), but Make // expects it in LOCAL_RESOURCE_DIRS order (high to low priority). - fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(android.ReversePaths(app.rroDirs).Strings(), " ")) + return android.ReversePaths(paths) + } + deviceRRODirs := filterRRO(device) + if len(deviceRRODirs) > 0 { + fmt.Fprintln(w, "LOCAL_SOONG_DEVICE_RRO_DIRS :=", strings.Join(deviceRRODirs.Strings(), " ")) + } + productRRODirs := filterRRO(product) + if len(productRRODirs) > 0 { + fmt.Fprintln(w, "LOCAL_SOONG_PRODUCT_RRO_DIRS :=", strings.Join(productRRODirs.Strings(), " ")) } if Bool(app.appProperties.Export_package_resources) { diff --git a/java/app_test.go b/java/app_test.go index 3942ecdb7..1bad12377 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -211,9 +211,11 @@ func TestAndroidResources(t *testing.T) { "foo": { buildDir + "/.intermediates/lib2/android_common/package-res.apk", buildDir + "/.intermediates/lib/android_common/package-res.apk", + buildDir + "/.intermediates/lib3/android_common/package-res.apk", "foo/res/res/values/strings.xml", "device/vendor/blah/static_overlay/foo/res/values/strings.xml", "device/vendor/blah/overlay/foo/res/values/strings.xml", + "product/vendor/blah/overlay/foo/res/values/strings.xml", }, "bar": { "device/vendor/blah/static_overlay/bar/res/values/strings.xml", @@ -244,6 +246,7 @@ func TestAndroidResources(t *testing.T) { "foo": { buildDir + "/.intermediates/lib2/android_common/package-res.apk", buildDir + "/.intermediates/lib/android_common/package-res.apk", + buildDir + "/.intermediates/lib3/android_common/package-res.apk", "foo/res/res/values/strings.xml", "device/vendor/blah/static_overlay/foo/res/values/strings.xml", }, @@ -260,9 +263,10 @@ func TestAndroidResources(t *testing.T) { rroDirs: map[string][]string{ "foo": { - "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", }, "bar": nil, "lib": nil, @@ -286,6 +290,7 @@ func TestAndroidResources(t *testing.T) { "foo": { buildDir + "/.intermediates/lib2/android_common/package-res.apk", buildDir + "/.intermediates/lib/android_common/package-res.apk", + buildDir + "/.intermediates/lib3/android_common/package-res.apk", "foo/res/res/values/strings.xml", "device/vendor/blah/static_overlay/foo/res/values/strings.xml", }, @@ -297,21 +302,27 @@ func TestAndroidResources(t *testing.T) { }, rroDirs: map[string][]string{ "foo": { - "device/vendor/blah/overlay/foo/res", - "device/vendor/blah/overlay/lib/res", + "device:device/vendor/blah/overlay/foo/res", + "product:product/vendor/blah/overlay/foo/res", + // Lib dep comes after the direct deps + "device:device/vendor/blah/overlay/lib/res", }, - "bar": {"device/vendor/blah/overlay/bar/res"}, - "lib": {"device/vendor/blah/overlay/lib/res"}, + "bar": {"device:device/vendor/blah/overlay/bar/res"}, + "lib": {"device:device/vendor/blah/overlay/lib/res"}, }, }, } - resourceOverlays := []string{ + deviceResourceOverlays := []string{ "device/vendor/blah/overlay", "device/vendor/blah/overlay2", "device/vendor/blah/static_overlay", } + productResourceOverlays := []string{ + "product/vendor/blah/overlay", + } + fs := map[string][]byte{ "foo/res/res/values/strings.xml": nil, "bar/res/res/values/strings.xml": nil, @@ -323,13 +334,14 @@ func TestAndroidResources(t *testing.T) { "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil, "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil, "device/vendor/blah/overlay2/res/values/strings.xml": nil, + "product/vendor/blah/overlay/foo/res/values/strings.xml": nil, } bp := ` android_app { name: "foo", resource_dirs: ["foo/res"], - static_libs: ["lib"], + static_libs: ["lib", "lib3"], } android_app { @@ -347,12 +359,19 @@ func TestAndroidResources(t *testing.T) { name: "lib2", resource_dirs: ["lib2/res"], } + + // This library has the same resources as lib (should not lead to dupe RROs) + android_library { + name: "lib3", + resource_dirs: ["lib/res"] + } ` for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { config := testConfig(nil) - config.TestProductVariables.ResourceOverlays = resourceOverlays + config.TestProductVariables.DeviceResourceOverlays = deviceResourceOverlays + config.TestProductVariables.ProductResourceOverlays = productResourceOverlays if testCase.enforceRROTargets != nil { config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets } @@ -389,7 +408,17 @@ func TestAndroidResources(t *testing.T) { overlayFiles = resourceListToFiles(module, overlayList.Inputs.Strings()) } - rroDirs = module.Module().(AndroidLibraryDependency).ExportedRRODirs().Strings() + for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() { + var prefix string + if d.overlayType == device { + prefix = "device:" + } else if d.overlayType == product { + prefix = "product:" + } else { + t.Fatalf("Unexpected overlayType %d", d.overlayType) + } + rroDirs = append(rroDirs, prefix+d.path.String()) + } return resourceFiles, overlayFiles, rroDirs }