Add enforced RRO support to Soong
am: 890ff551f7
Change-Id: Iabde599deb849c8252b65d7e5f9e2438fddb31f0
This commit is contained in:
commit
4713d17c35
4 changed files with 205 additions and 13 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue