Loading java/androidmk.go +26 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,32 @@ func (dstubs *Droidstubs) AndroidMk() android.AndroidMkData { } } func (app *AndroidAppImport) AndroidMk() android.AndroidMkData { return android.AndroidMkData{ Class: "APPS", OutputFile: android.OptionalPathForPath(app.outputFile), Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk", Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { if Bool(app.properties.Privileged) { fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true") } if app.certificate != nil { fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String()) } else { fmt.Fprintln(w, "LOCAL_CERTIFICATE := PRESIGNED") } if len(app.properties.Overrides) > 0 { fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES :=", strings.Join(app.properties.Overrides, " ")) } if len(app.dexpreopter.builtInstalled) > 0 { fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", app.dexpreopter.builtInstalled) } }, }, } } func androidMkWriteTestData(data android.Paths, ret *android.AndroidMkData) { var testFiles []string for _, d := range data { Loading java/app.go +158 −24 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ func init() { android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory) android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) android.RegisterModuleType("android_app_import", AndroidAppImportFactory) } // AndroidManifest.xml merging Loading Loading @@ -302,37 +303,38 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext return jniJarFile } func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx android.ModuleContext) []Certificate { cert := a.getCertString(ctx) certModule := android.SrcIsModule(cert) if certModule != "" { a.certificate = certificateDeps[0] certificateDeps = certificateDeps[1:] } else if cert != "" { // Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it // isn't a cert module reference. Also checks and enforces system cert restriction if applicable. func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate { if android.SrcIsModule(certPropValue) == "" { var mainCert Certificate if certPropValue != "" { defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) a.certificate = Certificate{ defaultDir.Join(ctx, cert+".x509.pem"), defaultDir.Join(ctx, cert+".pk8"), mainCert = Certificate{ defaultDir.Join(ctx, certPropValue+".x509.pem"), defaultDir.Join(ctx, certPropValue+".pk8"), } } else { pem, key := ctx.Config().DefaultAppCertificate(ctx) a.certificate = Certificate{pem, key} mainCert = Certificate{pem, key} } certificates = append([]Certificate{mainCert}, certificates...) } if !a.Module.Platform() { certPath := a.certificate.Pem.String() if !m.Platform() { certPath := certificates[0].Pem.String() systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String() if strings.HasPrefix(certPath, systemCertPath) { enforceSystemCert := ctx.Config().EnforceSystemCertificate() whitelist := ctx.Config().EnforceSystemCertificateWhitelist() if enforceSystemCert && !inList(a.Module.Name(), whitelist) { if enforceSystemCert && !inList(m.Name(), whitelist) { ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.") } } } return append([]Certificate{a.certificate}, certificateDeps...) return certificates } func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { Loading @@ -346,25 +348,26 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile := a.dexBuildActions(ctx) jniLibs, certificateDeps := a.collectAppDeps(ctx) jniLibs, certificateDeps := collectAppDeps(ctx) jniJarFile := a.jniBuildActions(jniLibs, ctx) if ctx.Failed() { return } certificates := a.certificateBuildActions(certificateDeps, ctx) certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx) a.certificate = certificates[0] // Build a final signed app package. // TODO(jungjw): Consider changing this to installApkName. packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk") CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates) CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates) a.outputFile = packageFile for _, split := range a.aapt.splits { // Sign the split APKs packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk") CreateAppPackage(ctx, packageFile, split.path, nil, nil, certificates) CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) } Loading @@ -390,7 +393,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { } } func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) { func collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) { var jniLibs []jniLib var certificates []Certificate Loading @@ -412,7 +415,6 @@ func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Cert } } else { ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName) } } else if tag == certificateTag { if dep, ok := module.(*AndroidAppCertificate); ok { Loading Loading @@ -620,3 +622,135 @@ func OverrideAndroidAppModuleFactory() android.Module { android.InitOverrideModule(m) return m } type AndroidAppImport struct { android.ModuleBase android.DefaultableModuleBase prebuilt android.Prebuilt properties AndroidAppImportProperties outputFile android.Path certificate *Certificate dexpreopter } type AndroidAppImportProperties struct { // A prebuilt apk to import Apk string // 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 // Set this flag to true if the prebuilt apk is already signed. The certificate property must not // be set for presigned modules. Presigned *bool // Specifies that this app should be installed to the priv-app directory, // where the system will grant it additional privileges not available to // normal apps. Privileged *bool // Names of modules to be overridden. Listed modules can only be other binaries // (in Make or Soong). // This does not completely prevent installation of the overridden binaries, but if both // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed // from PRODUCT_PACKAGES. Overrides []string } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { cert := android.SrcIsModule(String(a.properties.Certificate)) if cert != "" { ctx.AddDependency(ctx.Module(), certificateTag, cert) } } func (a *AndroidAppImport) uncompressEmbeddedJniLibs( ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) { rule := android.NewRuleBuilder() rule.Command(). Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). FlagWithInput("-i ", inputPath). FlagWithOutput("-o ", outputPath). FlagWithArg("-0 ", "'lib/**/*.so'"). Textf(`; else cp -f %s %s; fi`, inputPath, outputPath) rule.Build(pctx, ctx, "uncompress-embedded-jni-libs", "Uncompress embedded JIN libs") } func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if String(a.properties.Certificate) == "" && !Bool(a.properties.Presigned) { ctx.PropertyErrorf("certificate", "No certificate specified for prebuilt") } if String(a.properties.Certificate) != "" && Bool(a.properties.Presigned) { ctx.PropertyErrorf("certificate", "Certificate can't be specified for presigned modules") } _, certificates := collectAppDeps(ctx) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_DPI_VARIANTS // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) // TODO: Install or embed JNI libraries // Uncompress JNI libraries in the apk jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk") a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath) // TODO: Uncompress dex if applicable installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName()) a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk") a.dexpreopter.isInstallable = true a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned) dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed) // Sign or align the package // TODO: Handle EXTERNAL if !Bool(a.properties.Presigned) { certificates = processMainCert(a.ModuleBase, *a.properties.Certificate, certificates, ctx) if len(certificates) != 1 { ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates) } a.certificate = &certificates[0] signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk") SignAppPackage(ctx, signed, dexOutput, certificates) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk") TransformZipAlign(ctx, alignedApk, dexOutput) a.outputFile = alignedApk } // TODO: Optionally compress the output apk. ctx.InstallFile(installDir, a.BaseModuleName()+".apk", a.outputFile) // TODO: androidmk converter jni libs } func (a *AndroidAppImport) Prebuilt() *android.Prebuilt { return &a.prebuilt } func (a *AndroidAppImport) Name() string { return a.prebuilt.Name(a.ModuleBase.Name()) } // android_app_import imports a prebuilt apk with additional processing specified in the module. func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} module.AddProperties(&module.properties) module.AddProperties(&module.dexpreoptProperties) InitJavaModule(module, android.DeviceSupported) android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk) return module } java/app_builder.go +7 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk", CommandDeps: []string{"${config.MergeZipsCmd}"}, }) func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) { unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" Loading @@ -83,6 +83,11 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath Output: unsignedApk, }) SignAppPackage(ctx, outputFile, unsignedApk, certificates) } func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) { var certificateArgs []string var deps android.Paths for _, c := range certificates { Loading @@ -93,7 +98,7 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath ctx.Build(pctx, android.BuildParams{ Rule: Signapk, Description: "signapk", Output: outputFile, Output: signedApk, Input: unsignedApk, Implicits: deps, Args: map[string]string{ Loading java/app_test.go +84 −0 Original line number Diff line number Diff line Loading @@ -968,3 +968,87 @@ func TestOverrideAndroidApp(t *testing.T) { } } } func TestAndroidAppImport(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", certificate: "platform", dex_preopt: { enabled: true, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { t.Errorf("can't find dexpreopt outputs") } // Check cert signing flag. signedApk := variant.Output("signed/foo.apk") signingFlag := signedApk.Args["certificates"] expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" if expected != signingFlag { t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) } } func TestAndroidAppImport_NoDexPreopt(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", certificate: "platform", dex_preopt: { enabled: false, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. They shouldn't exist. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil { t.Errorf("dexpreopt shouldn't have run.") } } func TestAndroidAppImport_Presigned(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", presigned: true, dex_preopt: { enabled: true, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { t.Errorf("can't find dexpreopt outputs") } // Make sure stripping wasn't done. stripRule := variant.Output("dexpreopt/foo.apk") if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") { t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command) } // Make sure signing was skipped and aligning was done instead. if variant.MaybeOutput("signed/foo.apk").Rule != nil { t.Errorf("signing rule shouldn't be included.") } if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil { t.Errorf("can't find aligning rule") } } java/dexpreopt.go +8 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ type dexpreopter struct { isSDKLibrary bool isTest bool isInstallable bool isPresignedPrebuilt bool builtInstalled string } Loading Loading @@ -177,6 +178,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true), ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false), PresignedPrebuilt: d.isPresignedPrebuilt, NoStripping: Bool(d.dexpreoptProperties.Dex_preopt.No_stripping), StripInputPath: dexJarFile, StripOutputPath: strippedDexJarFile.OutputPath, Loading Loading
java/androidmk.go +26 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,32 @@ func (dstubs *Droidstubs) AndroidMk() android.AndroidMkData { } } func (app *AndroidAppImport) AndroidMk() android.AndroidMkData { return android.AndroidMkData{ Class: "APPS", OutputFile: android.OptionalPathForPath(app.outputFile), Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk", Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { if Bool(app.properties.Privileged) { fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true") } if app.certificate != nil { fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String()) } else { fmt.Fprintln(w, "LOCAL_CERTIFICATE := PRESIGNED") } if len(app.properties.Overrides) > 0 { fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES :=", strings.Join(app.properties.Overrides, " ")) } if len(app.dexpreopter.builtInstalled) > 0 { fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", app.dexpreopter.builtInstalled) } }, }, } } func androidMkWriteTestData(data android.Paths, ret *android.AndroidMkData) { var testFiles []string for _, d := range data { Loading
java/app.go +158 −24 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ func init() { android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory) android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) android.RegisterModuleType("android_app_import", AndroidAppImportFactory) } // AndroidManifest.xml merging Loading Loading @@ -302,37 +303,38 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext return jniJarFile } func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx android.ModuleContext) []Certificate { cert := a.getCertString(ctx) certModule := android.SrcIsModule(cert) if certModule != "" { a.certificate = certificateDeps[0] certificateDeps = certificateDeps[1:] } else if cert != "" { // Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it // isn't a cert module reference. Also checks and enforces system cert restriction if applicable. func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate { if android.SrcIsModule(certPropValue) == "" { var mainCert Certificate if certPropValue != "" { defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) a.certificate = Certificate{ defaultDir.Join(ctx, cert+".x509.pem"), defaultDir.Join(ctx, cert+".pk8"), mainCert = Certificate{ defaultDir.Join(ctx, certPropValue+".x509.pem"), defaultDir.Join(ctx, certPropValue+".pk8"), } } else { pem, key := ctx.Config().DefaultAppCertificate(ctx) a.certificate = Certificate{pem, key} mainCert = Certificate{pem, key} } certificates = append([]Certificate{mainCert}, certificates...) } if !a.Module.Platform() { certPath := a.certificate.Pem.String() if !m.Platform() { certPath := certificates[0].Pem.String() systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String() if strings.HasPrefix(certPath, systemCertPath) { enforceSystemCert := ctx.Config().EnforceSystemCertificate() whitelist := ctx.Config().EnforceSystemCertificateWhitelist() if enforceSystemCert && !inList(a.Module.Name(), whitelist) { if enforceSystemCert && !inList(m.Name(), whitelist) { ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.") } } } return append([]Certificate{a.certificate}, certificateDeps...) return certificates } func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { Loading @@ -346,25 +348,26 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile := a.dexBuildActions(ctx) jniLibs, certificateDeps := a.collectAppDeps(ctx) jniLibs, certificateDeps := collectAppDeps(ctx) jniJarFile := a.jniBuildActions(jniLibs, ctx) if ctx.Failed() { return } certificates := a.certificateBuildActions(certificateDeps, ctx) certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx) a.certificate = certificates[0] // Build a final signed app package. // TODO(jungjw): Consider changing this to installApkName. packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk") CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates) CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates) a.outputFile = packageFile for _, split := range a.aapt.splits { // Sign the split APKs packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk") CreateAppPackage(ctx, packageFile, split.path, nil, nil, certificates) CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) } Loading @@ -390,7 +393,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { } } func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) { func collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) { var jniLibs []jniLib var certificates []Certificate Loading @@ -412,7 +415,6 @@ func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Cert } } else { ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName) } } else if tag == certificateTag { if dep, ok := module.(*AndroidAppCertificate); ok { Loading Loading @@ -620,3 +622,135 @@ func OverrideAndroidAppModuleFactory() android.Module { android.InitOverrideModule(m) return m } type AndroidAppImport struct { android.ModuleBase android.DefaultableModuleBase prebuilt android.Prebuilt properties AndroidAppImportProperties outputFile android.Path certificate *Certificate dexpreopter } type AndroidAppImportProperties struct { // A prebuilt apk to import Apk string // 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 // Set this flag to true if the prebuilt apk is already signed. The certificate property must not // be set for presigned modules. Presigned *bool // Specifies that this app should be installed to the priv-app directory, // where the system will grant it additional privileges not available to // normal apps. Privileged *bool // Names of modules to be overridden. Listed modules can only be other binaries // (in Make or Soong). // This does not completely prevent installation of the overridden binaries, but if both // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed // from PRODUCT_PACKAGES. Overrides []string } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { cert := android.SrcIsModule(String(a.properties.Certificate)) if cert != "" { ctx.AddDependency(ctx.Module(), certificateTag, cert) } } func (a *AndroidAppImport) uncompressEmbeddedJniLibs( ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) { rule := android.NewRuleBuilder() rule.Command(). Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). FlagWithInput("-i ", inputPath). FlagWithOutput("-o ", outputPath). FlagWithArg("-0 ", "'lib/**/*.so'"). Textf(`; else cp -f %s %s; fi`, inputPath, outputPath) rule.Build(pctx, ctx, "uncompress-embedded-jni-libs", "Uncompress embedded JIN libs") } func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if String(a.properties.Certificate) == "" && !Bool(a.properties.Presigned) { ctx.PropertyErrorf("certificate", "No certificate specified for prebuilt") } if String(a.properties.Certificate) != "" && Bool(a.properties.Presigned) { ctx.PropertyErrorf("certificate", "Certificate can't be specified for presigned modules") } _, certificates := collectAppDeps(ctx) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_DPI_VARIANTS // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) // TODO: Install or embed JNI libraries // Uncompress JNI libraries in the apk jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk") a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath) // TODO: Uncompress dex if applicable installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName()) a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk") a.dexpreopter.isInstallable = true a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned) dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed) // Sign or align the package // TODO: Handle EXTERNAL if !Bool(a.properties.Presigned) { certificates = processMainCert(a.ModuleBase, *a.properties.Certificate, certificates, ctx) if len(certificates) != 1 { ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates) } a.certificate = &certificates[0] signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk") SignAppPackage(ctx, signed, dexOutput, certificates) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk") TransformZipAlign(ctx, alignedApk, dexOutput) a.outputFile = alignedApk } // TODO: Optionally compress the output apk. ctx.InstallFile(installDir, a.BaseModuleName()+".apk", a.outputFile) // TODO: androidmk converter jni libs } func (a *AndroidAppImport) Prebuilt() *android.Prebuilt { return &a.prebuilt } func (a *AndroidAppImport) Name() string { return a.prebuilt.Name(a.ModuleBase.Name()) } // android_app_import imports a prebuilt apk with additional processing specified in the module. func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} module.AddProperties(&module.properties) module.AddProperties(&module.dexpreoptProperties) InitJavaModule(module, android.DeviceSupported) android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk) return module }
java/app_builder.go +7 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk", CommandDeps: []string{"${config.MergeZipsCmd}"}, }) func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) { unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" Loading @@ -83,6 +83,11 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath Output: unsignedApk, }) SignAppPackage(ctx, outputFile, unsignedApk, certificates) } func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) { var certificateArgs []string var deps android.Paths for _, c := range certificates { Loading @@ -93,7 +98,7 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath ctx.Build(pctx, android.BuildParams{ Rule: Signapk, Description: "signapk", Output: outputFile, Output: signedApk, Input: unsignedApk, Implicits: deps, Args: map[string]string{ Loading
java/app_test.go +84 −0 Original line number Diff line number Diff line Loading @@ -968,3 +968,87 @@ func TestOverrideAndroidApp(t *testing.T) { } } } func TestAndroidAppImport(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", certificate: "platform", dex_preopt: { enabled: true, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { t.Errorf("can't find dexpreopt outputs") } // Check cert signing flag. signedApk := variant.Output("signed/foo.apk") signingFlag := signedApk.Args["certificates"] expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" if expected != signingFlag { t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) } } func TestAndroidAppImport_NoDexPreopt(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", certificate: "platform", dex_preopt: { enabled: false, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. They shouldn't exist. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil { t.Errorf("dexpreopt shouldn't have run.") } } func TestAndroidAppImport_Presigned(t *testing.T) { ctx := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", presigned: true, dex_preopt: { enabled: true, }, } `) variant := ctx.ModuleForTests("foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { t.Errorf("can't find dexpreopt outputs") } // Make sure stripping wasn't done. stripRule := variant.Output("dexpreopt/foo.apk") if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") { t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command) } // Make sure signing was skipped and aligning was done instead. if variant.MaybeOutput("signed/foo.apk").Rule != nil { t.Errorf("signing rule shouldn't be included.") } if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil { t.Errorf("can't find aligning rule") } }
java/dexpreopt.go +8 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ type dexpreopter struct { isSDKLibrary bool isTest bool isInstallable bool isPresignedPrebuilt bool builtInstalled string } Loading Loading @@ -177,6 +178,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true), ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false), PresignedPrebuilt: d.isPresignedPrebuilt, NoStripping: Bool(d.dexpreoptProperties.Dex_preopt.No_stripping), StripInputPath: dexJarFile, StripOutputPath: strippedDexJarFile.OutputPath, Loading