Merge "Enable soong build tool to handle APEX compression" am: 5d2c54f1e2

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1511283

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I567fada250e030005c9c103b1c24228bf0b52988
This commit is contained in:
Mohammad Islam
2020-12-09 14:49:33 +00:00
committed by Automerger Merge Worker
6 changed files with 96 additions and 6 deletions

View File

@@ -1272,6 +1272,10 @@ func (c *config) FlattenApex() bool {
return Bool(c.productVariables.Flatten_apex) return Bool(c.productVariables.Flatten_apex)
} }
func (c *config) CompressedApex() bool {
return Bool(c.productVariables.CompressedApex)
}
func (c *config) EnforceSystemCertificate() bool { func (c *config) EnforceSystemCertificate() bool {
return Bool(c.productVariables.EnforceSystemCertificate) return Bool(c.productVariables.EnforceSystemCertificate)
} }

View File

@@ -319,8 +319,9 @@ type productVariables struct {
Ndk_abis *bool `json:",omitempty"` Ndk_abis *bool `json:",omitempty"`
Exclude_draft_ndk_apis *bool `json:",omitempty"` Exclude_draft_ndk_apis *bool `json:",omitempty"`
Flatten_apex *bool `json:",omitempty"` Flatten_apex *bool `json:",omitempty"`
Aml_abis *bool `json:",omitempty"` CompressedApex *bool `json:",omitempty"`
Aml_abis *bool `json:",omitempty"`
DexpreoptGlobalConfig *string `json:",omitempty"` DexpreoptGlobalConfig *string `json:",omitempty"`

View File

@@ -360,7 +360,11 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class? fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String()) fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix()) stemSuffix := apexType.suffix()
if a.isCompressed {
stemSuffix = ".capex"
}
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix)
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable()) fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
// Because apex writes .mk with Custom(), we need to write manually some common properties // Because apex writes .mk with Custom(), we need to write manually some common properties

View File

@@ -120,6 +120,12 @@ type apexBundleProperties struct {
// Default: true. // Default: true.
Installable *bool Installable *bool
// Whether this APEX can be compressed or not. Setting this property to false means this
// APEX will never be compressed. When set to true, APEX will be compressed if other
// conditions, e.g, target device needs to support APEX compression, are also fulfilled.
// Default: true.
Compressible *bool
// For native libraries and binaries, use the vendor variant instead of the core (platform) // For native libraries and binaries, use the vendor variant instead of the core (platform)
// variant. Default is false. DO NOT use this for APEXes that are installed to the system or // variant. Default is false. DO NOT use this for APEXes that are installed to the system or
// system_ext partition. // system_ext partition.
@@ -354,6 +360,8 @@ type apexBundle struct {
prebuiltFileToDelete string prebuiltFileToDelete string
isCompressed bool
// Path of API coverage generate file // Path of API coverage generate file
coverageOutputPath android.ModuleOutPath coverageOutputPath android.ModuleOutPath
} }

View File

@@ -346,6 +346,13 @@ func ensureListEmpty(t *testing.T, result []string) {
} }
} }
func ensureListNotEmpty(t *testing.T, result []string) {
t.Helper()
if len(result) == 0 {
t.Errorf("%q is expected to be not empty", result)
}
}
// Minimal test // Minimal test
func TestBasicApex(t *testing.T) { func TestBasicApex(t *testing.T) {
ctx, config := testApex(t, ` ctx, config := testApex(t, `
@@ -6186,6 +6193,40 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) {
`) `)
} }
func TestCompressedApex(t *testing.T) {
ctx, config := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
compressible: true,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
`, func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.CompressedApex = proptools.BoolPtr(true)
})
compressRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("compressRule")
ensureContains(t, compressRule.Output.String(), "myapex.capex.unsigned")
signApkRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Description("sign compressedApex")
ensureEquals(t, signApkRule.Input.String(), compressRule.Output.String())
// Make sure output of bundle is .capex
ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
ensureContains(t, ab.outputFile.String(), "myapex.capex")
// Verify android.mk rules
data := android.AndroidMkDataForTest(t, config, "", ab)
var builder strings.Builder
data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
androidMk := builder.String()
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.capex\n")
}
func TestPreferredPrebuiltSharedLibDep(t *testing.T) { func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
ctx, config := testApex(t, ` ctx, config := testApex(t, `
apex { apex {

View File

@@ -66,6 +66,7 @@ func init() {
pctx.HostBinToolVariable("extract_apks", "extract_apks") pctx.HostBinToolVariable("extract_apks", "extract_apks")
pctx.HostBinToolVariable("make_f2fs", "make_f2fs") pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs") pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh") pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
} }
@@ -738,7 +739,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
// Step 4: Sign the APEX using signapk // Step 4: Sign the APEX using signapk
a.outputFile = android.PathForModuleOut(ctx, a.Name()+suffix) signedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix)
pem, key := a.getCertificateAndPrivateKey(ctx) pem, key := a.getCertificateAndPrivateKey(ctx)
rule := java.Signapk rule := java.Signapk
@@ -750,16 +751,47 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") { if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
rule = java.SignapkRE rule = java.SignapkRE
args["implicits"] = strings.Join(implicits.Strings(), ",") args["implicits"] = strings.Join(implicits.Strings(), ",")
args["outCommaList"] = a.outputFile.String() args["outCommaList"] = signedOutputFile.String()
} }
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: rule, Rule: rule,
Description: "signapk", Description: "signapk",
Output: a.outputFile, Output: signedOutputFile,
Input: unsignedOutputFile, Input: unsignedOutputFile,
Implicits: implicits, Implicits: implicits,
Args: args, Args: args,
}) })
a.outputFile = signedOutputFile
// Process APEX compression if enabled
compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.properties.Compressible, true)
if compressionEnabled && apexType == imageApex {
a.isCompressed = true
unsignedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+".capex.unsigned")
compressRule := android.NewRuleBuilder(pctx, ctx)
compressRule.Command().
Text("rm").
FlagWithOutput("-f ", unsignedCompressedOutputFile)
compressRule.Command().
BuiltTool("apex_compression_tool").
Flag("compress").
FlagWithArg("--apex_compression_tool ", outHostBinDir+":"+prebuiltSdkToolsBinDir).
FlagWithInput("--input ", signedOutputFile).
FlagWithOutput("--output ", unsignedCompressedOutputFile)
compressRule.Build("compressRule", "Generate unsigned compressed APEX file")
signedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+".capex")
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "sign compressedApex",
Output: signedCompressedOutputFile,
Input: unsignedCompressedOutputFile,
Implicits: implicits,
Args: args,
})
a.outputFile = signedCompressedOutputFile
}
// Install to $OUT/soong/{target,host}/.../apex // Install to $OUT/soong/{target,host}/.../apex
if a.installable() { if a.installable() {