apex_manifest in protobuf binary format
For Q compatibility, .json files are also bundled. Three different apex_manifest files are built from input. - apex_manifest.json: Q-readable .json file - apex_manifest_full.json: input + dependency - apex_manifest.pb: apex: converted from apex_manifest_full.json apexer will handle these files. Bug: 143654022 Test: m Change-Id: I9697094057f0c0543282b1b46b7535cf21431176
This commit is contained in:
105
apex/apex.go
105
apex/apex.go
@@ -41,7 +41,6 @@ var (
|
|||||||
// TODO(b/113082813) make this configurable using config.fs syntax
|
// TODO(b/113082813) make this configurable using config.fs syntax
|
||||||
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
|
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
|
||||||
Command: `echo '/ 1000 1000 0755' > ${out} && ` +
|
Command: `echo '/ 1000 1000 0755' > ${out} && ` +
|
||||||
`echo '/apex_manifest.json 1000 1000 0644' >> ${out} && ` +
|
|
||||||
`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
|
`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
|
||||||
`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`,
|
`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`,
|
||||||
Description: "fs_config ${out}",
|
Description: "fs_config ${out}",
|
||||||
@@ -57,6 +56,18 @@ var (
|
|||||||
Description: "prepare ${out}",
|
Description: "prepare ${out}",
|
||||||
}, "provideNativeLibs", "requireNativeLibs", "opt")
|
}, "provideNativeLibs", "requireNativeLibs", "opt")
|
||||||
|
|
||||||
|
stripApexManifestRule = pctx.StaticRule("stripApexManifestRule", blueprint.RuleParams{
|
||||||
|
Command: `rm -f $out && ${conv_apex_manifest} strip $in -o $out`,
|
||||||
|
CommandDeps: []string{"${conv_apex_manifest}"},
|
||||||
|
Description: "strip ${in}=>${out}",
|
||||||
|
})
|
||||||
|
|
||||||
|
pbApexManifestRule = pctx.StaticRule("pbApexManifestRule", blueprint.RuleParams{
|
||||||
|
Command: `rm -f $out && ${conv_apex_manifest} proto $in -o $out`,
|
||||||
|
CommandDeps: []string{"${conv_apex_manifest}"},
|
||||||
|
Description: "convert ${in}=>${out}",
|
||||||
|
})
|
||||||
|
|
||||||
// TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
|
// TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
|
||||||
// against the binary policy using sefcontext_compiler -p <policy>.
|
// against the binary policy using sefcontext_compiler -p <policy>.
|
||||||
|
|
||||||
@@ -66,6 +77,7 @@ var (
|
|||||||
`(. ${out}.copy_commands) && ` +
|
`(. ${out}.copy_commands) && ` +
|
||||||
`APEXER_TOOL_PATH=${tool_path} ` +
|
`APEXER_TOOL_PATH=${tool_path} ` +
|
||||||
`${apexer} --force --manifest ${manifest} ` +
|
`${apexer} --force --manifest ${manifest} ` +
|
||||||
|
`--manifest_json ${manifest_json} --manifest_json_full ${manifest_json_full} ` +
|
||||||
`--file_contexts ${file_contexts} ` +
|
`--file_contexts ${file_contexts} ` +
|
||||||
`--canned_fs_config ${canned_fs_config} ` +
|
`--canned_fs_config ${canned_fs_config} ` +
|
||||||
`--payload_type image ` +
|
`--payload_type image ` +
|
||||||
@@ -76,20 +88,22 @@ var (
|
|||||||
Rspfile: "${out}.copy_commands",
|
Rspfile: "${out}.copy_commands",
|
||||||
RspfileContent: "${copy_commands}",
|
RspfileContent: "${copy_commands}",
|
||||||
Description: "APEX ${image_dir} => ${out}",
|
Description: "APEX ${image_dir} => ${out}",
|
||||||
}, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key", "opt_flags")
|
}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags",
|
||||||
|
"manifest", "manifest_json", "manifest_json_full",
|
||||||
|
)
|
||||||
|
|
||||||
zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
|
zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
|
||||||
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
|
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
|
||||||
`(. ${out}.copy_commands) && ` +
|
`(. ${out}.copy_commands) && ` +
|
||||||
`APEXER_TOOL_PATH=${tool_path} ` +
|
`APEXER_TOOL_PATH=${tool_path} ` +
|
||||||
`${apexer} --force --manifest ${manifest} ` +
|
`${apexer} --force --manifest ${manifest} --manifest_json_full ${manifest_json_full} ` +
|
||||||
`--payload_type zip ` +
|
`--payload_type zip ` +
|
||||||
`${image_dir} ${out} `,
|
`${image_dir} ${out} `,
|
||||||
CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
|
CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
|
||||||
Rspfile: "${out}.copy_commands",
|
Rspfile: "${out}.copy_commands",
|
||||||
RspfileContent: "${copy_commands}",
|
RspfileContent: "${copy_commands}",
|
||||||
Description: "ZipAPEX ${image_dir} => ${out}",
|
Description: "ZipAPEX ${image_dir} => ${out}",
|
||||||
}, "tool_path", "image_dir", "copy_commands", "manifest")
|
}, "tool_path", "image_dir", "copy_commands", "manifest", "manifest_json_full")
|
||||||
|
|
||||||
apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
|
apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
@@ -181,6 +195,7 @@ func init() {
|
|||||||
pctx.HostBinToolVariable("zip2zip", "zip2zip")
|
pctx.HostBinToolVariable("zip2zip", "zip2zip")
|
||||||
pctx.HostBinToolVariable("zipalign", "zipalign")
|
pctx.HostBinToolVariable("zipalign", "zipalign")
|
||||||
pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
|
pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
|
||||||
|
pctx.HostBinToolVariable("conv_apex_manifest", "conv_apex_manifest")
|
||||||
|
|
||||||
android.RegisterModuleType("apex", BundleFactory)
|
android.RegisterModuleType("apex", BundleFactory)
|
||||||
android.RegisterModuleType("apex_test", testApexBundleFactory)
|
android.RegisterModuleType("apex_test", testApexBundleFactory)
|
||||||
@@ -637,7 +652,9 @@ type apexBundle struct {
|
|||||||
primaryApexType bool
|
primaryApexType bool
|
||||||
|
|
||||||
// intermediate path for apex_manifest.json
|
// intermediate path for apex_manifest.json
|
||||||
manifestOut android.WritablePath
|
manifestJsonOut android.WritablePath
|
||||||
|
manifestJsonFullOut android.WritablePath
|
||||||
|
manifestPbOut android.WritablePath
|
||||||
|
|
||||||
// list of commands to create symlinks for backward compatibility
|
// list of commands to create symlinks for backward compatibility
|
||||||
// these commands will be attached as LOCAL_POST_INSTALL_CMD to
|
// these commands will be attached as LOCAL_POST_INSTALL_CMD to
|
||||||
@@ -1288,9 +1305,24 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
a.filesInfo = filesInfo
|
a.filesInfo = filesInfo
|
||||||
|
|
||||||
// prepare apex_manifest.json
|
// prepare apex_manifest.json
|
||||||
a.manifestOut = android.PathForModuleOut(ctx, "apex_manifest.json")
|
a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
|
||||||
|
|
||||||
|
a.setCertificateAndPrivateKey(ctx)
|
||||||
|
if a.properties.ApexType == flattenedApex {
|
||||||
|
a.buildFlattenedApex(ctx)
|
||||||
|
} else {
|
||||||
|
a.buildUnflattenedApex(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
|
||||||
|
a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, requireNativeLibs []string) {
|
||||||
manifestSrc := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
|
manifestSrc := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
|
||||||
|
|
||||||
|
a.manifestJsonFullOut = android.PathForModuleOut(ctx, "apex_manifest_full.json")
|
||||||
|
|
||||||
// put dependency({provide|require}NativeLibs) in apex_manifest.json
|
// put dependency({provide|require}NativeLibs) in apex_manifest.json
|
||||||
provideNativeLibs = android.SortedUniqueStrings(provideNativeLibs)
|
provideNativeLibs = android.SortedUniqueStrings(provideNativeLibs)
|
||||||
requireNativeLibs = android.SortedUniqueStrings(android.RemoveListFromList(requireNativeLibs, provideNativeLibs))
|
requireNativeLibs = android.SortedUniqueStrings(android.RemoveListFromList(requireNativeLibs, provideNativeLibs))
|
||||||
@@ -1304,7 +1336,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: apexManifestRule,
|
Rule: apexManifestRule,
|
||||||
Input: manifestSrc,
|
Input: manifestSrc,
|
||||||
Output: a.manifestOut,
|
Output: a.manifestJsonFullOut,
|
||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"provideNativeLibs": strings.Join(provideNativeLibs, " "),
|
"provideNativeLibs": strings.Join(provideNativeLibs, " "),
|
||||||
"requireNativeLibs": strings.Join(requireNativeLibs, " "),
|
"requireNativeLibs": strings.Join(requireNativeLibs, " "),
|
||||||
@@ -1312,15 +1344,22 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
a.setCertificateAndPrivateKey(ctx)
|
// b/143654022 Q apexd can't understand newly added keys in apex_manifest.json
|
||||||
if a.properties.ApexType == flattenedApex {
|
// prepare stripp-downed version so that APEX modules built from R+ can be installed to Q
|
||||||
a.buildFlattenedApex(ctx)
|
a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json")
|
||||||
} else {
|
ctx.Build(pctx, android.BuildParams{
|
||||||
a.buildUnflattenedApex(ctx)
|
Rule: stripApexManifestRule,
|
||||||
}
|
Input: a.manifestJsonFullOut,
|
||||||
|
Output: a.manifestJsonOut,
|
||||||
|
})
|
||||||
|
|
||||||
apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
|
// from R+, protobuf binary format (.pb) is the standard format for apex_manifest
|
||||||
a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
|
a.manifestPbOut = android.PathForModuleOut(ctx, "apex_manifest.pb")
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: pbApexManifestRule,
|
||||||
|
Input: a.manifestJsonFullOut,
|
||||||
|
Output: a.manifestPbOut,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext, apexFileName string) android.OptionalPath {
|
func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext, apexFileName string) android.OptionalPath {
|
||||||
@@ -1382,7 +1421,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
|
|||||||
emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
|
emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
|
||||||
|
|
||||||
implicitInputs := append(android.Paths(nil), filesToCopy...)
|
implicitInputs := append(android.Paths(nil), filesToCopy...)
|
||||||
implicitInputs = append(implicitInputs, a.manifestOut)
|
implicitInputs = append(implicitInputs, a.manifestPbOut, a.manifestJsonFullOut, a.manifestJsonOut)
|
||||||
|
|
||||||
if a.properties.Whitelisted_files != nil {
|
if a.properties.Whitelisted_files != nil {
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
@@ -1418,7 +1457,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
if apexType == imageApex {
|
if apexType == imageApex {
|
||||||
// files and dirs that will be created in APEX
|
// files and dirs that will be created in APEX
|
||||||
var readOnlyPaths []string
|
var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
|
||||||
var executablePaths []string // this also includes dirs
|
var executablePaths []string // this also includes dirs
|
||||||
for _, f := range a.filesInfo {
|
for _, f := range a.filesInfo {
|
||||||
pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
|
pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
|
||||||
@@ -1516,14 +1555,16 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
|
|||||||
Output: unsignedOutputFile,
|
Output: unsignedOutputFile,
|
||||||
Description: "apex (" + apexType.name() + ")",
|
Description: "apex (" + apexType.name() + ")",
|
||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
|
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
|
||||||
"image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
|
"image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
|
||||||
"copy_commands": strings.Join(copyCommands, " && "),
|
"copy_commands": strings.Join(copyCommands, " && "),
|
||||||
"manifest": a.manifestOut.String(),
|
"manifest_json_full": a.manifestJsonFullOut.String(),
|
||||||
"file_contexts": fileContexts.String(),
|
"manifest_json": a.manifestJsonOut.String(),
|
||||||
"canned_fs_config": cannedFsConfig.String(),
|
"manifest": a.manifestPbOut.String(),
|
||||||
"key": a.private_key_file.String(),
|
"file_contexts": fileContexts.String(),
|
||||||
"opt_flags": strings.Join(optFlags, " "),
|
"canned_fs_config": cannedFsConfig.String(),
|
||||||
|
"key": a.private_key_file.String(),
|
||||||
|
"opt_flags": strings.Join(optFlags, " "),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1554,10 +1595,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
|
|||||||
Output: unsignedOutputFile,
|
Output: unsignedOutputFile,
|
||||||
Description: "apex (" + apexType.name() + ")",
|
Description: "apex (" + apexType.name() + ")",
|
||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
|
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
|
||||||
"image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
|
"image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
|
||||||
"copy_commands": strings.Join(copyCommands, " && "),
|
"copy_commands": strings.Join(copyCommands, " && "),
|
||||||
"manifest": a.manifestOut.String(),
|
"manifest": a.manifestPbOut.String(),
|
||||||
|
"manifest_json_full": a.manifestJsonFullOut.String(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1615,7 +1657,8 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
|
|||||||
if a.installable() {
|
if a.installable() {
|
||||||
// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
|
// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
|
||||||
// with other ordinary files.
|
// with other ordinary files.
|
||||||
a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, "apex_manifest.json." + ctx.ModuleName() + a.suffix, ".", etc, nil, nil})
|
a.filesInfo = append(a.filesInfo, apexFile{a.manifestJsonOut, "apex_manifest.json." + ctx.ModuleName() + a.suffix, ".", etc, nil, nil})
|
||||||
|
a.filesInfo = append(a.filesInfo, apexFile{a.manifestPbOut, "apex_manifest.pb." + ctx.ModuleName() + a.suffix, ".", etc, nil, nil})
|
||||||
|
|
||||||
// rename to apex_pubkey
|
// rename to apex_pubkey
|
||||||
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
|
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
|
||||||
@@ -1752,7 +1795,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
|
|||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
|
||||||
// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
|
// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
|
||||||
if a.primaryApexType && fi.builtFile.Base() == "apex_manifest.json" && len(a.compatSymlinks) > 0 {
|
if a.primaryApexType && fi.builtFile == a.manifestPbOut && len(a.compatSymlinks) > 0 {
|
||||||
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
|
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
||||||
|
@@ -517,6 +517,26 @@ func TestBasicApex(t *testing.T) {
|
|||||||
ensureListContains(t, noticeInputs, "custom_notice")
|
ensureListContains(t, noticeInputs, "custom_notice")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApexManifest(t *testing.T) {
|
||||||
|
ctx, _ := testApex(t, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
|
||||||
|
module.Output("apex_manifest.pb")
|
||||||
|
module.Output("apex_manifest.json")
|
||||||
|
module.Output("apex_manifest_full.json")
|
||||||
|
}
|
||||||
|
|
||||||
func TestBasicZipApex(t *testing.T) {
|
func TestBasicZipApex(t *testing.T) {
|
||||||
ctx, _ := testApex(t, `
|
ctx, _ := testApex(t, `
|
||||||
apex {
|
apex {
|
||||||
|
Reference in New Issue
Block a user