Add soong support for resource shrinking

This adds a new flag to the optimize section to allow invoking the resource shrinker

Bug: 246217952
Test: m
Change-Id: I2e7851af1189db2a6adf6f9f9f444a1d7f3a8d60
This commit is contained in:
Rico Wind
2022-09-22 10:41:42 +02:00
parent eb30142616
commit 351bac996c
7 changed files with 64 additions and 11 deletions

View File

@@ -64,6 +64,7 @@ bootstrap_go_package {
"plugin.go", "plugin.go",
"prebuilt_apis.go", "prebuilt_apis.go",
"proto.go", "proto.go",
"resourceshrinker.go",
"robolectric.go", "robolectric.go",
"rro.go", "rro.go",
"sdk.go", "sdk.go",

View File

@@ -256,17 +256,21 @@ func aapt2Link(ctx android.ModuleContext,
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert", var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{ blueprint.RuleParams{
Command: `${config.Aapt2Cmd} convert --output-format proto $in -o $out`, Command: `${config.Aapt2Cmd} convert --output-format $format $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"}, CommandDeps: []string{"${config.Aapt2Cmd}"},
}) }, "format",
)
// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto // 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. // format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) { func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path, format string) {
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule, Rule: aapt2ConvertRule,
Input: in, Input: in,
Output: out, Output: out,
Description: "convert to proto", Description: "convert to " + format,
Args: map[string]string{
"format": format,
},
}) })
} }

View File

@@ -667,10 +667,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
if lineage := String(a.overridableAppProperties.Lineage); lineage != "" { if lineage := String(a.overridableAppProperties.Lineage); lineage != "" {
lineageFile = android.PathForModuleSrc(ctx, lineage) lineageFile = android.PathForModuleSrc(ctx, lineage)
} }
rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion) rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion) CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, Bool(a.dexProperties.Optimize.Shrink_resources))
a.outputFile = packageFile a.outputFile = packageFile
if v4SigningRequested { if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -699,7 +698,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
if v4SigningRequested { if v4SigningRequested {
v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig") v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
} }
CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion) CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, false)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile) a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
if v4SigningRequested { if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)

View File

@@ -52,7 +52,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk",
}) })
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) { packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string, shrinkResources bool) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName) unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -65,7 +65,6 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa
if jniJarFile != nil { if jniJarFile != nil {
inputs = append(inputs, jniJarFile) inputs = append(inputs, jniJarFile)
} }
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: combineApk, Rule: combineApk,
Inputs: inputs, Inputs: inputs,
@@ -73,6 +72,11 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa
Implicits: deps, Implicits: deps,
}) })
if shrinkResources {
shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
ShrinkResources(ctx, unsignedApk, shrunkenApk)
unsignedApk = shrunkenApk
}
SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion) SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
} }
@@ -84,7 +88,6 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u
certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String()) certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
deps = append(deps, c.Pem, c.Key) deps = append(deps, c.Pem, c.Key)
} }
outputFiles := android.WritablePaths{signedApk} outputFiles := android.WritablePaths{signedApk}
var flags []string var flags []string
if v4SignatureFile != nil { if v4SignatureFile != nil {
@@ -182,7 +185,7 @@ func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePat
packageFile, jniJarFile, dexJarFile android.Path) { packageFile, jniJarFile, dexJarFile android.Path) {
protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk") protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
aapt2Convert(ctx, protoResJarFile, packageFile) aapt2Convert(ctx, protoResJarFile, packageFile, "proto")
var zips android.Paths var zips android.Paths

View File

@@ -165,6 +165,7 @@ func init() {
pctx.HostBinToolVariable("ApiCheckCmd", "apicheck") pctx.HostBinToolVariable("ApiCheckCmd", "apicheck")
pctx.HostBinToolVariable("D8Cmd", "d8") pctx.HostBinToolVariable("D8Cmd", "d8")
pctx.HostBinToolVariable("R8Cmd", "r8") pctx.HostBinToolVariable("R8Cmd", "r8")
pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker")
pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi")
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string { pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {

View File

@@ -63,6 +63,8 @@ type DexProperties struct {
// classes referenced by the app manifest. Defaults to false. // classes referenced by the app manifest. Defaults to false.
No_aapt_flags *bool No_aapt_flags *bool
Shrink_resources *bool
// Flags to pass to proguard. // Flags to pass to proguard.
Proguard_flags []string Proguard_flags []string

43
java/resourceshrinker.go Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package java
import (
"android/soong/android"
"github.com/google/blueprint"
)
var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
blueprint.RuleParams{
Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`,
CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
}, "raw_resources")
func ShrinkResources(ctx android.ModuleContext, apk android.Path, outputFile android.WritablePath) {
protoFile := android.PathForModuleOut(ctx, apk.Base()+".proto.apk")
aapt2Convert(ctx, protoFile, apk, "proto")
strictModeFile := android.PathForSource(ctx, "prebuilts/cmdline-tools/shrinker.xml")
protoOut := android.PathForModuleOut(ctx, apk.Base()+".proto.out.apk")
ctx.Build(pctx, android.BuildParams{
Rule: shrinkResources,
Input: protoFile,
Output: protoOut,
Args: map[string]string{
"raw_resources": strictModeFile.String(),
},
})
aapt2Convert(ctx, outputFile, protoOut, "binary")
}