Loading android/prebuilt.go +5 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,11 @@ func (p *Prebuilt) Name(name string) string { return "prebuilt_" + name } // The below source-related functions and the srcs, src fields are based on an assumption that // prebuilt modules have a static source property at the moment. Currently there is only one // exception, android_app_import, which chooses a source file depending on the product's DPI // preference configs. We'll want to add native support for dynamic source cases if we end up having // more modules like this. func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { if p.srcs != nil { if len(*p.srcs) == 0 { Loading java/app.go +79 −5 Original line number Diff line number Diff line Loading @@ -17,17 +17,20 @@ package java // This file contains the module types for compiling Android apps. import ( "path/filepath" "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" "path/filepath" "reflect" "strings" "android/soong/android" "android/soong/cc" "android/soong/tradefed" ) var supportedDpis = [...]string{"Ldpi", "Mdpi", "Hdpi", "Xhdpi", "Xxhdpi", "Xxxhdpi"} var dpiVariantsStruct reflect.Type func init() { android.RegisterModuleType("android_app", AndroidAppFactory) android.RegisterModuleType("android_test", AndroidTestFactory) Loading @@ -35,6 +38,22 @@ func init() { android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) android.RegisterModuleType("android_app_import", AndroidAppImportFactory) // Dynamically construct a struct for the dpi_variants property in android_app_import. perDpiStruct := reflect.StructOf([]reflect.StructField{ { Name: "Apk", Type: reflect.TypeOf((*string)(nil)), }, }) dpiVariantsFields := make([]reflect.StructField, len(supportedDpis)) for i, dpi := range supportedDpis { dpiVariantsFields[i] = reflect.StructField{ Name: string(dpi), Type: perDpiStruct, } } dpiVariantsStruct = reflect.StructOf(dpiVariantsFields) } // AndroidManifest.xml merging Loading Loading @@ -635,6 +654,26 @@ type AndroidAppImportProperties struct { // A prebuilt apk to import Apk string // Per-DPI settings. This property makes it possible to specify a different source apk path for // each DPI. // // Example: // // android_app_import { // name: "example_import", // apk: "prebuilts/example.apk", // dpi_variants: { // mdpi: { // apk: "prebuilts/example_mdpi.apk", // }, // xhdpi: { // apk: "prebuilts/example_xhdpi.apk", // }, // }, // certificate: "PRESIGNED", // } Dpi_variants interface{} // The name of a certificate in the default certificate directory, blank to use the default // product certificate, or an android_app_certificate module name in the form ":module". Certificate *string Loading @@ -656,6 +695,41 @@ type AndroidAppImportProperties struct { Overrides []string } func getApkPathForDpi(dpiVariantsValue reflect.Value, dpi string) string { dpiField := dpiVariantsValue.FieldByName(proptools.FieldNameForProperty(dpi)) if !dpiField.IsValid() { return "" } apkValue := dpiField.FieldByName("Apk").Elem() if apkValue.IsValid() { return apkValue.String() } return "" } // Chooses a source APK path to use based on the module's per-DPI settings and the product config. func (a *AndroidAppImport) getSrcApkPath(ctx android.ModuleContext) string { config := ctx.Config() dpiVariantsValue := reflect.ValueOf(a.properties.Dpi_variants).Elem() if !dpiVariantsValue.IsValid() { return a.properties.Apk } // Match PRODUCT_AAPT_PREF_CONFIG first and then PRODUCT_AAPT_PREBUILT_DPI. if config.ProductAAPTPreferredConfig() != "" { if apk := getApkPathForDpi(dpiVariantsValue, config.ProductAAPTPreferredConfig()); apk != "" { return apk } } for _, dpi := range config.ProductAAPTPrebuiltDPI() { if apk := getApkPathForDpi(dpiVariantsValue, dpi); apk != "" { return apk } } // No match. Use the generic one. return a.properties.Apk } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { cert := android.SrcIsModule(String(a.properties.Certificate)) if cert != "" { Loading Loading @@ -701,10 +775,9 @@ func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext _, certificates := collectAppDeps(ctx) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_DPI_VARIANTS // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) srcApk := android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx)) // TODO: Install or embed JNI libraries Loading Loading @@ -754,6 +827,7 @@ func (a *AndroidAppImport) Name() string { // android_app_import imports a prebuilt apk with additional processing specified in the module. func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface() module.AddProperties(&module.properties) module.AddProperties(&module.dexpreoptProperties) Loading java/app_test.go +84 −3 Original line number Diff line number Diff line Loading @@ -15,15 +15,18 @@ package java import ( "android/soong/android" "android/soong/cc" "fmt" "path/filepath" "reflect" "regexp" "sort" "strings" "testing" "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/cc" ) var ( Loading Loading @@ -1052,3 +1055,81 @@ func TestAndroidAppImport_Presigned(t *testing.T) { t.Errorf("can't find aligning rule") } } func TestAndroidAppImport_DpiVariants(t *testing.T) { bp := ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", dpi_variants: { xhdpi: { apk: "prebuilts/apk/app_xhdpi.apk", }, xxhdpi: { apk: "prebuilts/apk/app_xxhdpi.apk", }, }, certificate: "PRESIGNED", dex_preopt: { enabled: true, }, } ` testCases := []struct { name string aaptPreferredConfig *string aaptPrebuiltDPI []string expected string }{ { name: "no preferred", aaptPreferredConfig: nil, aaptPrebuiltDPI: []string{}, expected: "prebuilts/apk/app.apk", }, { name: "AAPTPreferredConfig matches", aaptPreferredConfig: proptools.StringPtr("xhdpi"), aaptPrebuiltDPI: []string{"xxhdpi", "lhdpi"}, expected: "prebuilts/apk/app_xhdpi.apk", }, { name: "AAPTPrebuiltDPI matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"}, expected: "prebuilts/apk/app_xxhdpi.apk", }, { name: "non-first AAPTPrebuiltDPI matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"ldpi", "xhdpi"}, expected: "prebuilts/apk/app_xhdpi.apk", }, { name: "no matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"}, expected: "prebuilts/apk/app.apk", }, } jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") for _, test := range testCases { config := testConfig(nil) config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI ctx := testAppContext(config, bp, nil) run(t, ctx, config) variant := ctx.ModuleForTests("foo", "android_common") jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) if len(matches) != 2 { t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) } if test.expected != matches[1] { t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) } } } java/java_test.go +3 −1 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ func testContext(config android.Config, bp string, "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), "prebuilts/apk/app.apk": nil, "prebuilts/apk/app_xhdpi.apk": nil, "prebuilts/apk/app_xxhdpi.apk": nil, // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, Loading Loading
android/prebuilt.go +5 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,11 @@ func (p *Prebuilt) Name(name string) string { return "prebuilt_" + name } // The below source-related functions and the srcs, src fields are based on an assumption that // prebuilt modules have a static source property at the moment. Currently there is only one // exception, android_app_import, which chooses a source file depending on the product's DPI // preference configs. We'll want to add native support for dynamic source cases if we end up having // more modules like this. func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { if p.srcs != nil { if len(*p.srcs) == 0 { Loading
java/app.go +79 −5 Original line number Diff line number Diff line Loading @@ -17,17 +17,20 @@ package java // This file contains the module types for compiling Android apps. import ( "path/filepath" "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" "path/filepath" "reflect" "strings" "android/soong/android" "android/soong/cc" "android/soong/tradefed" ) var supportedDpis = [...]string{"Ldpi", "Mdpi", "Hdpi", "Xhdpi", "Xxhdpi", "Xxxhdpi"} var dpiVariantsStruct reflect.Type func init() { android.RegisterModuleType("android_app", AndroidAppFactory) android.RegisterModuleType("android_test", AndroidTestFactory) Loading @@ -35,6 +38,22 @@ func init() { android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) android.RegisterModuleType("android_app_import", AndroidAppImportFactory) // Dynamically construct a struct for the dpi_variants property in android_app_import. perDpiStruct := reflect.StructOf([]reflect.StructField{ { Name: "Apk", Type: reflect.TypeOf((*string)(nil)), }, }) dpiVariantsFields := make([]reflect.StructField, len(supportedDpis)) for i, dpi := range supportedDpis { dpiVariantsFields[i] = reflect.StructField{ Name: string(dpi), Type: perDpiStruct, } } dpiVariantsStruct = reflect.StructOf(dpiVariantsFields) } // AndroidManifest.xml merging Loading Loading @@ -635,6 +654,26 @@ type AndroidAppImportProperties struct { // A prebuilt apk to import Apk string // Per-DPI settings. This property makes it possible to specify a different source apk path for // each DPI. // // Example: // // android_app_import { // name: "example_import", // apk: "prebuilts/example.apk", // dpi_variants: { // mdpi: { // apk: "prebuilts/example_mdpi.apk", // }, // xhdpi: { // apk: "prebuilts/example_xhdpi.apk", // }, // }, // certificate: "PRESIGNED", // } Dpi_variants interface{} // The name of a certificate in the default certificate directory, blank to use the default // product certificate, or an android_app_certificate module name in the form ":module". Certificate *string Loading @@ -656,6 +695,41 @@ type AndroidAppImportProperties struct { Overrides []string } func getApkPathForDpi(dpiVariantsValue reflect.Value, dpi string) string { dpiField := dpiVariantsValue.FieldByName(proptools.FieldNameForProperty(dpi)) if !dpiField.IsValid() { return "" } apkValue := dpiField.FieldByName("Apk").Elem() if apkValue.IsValid() { return apkValue.String() } return "" } // Chooses a source APK path to use based on the module's per-DPI settings and the product config. func (a *AndroidAppImport) getSrcApkPath(ctx android.ModuleContext) string { config := ctx.Config() dpiVariantsValue := reflect.ValueOf(a.properties.Dpi_variants).Elem() if !dpiVariantsValue.IsValid() { return a.properties.Apk } // Match PRODUCT_AAPT_PREF_CONFIG first and then PRODUCT_AAPT_PREBUILT_DPI. if config.ProductAAPTPreferredConfig() != "" { if apk := getApkPathForDpi(dpiVariantsValue, config.ProductAAPTPreferredConfig()); apk != "" { return apk } } for _, dpi := range config.ProductAAPTPrebuiltDPI() { if apk := getApkPathForDpi(dpiVariantsValue, dpi); apk != "" { return apk } } // No match. Use the generic one. return a.properties.Apk } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { cert := android.SrcIsModule(String(a.properties.Certificate)) if cert != "" { Loading Loading @@ -701,10 +775,9 @@ func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext _, certificates := collectAppDeps(ctx) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_DPI_VARIANTS // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) srcApk := android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx)) // TODO: Install or embed JNI libraries Loading Loading @@ -754,6 +827,7 @@ func (a *AndroidAppImport) Name() string { // android_app_import imports a prebuilt apk with additional processing specified in the module. func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface() module.AddProperties(&module.properties) module.AddProperties(&module.dexpreoptProperties) Loading
java/app_test.go +84 −3 Original line number Diff line number Diff line Loading @@ -15,15 +15,18 @@ package java import ( "android/soong/android" "android/soong/cc" "fmt" "path/filepath" "reflect" "regexp" "sort" "strings" "testing" "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/cc" ) var ( Loading Loading @@ -1052,3 +1055,81 @@ func TestAndroidAppImport_Presigned(t *testing.T) { t.Errorf("can't find aligning rule") } } func TestAndroidAppImport_DpiVariants(t *testing.T) { bp := ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", dpi_variants: { xhdpi: { apk: "prebuilts/apk/app_xhdpi.apk", }, xxhdpi: { apk: "prebuilts/apk/app_xxhdpi.apk", }, }, certificate: "PRESIGNED", dex_preopt: { enabled: true, }, } ` testCases := []struct { name string aaptPreferredConfig *string aaptPrebuiltDPI []string expected string }{ { name: "no preferred", aaptPreferredConfig: nil, aaptPrebuiltDPI: []string{}, expected: "prebuilts/apk/app.apk", }, { name: "AAPTPreferredConfig matches", aaptPreferredConfig: proptools.StringPtr("xhdpi"), aaptPrebuiltDPI: []string{"xxhdpi", "lhdpi"}, expected: "prebuilts/apk/app_xhdpi.apk", }, { name: "AAPTPrebuiltDPI matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"}, expected: "prebuilts/apk/app_xxhdpi.apk", }, { name: "non-first AAPTPrebuiltDPI matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"ldpi", "xhdpi"}, expected: "prebuilts/apk/app_xhdpi.apk", }, { name: "no matches", aaptPreferredConfig: proptools.StringPtr("mdpi"), aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"}, expected: "prebuilts/apk/app.apk", }, } jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") for _, test := range testCases { config := testConfig(nil) config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI ctx := testAppContext(config, bp, nil) run(t, ctx, config) variant := ctx.ModuleForTests("foo", "android_common") jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) if len(matches) != 2 { t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) } if test.expected != matches[1] { t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) } } }
java/java_test.go +3 −1 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ func testContext(config android.Config, bp string, "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), "prebuilts/apk/app.apk": nil, "prebuilts/apk/app_xhdpi.apk": nil, "prebuilts/apk/app_xxhdpi.apk": nil, // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, Loading