Loading cmd/extract_apks/main.go +32 −7 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import ( "math" "os" "regexp" "sort" "strings" "github.com/golang/protobuf/proto" Loading Loading @@ -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 Loading Loading @@ -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) Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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) Loading Loading @@ -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) Loading cmd/extract_apks/main_test.go +27 −11 Original line number Diff line number Diff line Loading @@ -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" ) Loading Loading @@ -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) } } } java/androidmk.go +1 −0 Original line number Diff line number Diff line Loading @@ -719,6 +719,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...) }, }, Loading java/app.go +9 −4 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ type AndroidAppSet struct { properties AndroidAppSetProperties packedOutput android.WritablePath masterFile string apkcertsFile android.ModuleOutPath } func (as *AndroidAppSet) Name() string { Loading Loading @@ -130,6 +131,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. Loading @@ -145,6 +147,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) 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), ","), Loading @@ -152,6 +155,8 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) "screen-densities": screenDensities, "sdk-version": ctx.Config().PlatformSdkVersion(), "stem": as.BaseModuleName(), "apkcerts": as.apkcertsFile.String(), "partition": as.PartitionTag(ctx.DeviceConfig()), }, }) } Loading java/app_test.go +4 −1 Original line number Diff line number Diff line Loading @@ -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"} Loading Loading
cmd/extract_apks/main.go +32 −7 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import ( "math" "os" "regexp" "sort" "strings" "github.com/golang/protobuf/proto" Loading Loading @@ -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 Loading Loading @@ -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) Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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) Loading Loading @@ -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) Loading
cmd/extract_apks/main_test.go +27 −11 Original line number Diff line number Diff line Loading @@ -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" ) Loading Loading @@ -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) } } }
java/androidmk.go +1 −0 Original line number Diff line number Diff line Loading @@ -719,6 +719,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...) }, }, Loading
java/app.go +9 −4 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ type AndroidAppSet struct { properties AndroidAppSetProperties packedOutput android.WritablePath masterFile string apkcertsFile android.ModuleOutPath } func (as *AndroidAppSet) Name() string { Loading Loading @@ -130,6 +131,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. Loading @@ -145,6 +147,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) 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), ","), Loading @@ -152,6 +155,8 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) "screen-densities": screenDensities, "sdk-version": ctx.Config().PlatformSdkVersion(), "stem": as.BaseModuleName(), "apkcerts": as.apkcertsFile.String(), "partition": as.PartitionTag(ctx.DeviceConfig()), }, }) } Loading
java/app_test.go +4 −1 Original line number Diff line number Diff line Loading @@ -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"} Loading