Merge changes from topic "fix-apexkeys" into main
* changes: Rewrite how to generate apexkeys.txt Refactor around apexKeysText singleton
This commit is contained in:
@@ -260,6 +260,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
|
|||||||
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
|
||||||
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " "))
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " "))
|
||||||
}
|
}
|
||||||
|
fmt.Fprintln(w, "LOCAL_APEX_KEY_PATH := ", a.apexKeysPath.String())
|
||||||
|
|
||||||
// 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
|
||||||
// which are available via data.Entries
|
// which are available via data.Entries
|
||||||
|
@@ -454,6 +454,9 @@ type apexBundle struct {
|
|||||||
// Path where this APEX was installed.
|
// Path where this APEX was installed.
|
||||||
installedFile android.InstallPath
|
installedFile android.InstallPath
|
||||||
|
|
||||||
|
// fragment for this apex for apexkeys.txt
|
||||||
|
apexKeysPath android.WritablePath
|
||||||
|
|
||||||
// Installed locations of symlinks for backward compatibility.
|
// Installed locations of symlinks for backward compatibility.
|
||||||
compatSymlinks android.InstallPaths
|
compatSymlinks android.InstallPaths
|
||||||
|
|
||||||
@@ -1923,6 +1926,7 @@ func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
a.filesInfo = append(a.filesInfo, fileInfo)
|
a.filesInfo = append(a.filesInfo, fileInfo)
|
||||||
}
|
}
|
||||||
|
a.apexKeysPath = writeApexKeys(ctx, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apexBundle) setCompression(ctx android.ModuleContext) {
|
func (a *apexBundle) setCompression(ctx android.ModuleContext) {
|
||||||
|
@@ -9089,8 +9089,8 @@ func TestApexKeysTxt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
apexKeysText := ctx.SingletonForTests("apex_keys_text")
|
myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
|
||||||
content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
|
content := myapex.Output("apexkeys.txt").BuildParams.Args["content"]
|
||||||
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
|
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9130,10 +9130,10 @@ func TestApexKeysTxtOverrides(t *testing.T) {
|
|||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
apexKeysText := ctx.SingletonForTests("apex_keys_text")
|
content := ctx.ModuleForTests("myapex", "android_common_myapex").Output("apexkeys.txt").BuildParams.Args["content"]
|
||||||
content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
|
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
|
||||||
|
content = ctx.ModuleForTests("myapex_set", "android_common_myapex_set").Output("apexkeys.txt").BuildParams.Args["content"]
|
||||||
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
|
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
|
||||||
ensureContains(t, content, `name="myapex.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAllowedFiles(t *testing.T) {
|
func TestAllowedFiles(t *testing.T) {
|
||||||
|
@@ -948,6 +948,8 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
// installed-files.txt is dist'ed
|
// installed-files.txt is dist'ed
|
||||||
a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir)
|
a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir)
|
||||||
|
|
||||||
|
a.apexKeysPath = writeApexKeys(ctx, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCertificateAndPrivateKey retrieves the cert and the private key that will be used to sign
|
// getCertificateAndPrivateKey retrieves the cert and the private key that will be used to sign
|
||||||
|
139
apex/key.go
139
apex/key.go
@@ -16,8 +16,6 @@ package apex
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/bazel"
|
"android/soong/bazel"
|
||||||
@@ -33,7 +31,6 @@ func init() {
|
|||||||
|
|
||||||
func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
|
func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
|
||||||
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
|
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
|
||||||
ctx.RegisterParallelSingletonType("apex_keys_text", apexKeysTextFactory)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type apexKey struct {
|
type apexKey struct {
|
||||||
@@ -102,99 +99,65 @@ func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////////
|
type apexKeyEntry struct {
|
||||||
// apex_keys_text
|
name string
|
||||||
type apexKeysText struct {
|
presigned bool
|
||||||
output android.OutputPath
|
publicKey string
|
||||||
|
privateKey string
|
||||||
|
containerCertificate string
|
||||||
|
containerPrivateKey string
|
||||||
|
partition string
|
||||||
|
signTool string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
|
func (e apexKeyEntry) String() string {
|
||||||
s.output = android.PathForOutput(ctx, "apexkeys.txt")
|
signTool := ""
|
||||||
type apexKeyEntry struct {
|
if e.signTool != "" {
|
||||||
name string
|
signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
|
||||||
presigned bool
|
|
||||||
publicKey string
|
|
||||||
privateKey string
|
|
||||||
containerCertificate string
|
|
||||||
containerPrivateKey string
|
|
||||||
partition string
|
|
||||||
signTool string
|
|
||||||
}
|
}
|
||||||
toString := func(e apexKeyEntry) string {
|
format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
|
||||||
signTool := ""
|
if e.presigned {
|
||||||
if e.signTool != "" {
|
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
|
||||||
signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
|
} else {
|
||||||
}
|
return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
|
||||||
format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
|
|
||||||
if e.presigned {
|
|
||||||
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apexKeyMap := make(map[string]apexKeyEntry)
|
|
||||||
ctx.VisitAllModules(func(module android.Module) {
|
|
||||||
if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
|
|
||||||
pem, key := m.getCertificateAndPrivateKey(ctx)
|
|
||||||
apexKeyMap[m.Name()] = apexKeyEntry{
|
|
||||||
name: m.Name() + ".apex",
|
|
||||||
presigned: false,
|
|
||||||
publicKey: m.publicKeyFile.String(),
|
|
||||||
privateKey: m.privateKeyFile.String(),
|
|
||||||
containerCertificate: pem.String(),
|
|
||||||
containerPrivateKey: key.String(),
|
|
||||||
partition: m.PartitionTag(ctx.DeviceConfig()),
|
|
||||||
signTool: proptools.String(m.properties.Custom_sign_tool),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Find prebuilts and let them override apexBundle if they are preferred
|
|
||||||
ctx.VisitAllModules(func(module android.Module) {
|
|
||||||
if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
|
|
||||||
m.Prebuilt().UsePrebuilt() {
|
|
||||||
apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
|
|
||||||
name: m.InstallFilename(),
|
|
||||||
presigned: true,
|
|
||||||
partition: m.PartitionTag(ctx.DeviceConfig()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
|
|
||||||
// so that apex_set are not overridden by prebuilts.
|
|
||||||
ctx.VisitAllModules(func(module android.Module) {
|
|
||||||
if m, ok := module.(*ApexSet); ok && m.Enabled() {
|
|
||||||
entry := apexKeyEntry{
|
|
||||||
name: m.InstallFilename(),
|
|
||||||
presigned: true,
|
|
||||||
partition: m.PartitionTag(ctx.DeviceConfig()),
|
|
||||||
}
|
|
||||||
apexKeyMap[m.BaseModuleName()] = entry
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// iterating over map does not give consistent ordering in golang
|
|
||||||
var moduleNames []string
|
|
||||||
for key, _ := range apexKeyMap {
|
|
||||||
moduleNames = append(moduleNames, key)
|
|
||||||
}
|
|
||||||
sort.Strings(moduleNames)
|
|
||||||
|
|
||||||
var filecontent strings.Builder
|
|
||||||
for _, name := range moduleNames {
|
|
||||||
filecontent.WriteString(toString(apexKeyMap[name]))
|
|
||||||
}
|
|
||||||
android.WriteFileRule(ctx, s.output, filecontent.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func apexKeysTextFactory() android.Singleton {
|
func apexKeyEntryFor(ctx android.ModuleContext, module android.Module) apexKeyEntry {
|
||||||
return &apexKeysText{}
|
switch m := module.(type) {
|
||||||
|
case *apexBundle:
|
||||||
|
pem, key := m.getCertificateAndPrivateKey(ctx)
|
||||||
|
return apexKeyEntry{
|
||||||
|
name: m.Name() + ".apex",
|
||||||
|
presigned: false,
|
||||||
|
publicKey: m.publicKeyFile.String(),
|
||||||
|
privateKey: m.privateKeyFile.String(),
|
||||||
|
containerCertificate: pem.String(),
|
||||||
|
containerPrivateKey: key.String(),
|
||||||
|
partition: m.PartitionTag(ctx.DeviceConfig()),
|
||||||
|
signTool: proptools.String(m.properties.Custom_sign_tool),
|
||||||
|
}
|
||||||
|
case *Prebuilt:
|
||||||
|
return apexKeyEntry{
|
||||||
|
name: m.InstallFilename(),
|
||||||
|
presigned: true,
|
||||||
|
partition: m.PartitionTag(ctx.DeviceConfig()),
|
||||||
|
}
|
||||||
|
case *ApexSet:
|
||||||
|
return apexKeyEntry{
|
||||||
|
name: m.InstallFilename(),
|
||||||
|
presigned: true,
|
||||||
|
partition: m.PartitionTag(ctx.DeviceConfig()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("unknown type(%t) for apexKeyEntry", module))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) {
|
func writeApexKeys(ctx android.ModuleContext, module android.Module) android.WritablePath {
|
||||||
ctx.Strict("SOONG_APEX_KEYS_FILE", s.output.String())
|
path := android.PathForModuleOut(ctx, "apexkeys.txt")
|
||||||
|
entry := apexKeyEntryFor(ctx, module)
|
||||||
|
android.WriteFileRuleVerbatim(ctx, path, entry.String())
|
||||||
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Bazel / bp2build
|
// For Bazel / bp2build
|
||||||
|
@@ -60,6 +60,9 @@ type prebuiltCommon struct {
|
|||||||
installedFile android.InstallPath
|
installedFile android.InstallPath
|
||||||
outputApex android.WritablePath
|
outputApex android.WritablePath
|
||||||
|
|
||||||
|
// fragment for this apex for apexkeys.txt
|
||||||
|
apexKeysPath android.WritablePath
|
||||||
|
|
||||||
// A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used
|
// A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used
|
||||||
// to create make modules in prebuiltCommon.AndroidMkEntries.
|
// to create make modules in prebuiltCommon.AndroidMkEntries.
|
||||||
apexFilesForAndroidMk []apexFile
|
apexFilesForAndroidMk []apexFile
|
||||||
@@ -238,6 +241,7 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
|
|||||||
entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...)
|
entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...)
|
||||||
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
|
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
|
||||||
entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
|
entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
|
||||||
|
entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String())
|
||||||
p.addRequiredModules(entries)
|
p.addRequiredModules(entries)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -759,6 +763,7 @@ func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
p.apexKeysPath = writeApexKeys(ctx, p)
|
||||||
// TODO(jungjw): Check the key validity.
|
// TODO(jungjw): Check the key validity.
|
||||||
p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
|
p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
|
||||||
p.installDir = android.PathForModuleInstall(ctx, "apex")
|
p.installDir = android.PathForModuleInstall(ctx, "apex")
|
||||||
@@ -975,6 +980,7 @@ func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
a.apexKeysPath = writeApexKeys(ctx, a)
|
||||||
a.installFilename = a.InstallFilename()
|
a.installFilename = a.InstallFilename()
|
||||||
if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
|
if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
|
||||||
ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
|
ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
|
||||||
|
Reference in New Issue
Block a user