Improve comments in java/aapt2.go
Test: N/A
Change-Id: I4b35a7c8707b9c4b173bb4587f7634e570d78674
diff --git a/java/aapt2.go b/java/aapt2.go
index 04e4de5..5346ddf 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -25,12 +25,9 @@
"android/soong/android"
)
-const AAPT2_SHARD_SIZE = 100
-
// Convert input resource file path to output file path.
// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
-// For other resource file, just replace the last "/" with "_" and
-// add .flat extension.
+// For other resource file, just replace the last "/" with "_" and add .flat extension.
func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
name := res.Base()
@@ -43,6 +40,7 @@
return android.PathForModuleOut(ctx, "aapt2", subDir, name)
}
+// pathsToAapt2Paths Calls pathToAapt2Path on each entry of the given Paths, i.e. []Path.
func pathsToAapt2Paths(ctx android.ModuleContext, resPaths android.Paths) android.WritablePaths {
outPaths := make(android.WritablePaths, len(resPaths))
@@ -53,6 +51,9 @@
return outPaths
}
+// Shard resource files for efficiency. See aapt2Compile for details.
+const AAPT2_SHARD_SIZE = 100
+
var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile",
blueprint.RuleParams{
Command: `${config.Aapt2Cmd} compile -o $outDir $cFlags $in`,
@@ -60,14 +61,26 @@
},
"outDir", "cFlags")
+// aapt2Compile compiles resources and puts the results in the requested directory.
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
flags []string) android.WritablePaths {
+ // Shard the input paths so that they can be processed in parallel. If we shard them into too
+ // small chunks, the additional cost of spinning up aapt2 outweighs the performance gain. The
+ // current shard size, 100, seems to be a good balance between the added cost and the gain.
+ // The aapt2 compile actions are trivially short, but each action in ninja takes on the order of
+ // ~10 ms to run. frameworks/base/core/res/res has >10k resource files, so compiling each one
+ // with an individual action could take 100 CPU seconds. Sharding them reduces the overhead of
+ // starting actions by a factor of 100, at the expense of recompiling more files when one
+ // changes. Since the individual compiles are trivial it's a good tradeoff.
shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE)
ret := make(android.WritablePaths, 0, len(paths))
for i, shard := range shards {
+ // This should be kept in sync with pathToAapt2Path. The aapt2 compile command takes an
+ // output directory path, but not output file paths. So, outPaths is just where we expect
+ // the output files will be located.
outPaths := pathsToAapt2Paths(ctx, shard)
ret = append(ret, outPaths...)
@@ -82,6 +95,12 @@
Inputs: shard,
Outputs: outPaths,
Args: map[string]string{
+ // The aapt2 compile command takes an output directory path, but not output file paths.
+ // outPaths specified above is only used for dependency management purposes. In order for
+ // the outPaths values to match the actual outputs from aapt2, the dir parameter value
+ // must be a common prefix path of the paths values, and the top-level path segment used
+ // below, "aapt2", must always be kept in sync with the one in pathToAapt2Path.
+ // TODO(b/174505750): Make this easier and robust to use.
"outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
"cFlags": strings.Join(flags, " "),
},
@@ -104,6 +123,8 @@
},
}, "cFlags", "resZipDir", "zipSyncFlags")
+// Unzips the given compressed file and compiles the resource source files in it. The zipPrefix
+// parameter points to the subdirectory in the zip file where the resource files are located.
func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string,
flags []string) {
@@ -163,6 +184,7 @@
var inFlags []string
if len(compiledRes) > 0 {
+ // Create a file that contains the list of all compiled resource file paths.
resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list")
// Write out file lists to files
ctx.Build(pctx, android.BuildParams{
@@ -174,10 +196,12 @@
deps = append(deps, compiledRes...)
deps = append(deps, resFileList)
+ // aapt2 filepath arguments that start with "@" mean file-list files.
inFlags = append(inFlags, "@"+resFileList.String())
}
if len(compiledOverlay) > 0 {
+ // Compiled overlay files are processed the same way as compiled resources.
overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list")
ctx.Build(pctx, android.BuildParams{
Rule: fileListToFileRule,
@@ -188,9 +212,11 @@
deps = append(deps, compiledOverlay...)
deps = append(deps, overlayFileList)
+ // Compiled overlay files are passed over to aapt2 using -R option.
inFlags = append(inFlags, "-R", "@"+overlayFileList.String())
}
+ // Set auxiliary outputs as implicit outputs to establish correct dependency chains.
implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
linkOutput := packageRes
@@ -212,6 +238,10 @@
Implicits: deps,
Output: linkOutput,
ImplicitOutputs: implicitOutputs,
+ // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
+ // values via the flags parameter when it wants to split outputs.
+ // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
+ // tidy.
Args: map[string]string{
"flags": strings.Join(flags, " "),
"inFlags": strings.Join(inFlags, " "),
@@ -230,6 +260,8 @@
CommandDeps: []string{"${config.Aapt2Cmd}"},
})
+// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto
+// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,