Add enforced RRO support to Soong

am: 890ff551f7

Change-Id: Iabde599deb849c8252b65d7e5f9e2438fddb31f0
This commit is contained in:
Colin Cross 2017-12-01 22:11:21 +00:00 committed by android-build-merger
commit 4713d17c35
4 changed files with 205 additions and 13 deletions

View file

@ -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
}
}

View file

@ -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())
}
},
},

View file

@ -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())

View file

@ -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)
}
})
}
}