Output apkcerts file for android_app_set.
Soong and Make have no ways to figure out what splits will be outputted from a given android_app_set, so it's impossible for them to provide full PACKAGES.$(LOCAL_MODULE).CERTIFICATE entries, which are required to build a final apkcerts.txt. This change makes extract_apks produce apkcerts.txt files for each input modules instead. The Make-side counterpart of this change merges all local apkcerts.txt into a final one. Fixes: 160119159 Test: main_test.go Test: m apkcerts-list Change-Id: I321e80fd636a955213761f56a3ac64bfe7f7f7c0
This commit is contained in:
parent
c4422106a7
commit
8bec026e3a
6 changed files with 75 additions and 24 deletions
|
@ -24,6 +24,7 @@ import (
|
|||
"math"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
@ -355,7 +356,7 @@ type Zip2ZipWriter interface {
|
|||
|
||||
// Writes out selected entries, renaming them as needed
|
||||
func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
|
||||
writer Zip2ZipWriter) error {
|
||||
writer Zip2ZipWriter, partition string) ([]string, error) {
|
||||
// Renaming rules:
|
||||
// splits/MODULE-master.apk to STEM.apk
|
||||
// else
|
||||
|
@ -389,10 +390,11 @@ func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
|
|||
}
|
||||
|
||||
entryOrigin := make(map[string]string) // output entry to input entry
|
||||
var apkcerts []string
|
||||
for _, apk := range selected.entries {
|
||||
apkFile, ok := apkSet.entries[apk]
|
||||
if !ok {
|
||||
return fmt.Errorf("TOC refers to an entry %s which does not exist", apk)
|
||||
return nil, fmt.Errorf("TOC refers to an entry %s which does not exist", apk)
|
||||
}
|
||||
inName := apkFile.Name
|
||||
outName, ok := renamer(inName)
|
||||
|
@ -405,10 +407,15 @@ func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
|
|||
}
|
||||
entryOrigin[outName] = inName
|
||||
if err := writer.CopyFrom(apkFile, outName); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if partition != "" {
|
||||
apkcerts = append(apkcerts, fmt.Sprintf(
|
||||
`name="%s" certificate="PRESIGNED" private_key="" partition="%s"`, outName, partition))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
sort.Strings(apkcerts)
|
||||
return apkcerts, nil
|
||||
}
|
||||
|
||||
func (apkSet *ApkSet) extractAndCopySingle(selected SelectionResult, outFile *os.File) error {
|
||||
|
@ -433,6 +440,9 @@ var (
|
|||
}
|
||||
extractSingle = flag.Bool("extract-single", false,
|
||||
"extract a single target and output it uncompressed. only available for standalone apks and apexes.")
|
||||
apkcertsOutput = flag.String("apkcerts", "",
|
||||
"optional apkcerts.txt output file containing signing info of all outputted apks")
|
||||
partition = flag.String("partition", "", "partition string. required when -apkcerts is used.")
|
||||
)
|
||||
|
||||
// Parse abi values
|
||||
|
@ -485,7 +495,8 @@ func (s screenDensityFlagValue) Set(densityList string) error {
|
|||
func processArgs() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> -sdk-version value -abis value `+
|
||||
`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] <APK set>`)
|
||||
`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] `+
|
||||
`[-apkcerts <apkcerts output file> -partition <partition>] <APK set>`)
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
@ -498,7 +509,8 @@ func processArgs() {
|
|||
"allow prereleased")
|
||||
flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name in the output zip file")
|
||||
flag.Parse()
|
||||
if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 || (targetConfig.stem == "" && !*extractSingle) {
|
||||
if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 ||
|
||||
(targetConfig.stem == "" && !*extractSingle) || (*apkcertsOutput != "" && *partition == "") {
|
||||
flag.Usage()
|
||||
}
|
||||
targetConfig.sdkVersion = int32(*version)
|
||||
|
@ -536,7 +548,20 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = apkSet.writeApks(sel, targetConfig, writer)
|
||||
apkcerts, err := apkSet.writeApks(sel, targetConfig, writer, *partition)
|
||||
if err == nil && *apkcertsOutput != "" {
|
||||
apkcertsFile, err := os.Create(*apkcertsOutput)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer apkcertsFile.Close()
|
||||
for _, a := range apkcerts {
|
||||
_, err = apkcertsFile.WriteString(a + "\n")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -16,10 +16,11 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
bp "android/soong/cmd/extract_apks/bundle_proto"
|
||||
"android/soong/third_party/zip"
|
||||
)
|
||||
|
@ -430,48 +431,63 @@ func (w testZip2ZipWriter) CopyFrom(file *zip.File, out string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type testCaseWriteZip struct {
|
||||
type testCaseWriteApks struct {
|
||||
name string
|
||||
moduleName string
|
||||
stem string
|
||||
partition string
|
||||
// what we write from what
|
||||
expected map[string]string
|
||||
expectedZipEntries map[string]string
|
||||
expectedApkcerts []string
|
||||
}
|
||||
|
||||
func TestWriteZip(t *testing.T) {
|
||||
testCases := []testCaseWriteZip{
|
||||
func TestWriteApks(t *testing.T) {
|
||||
testCases := []testCaseWriteApks{
|
||||
{
|
||||
name: "splits",
|
||||
moduleName: "mybase",
|
||||
stem: "Foo",
|
||||
expected: map[string]string{
|
||||
partition: "system",
|
||||
expectedZipEntries: map[string]string{
|
||||
"Foo.apk": "splits/mybase-master.apk",
|
||||
"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
|
||||
},
|
||||
expectedApkcerts: []string{
|
||||
`name="Foo-xhdpi.apk" certificate="PRESIGNED" private_key="" partition="system"`,
|
||||
`name="Foo.apk" certificate="PRESIGNED" private_key="" partition="system"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "universal",
|
||||
moduleName: "base",
|
||||
stem: "Bar",
|
||||
expected: map[string]string{
|
||||
partition: "product",
|
||||
expectedZipEntries: map[string]string{
|
||||
"Bar.apk": "universal.apk",
|
||||
},
|
||||
expectedApkcerts: []string{
|
||||
`name="Bar.apk" certificate="PRESIGNED" private_key="" partition="product"`,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
apkSet := ApkSet{entries: make(map[string]*zip.File)}
|
||||
sel := SelectionResult{moduleName: testCase.moduleName}
|
||||
for _, in := range testCase.expected {
|
||||
for _, in := range testCase.expectedZipEntries {
|
||||
apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
|
||||
sel.entries = append(sel.entries, in)
|
||||
}
|
||||
writer := testZip2ZipWriter{make(map[string]string)}
|
||||
config := TargetConfig{stem: testCase.stem}
|
||||
if err := apkSet.writeApks(sel, config, writer); err != nil {
|
||||
apkcerts, err := apkSet.writeApks(sel, config, writer, testCase.partition)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.expected, writer.entries) {
|
||||
t.Errorf("expected %v, got %v", testCase.expected, writer.entries)
|
||||
if !reflect.DeepEqual(testCase.expectedZipEntries, writer.entries) {
|
||||
t.Errorf("expected zip entries %v, got %v", testCase.expectedZipEntries, writer.entries)
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.expectedApkcerts, apkcerts) {
|
||||
t.Errorf("expected apkcerts %v, got %v", testCase.expectedApkcerts, apkcerts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -716,6 +716,7 @@ func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
func(entries *android.AndroidMkEntries) {
|
||||
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged())
|
||||
entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile)
|
||||
entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
|
||||
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
|
||||
},
|
||||
},
|
||||
|
|
13
java/app.go
13
java/app.go
|
@ -78,6 +78,7 @@ type AndroidAppSet struct {
|
|||
properties AndroidAppSetProperties
|
||||
packedOutput android.WritablePath
|
||||
masterFile string
|
||||
apkcertsFile android.ModuleOutPath
|
||||
}
|
||||
|
||||
func (as *AndroidAppSet) Name() string {
|
||||
|
@ -129,6 +130,7 @@ func SupportedAbis(ctx android.ModuleContext) []string {
|
|||
|
||||
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
|
||||
as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
|
||||
// We are assuming here that the master file in the APK
|
||||
// set has `.apk` suffix. If it doesn't the build will fail.
|
||||
// APK sets containing APEX files are handled elsewhere.
|
||||
|
@ -141,16 +143,19 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext)
|
|||
// TODO(asmundak): do we support device features
|
||||
ctx.Build(pctx,
|
||||
android.BuildParams{
|
||||
Rule: extractMatchingApks,
|
||||
Description: "Extract APKs from APK set",
|
||||
Output: as.packedOutput,
|
||||
Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
|
||||
Rule: extractMatchingApks,
|
||||
Description: "Extract APKs from APK set",
|
||||
Output: as.packedOutput,
|
||||
ImplicitOutput: as.apkcertsFile,
|
||||
Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
|
||||
Args: map[string]string{
|
||||
"abis": strings.Join(SupportedAbis(ctx), ","),
|
||||
"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
|
||||
"screen-densities": screenDensities,
|
||||
"sdk-version": ctx.Config().PlatformSdkVersion(),
|
||||
"stem": as.BaseModuleName(),
|
||||
"apkcerts": as.apkcertsFile.String(),
|
||||
"partition": as.PartitionTag(ctx.DeviceConfig()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ func TestAndroidAppSet(t *testing.T) {
|
|||
name: "foo",
|
||||
set: "prebuilts/apks/app.apks",
|
||||
prerelease: true,
|
||||
}`)
|
||||
}`)
|
||||
module := ctx.ModuleForTests("foo", "android_common")
|
||||
const packedSplitApks = "foo.zip"
|
||||
params := module.Output(packedSplitApks)
|
||||
|
@ -157,6 +157,9 @@ func TestAndroidAppSet(t *testing.T) {
|
|||
if s := params.Args["allow-prereleased"]; s != "true" {
|
||||
t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s)
|
||||
}
|
||||
if s := params.Args["partition"]; s != "system" {
|
||||
t.Errorf("wrong partition value: '%s', expected 'system'", s)
|
||||
}
|
||||
mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
|
||||
actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"]
|
||||
expectedMaster := []string{"foo.apk"}
|
||||
|
|
|
@ -120,10 +120,11 @@ var (
|
|||
`${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
|
||||
`-sdk-version=${sdk-version} -abis=${abis} ` +
|
||||
`--screen-densities=${screen-densities} --stem=${stem} ` +
|
||||
`-apkcerts=${apkcerts} -partition=${partition} ` +
|
||||
`${in}`,
|
||||
CommandDeps: []string{"${config.ExtractApksCmd}"},
|
||||
},
|
||||
"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem")
|
||||
"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition")
|
||||
|
||||
turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine",
|
||||
blueprint.RuleParams{
|
||||
|
|
Loading…
Reference in a new issue