summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/aapt2.go4
-rw-r--r--java/androidmk.go7
-rw-r--r--java/app.go68
-rw-r--r--java/app_test.go148
4 files changed, 214 insertions, 13 deletions
diff --git a/java/aapt2.go b/java/aapt2.go
index cebd6d157..84e3729fe 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -16,6 +16,7 @@ package java
import (
"path/filepath"
+ "sort"
"strconv"
"strings"
@@ -85,6 +86,9 @@ func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Pat
})
}
+ sort.Slice(ret, func(i, j int) bool {
+ return ret[i].String() < ret[j].String()
+ })
return ret
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 86e000d7f..2e676399a 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -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())
}
},
},
diff --git a/java/app.go b/java/app.go
index b66eb4b7d..6866e2a83 100644
--- a/java/app.go
+++ b/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())
diff --git a/java/app_test.go b/java/app_test.go
index 37489f587..73ac3f78e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -17,6 +17,7 @@ package java
import (
"android/soong/android"
"reflect"
+ "sort"
"testing"
)
@@ -79,7 +80,11 @@ func TestApp(t *testing.T) {
t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
resourceFiles, compile.Inputs.Strings())
}
- expectedLinkImplicits = append(expectedLinkImplicits, compile.Outputs.Strings()...)
+
+ compiledResourceOutputs := compile.Outputs.Strings()
+ sort.Strings(compiledResourceOutputs)
+
+ expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
list := foo.Output("aapt2/res.list")
expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
@@ -91,3 +96,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)
+ }
+
+ })
+ }
+}