Add enforced RRO support to Soong
Ignore overlay directories that have been selected for enforced RRO by the product, and pass them to Make instead to be converted to an auto generated RRO package. Bug: 69917341 Test: m checkbuild Change-Id: I8e2677f4c600acdd8dee0869bf4fbc3d5dbc8b44
This commit is contained in:
@@ -131,7 +131,7 @@ func (m TestingModule) Output(file string) BuildParams {
|
||||
outputs = append(outputs, p.Output)
|
||||
}
|
||||
for _, f := range outputs {
|
||||
if f.Rel() == file {
|
||||
if f.String() == file || f.Rel() == file {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
@@ -143,6 +143,13 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData {
|
||||
// framework_res.
|
||||
fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
|
||||
}
|
||||
|
||||
if len(app.rroDirs) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(app.rroDirs.Strings(), " "))
|
||||
}
|
||||
fmt.Fprintln(w, "LOCAL_EXPORT_PACKAGE_RESOURCES :=",
|
||||
Bool(app.appProperties.Export_package_resources))
|
||||
fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", app.manifestPath.String())
|
||||
}
|
||||
},
|
||||
},
|
||||
|
68
java/app.go
68
java/app.go
@@ -70,6 +70,8 @@ type AndroidApp struct {
|
||||
|
||||
aaptSrcJar android.Path
|
||||
exportPackage android.Path
|
||||
rroDirs android.Paths
|
||||
manifestPath android.Path
|
||||
}
|
||||
|
||||
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
@@ -86,7 +88,7 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
}
|
||||
|
||||
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
linkFlags, linkDeps, resDirs, overlayDirs := a.aapt2Flags(ctx)
|
||||
linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, manifestPath := a.aapt2Flags(ctx)
|
||||
|
||||
packageRes := android.PathForModuleOut(ctx, "package-res.apk")
|
||||
srcJar := android.PathForModuleGen(ctx, "R.jar")
|
||||
@@ -144,6 +146,8 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)
|
||||
|
||||
a.outputFile = packageFile
|
||||
a.rroDirs = rroDirs
|
||||
a.manifestPath = manifestPath
|
||||
|
||||
if ctx.ModuleName() == "framework-res" {
|
||||
// framework-res.apk is installed as system/framework/framework-res.apk
|
||||
@@ -171,7 +175,7 @@ type globbedResourceDir struct {
|
||||
}
|
||||
|
||||
func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps android.Paths,
|
||||
resDirs, overlayDirs []globbedResourceDir) {
|
||||
resDirs, overlayDirs []globbedResourceDir, rroDirs android.Paths, manifestPath android.Path) {
|
||||
|
||||
hasVersionCode := false
|
||||
hasVersionName := false
|
||||
@@ -205,7 +209,9 @@ func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps
|
||||
dir: dir,
|
||||
files: resourceGlob(ctx, dir),
|
||||
})
|
||||
overlayDirs = append(overlayDirs, overlayResourceGlob(ctx, dir)...)
|
||||
resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
|
||||
overlayDirs = append(overlayDirs, resOverlayDirs...)
|
||||
rroDirs = append(rroDirs, resRRODirs...)
|
||||
}
|
||||
|
||||
var assetFiles android.Paths
|
||||
@@ -221,7 +227,7 @@ func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps
|
||||
manifestFile = *a.properties.Manifest
|
||||
}
|
||||
|
||||
manifestPath := android.PathForModuleSrc(ctx, manifestFile)
|
||||
manifestPath = android.PathForModuleSrc(ctx, manifestFile)
|
||||
linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
|
||||
linkDeps = append(linkDeps, manifestPath)
|
||||
|
||||
@@ -288,7 +294,7 @@ func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps
|
||||
// TODO: LOCAL_PACKAGE_OVERRIDES
|
||||
// $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
|
||||
|
||||
return linkFlags, linkDeps, resDirs, overlayDirs
|
||||
return linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, manifestPath
|
||||
}
|
||||
|
||||
func AndroidAppFactory() android.Module {
|
||||
@@ -320,26 +326,49 @@ func resourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
|
||||
type overlayGlobResult struct {
|
||||
dir string
|
||||
paths android.DirectorySortedPaths
|
||||
|
||||
// Set to true of the product has selected that values in this overlay should not be moved to
|
||||
// Runtime Resource Overlay (RRO) packages.
|
||||
excludeFromRRO bool
|
||||
}
|
||||
|
||||
const overlayDataKey = "overlayDataKey"
|
||||
|
||||
func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) []globbedResourceDir {
|
||||
func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
|
||||
rroDirs android.Paths) {
|
||||
|
||||
overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
|
||||
|
||||
var ret []globbedResourceDir
|
||||
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
|
||||
rroEnabled := false
|
||||
enforceRROTargets := ctx.Config().ProductVariables.EnforceRROTargets
|
||||
if enforceRROTargets != nil {
|
||||
if len(*enforceRROTargets) == 1 && (*enforceRROTargets)[0] == "*" {
|
||||
rroEnabled = true
|
||||
} else if inList(ctx.ModuleName(), *enforceRROTargets) {
|
||||
rroEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, data := range overlayData {
|
||||
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
|
||||
if len(files) > 0 {
|
||||
ret = append(ret, globbedResourceDir{
|
||||
dir: android.PathForSource(ctx, data.dir, dir.String()),
|
||||
files: files,
|
||||
})
|
||||
overlayModuleDir := android.PathForSource(ctx, data.dir, dir.String())
|
||||
// If enforce RRO is enabled for this module and this overlay is not in the
|
||||
// exclusion list, ignore the overlay. The list of ignored overlays will be
|
||||
// passed to Make to be turned into an RRO package.
|
||||
if rroEnabled && !data.excludeFromRRO {
|
||||
rroDirs = append(rroDirs, overlayModuleDir)
|
||||
} else {
|
||||
res = append(res, globbedResourceDir{
|
||||
dir: overlayModuleDir,
|
||||
files: files,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
return res, rroDirs
|
||||
}
|
||||
|
||||
func OverlaySingletonFactory() android.Singleton {
|
||||
@@ -349,10 +378,25 @@ func OverlaySingletonFactory() android.Singleton {
|
||||
type overlaySingleton struct{}
|
||||
|
||||
func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
|
||||
// Specific overlays may be excluded from Runtime Resource Overlays by the product config
|
||||
var rroExcludedOverlays []string
|
||||
if ctx.Config().ProductVariables.EnforceRROExcludedOverlays != nil {
|
||||
rroExcludedOverlays = *ctx.Config().ProductVariables.EnforceRROExcludedOverlays
|
||||
}
|
||||
|
||||
var overlayData []overlayGlobResult
|
||||
for _, overlay := range ctx.Config().ResourceOverlays() {
|
||||
var result overlayGlobResult
|
||||
result.dir = overlay
|
||||
|
||||
// Mark overlays that will not have Runtime Resource Overlays enforced on them
|
||||
for _, exclude := range rroExcludedOverlays {
|
||||
if strings.HasPrefix(overlay, exclude) {
|
||||
result.excludeFromRRO = true
|
||||
}
|
||||
}
|
||||
|
||||
files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), aaptIgnoreFilenames)
|
||||
if err != nil {
|
||||
ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
|
||||
|
141
java/app_test.go
141
java/app_test.go
@@ -91,3 +91,144 @@ func TestApp(t *testing.T) {
|
||||
expectedLinkImplicits, res.Implicits.Strings())
|
||||
}
|
||||
}
|
||||
|
||||
var testEnforceRROTests = []struct {
|
||||
name string
|
||||
enforceRROTargets []string
|
||||
enforceRROExcludedOverlays []string
|
||||
fooOverlayFiles []string
|
||||
fooRRODirs []string
|
||||
barOverlayFiles []string
|
||||
barRRODirs []string
|
||||
}{
|
||||
{
|
||||
name: "no RRO",
|
||||
enforceRROTargets: nil,
|
||||
enforceRROExcludedOverlays: nil,
|
||||
fooOverlayFiles: []string{
|
||||
"device/vendor/blah/overlay/foo/res/values/strings.xml",
|
||||
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
||||
},
|
||||
fooRRODirs: nil,
|
||||
barOverlayFiles: []string{
|
||||
"device/vendor/blah/overlay/bar/res/values/strings.xml",
|
||||
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
|
||||
},
|
||||
barRRODirs: nil,
|
||||
},
|
||||
{
|
||||
name: "enforce RRO on foo",
|
||||
enforceRROTargets: []string{"foo"},
|
||||
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
|
||||
fooOverlayFiles: []string{
|
||||
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
||||
},
|
||||
fooRRODirs: []string{
|
||||
"device/vendor/blah/overlay/foo/res",
|
||||
},
|
||||
barOverlayFiles: []string{
|
||||
"device/vendor/blah/overlay/bar/res/values/strings.xml",
|
||||
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
|
||||
},
|
||||
barRRODirs: nil,
|
||||
},
|
||||
{
|
||||
name: "enforce RRO on all",
|
||||
enforceRROTargets: []string{"*"},
|
||||
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
|
||||
fooOverlayFiles: []string{
|
||||
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
||||
},
|
||||
fooRRODirs: []string{
|
||||
"device/vendor/blah/overlay/foo/res",
|
||||
},
|
||||
barOverlayFiles: []string{
|
||||
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
|
||||
},
|
||||
barRRODirs: []string{
|
||||
"device/vendor/blah/overlay/bar/res",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestEnforceRRO(t *testing.T) {
|
||||
resourceOverlays := []string{
|
||||
"device/vendor/blah/overlay",
|
||||
"device/vendor/blah/overlay2",
|
||||
"device/vendor/blah/static_overlay",
|
||||
}
|
||||
|
||||
fs := map[string][]byte{
|
||||
"foo/res/res/values/strings.xml": nil,
|
||||
"bar/res/res/values/strings.xml": nil,
|
||||
"device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
|
||||
"device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
|
||||
"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,
|
||||
}
|
||||
|
||||
bp := `
|
||||
android_app {
|
||||
name: "foo",
|
||||
resource_dirs: ["foo/res"],
|
||||
}
|
||||
|
||||
android_app {
|
||||
name: "bar",
|
||||
resource_dirs: ["bar/res"],
|
||||
}
|
||||
`
|
||||
|
||||
for _, testCase := range testEnforceRROTests {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
config := testConfig(nil)
|
||||
config.ProductVariables.ResourceOverlays = &resourceOverlays
|
||||
if testCase.enforceRROTargets != nil {
|
||||
config.ProductVariables.EnforceRROTargets = &testCase.enforceRROTargets
|
||||
}
|
||||
if testCase.enforceRROExcludedOverlays != nil {
|
||||
config.ProductVariables.EnforceRROExcludedOverlays = &testCase.enforceRROExcludedOverlays
|
||||
}
|
||||
|
||||
ctx := testAppContext(config, bp, fs)
|
||||
run(t, ctx, config)
|
||||
|
||||
getOverlays := func(moduleName string) ([]string, []string) {
|
||||
module := ctx.ModuleForTests(moduleName, "android_common")
|
||||
overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
|
||||
|
||||
var overlayFiles []string
|
||||
for _, o := range overlayCompiledPaths {
|
||||
overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
|
||||
}
|
||||
|
||||
rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
|
||||
|
||||
return overlayFiles, rroDirs
|
||||
}
|
||||
|
||||
fooOverlayFiles, fooRRODirs := getOverlays("foo")
|
||||
barOverlayFiles, barRRODirs := getOverlays("bar")
|
||||
|
||||
if !reflect.DeepEqual(fooOverlayFiles, testCase.fooOverlayFiles) {
|
||||
t.Errorf("expected foo overlay files:\n %#v\n got:\n %#v",
|
||||
testCase.fooOverlayFiles, fooOverlayFiles)
|
||||
}
|
||||
if !reflect.DeepEqual(fooRRODirs, testCase.fooRRODirs) {
|
||||
t.Errorf("expected foo rroDirs: %#v\n got:\n %#v",
|
||||
testCase.fooRRODirs, fooRRODirs)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(barOverlayFiles, testCase.barOverlayFiles) {
|
||||
t.Errorf("expected bar overlay files:\n %#v\n got:\n %#v",
|
||||
testCase.barOverlayFiles, barOverlayFiles)
|
||||
}
|
||||
if !reflect.DeepEqual(barRRODirs, testCase.barRRODirs) {
|
||||
t.Errorf("expected bar rroDirs: %#v\n got:\n %#v",
|
||||
testCase.barRRODirs, barRRODirs)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user