diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/androidmk.go | 8 | ||||
-rw-r--r-- | java/androidmk_test.go | 36 | ||||
-rwxr-xr-x | java/app.go | 64 | ||||
-rw-r--r-- | java/app_builder.go | 16 | ||||
-rw-r--r-- | java/app_test.go | 60 | ||||
-rw-r--r-- | java/dexpreopt.go | 7 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 226 | ||||
-rw-r--r-- | java/dexpreopt_bootjars_test.go | 2 | ||||
-rw-r--r-- | java/dexpreopt_config.go | 51 | ||||
-rw-r--r-- | java/hiddenapi_singleton.go | 26 | ||||
-rw-r--r-- | java/java.go | 57 | ||||
-rw-r--r-- | java/java_test.go | 24 | ||||
-rw-r--r-- | java/sdk.go | 2 | ||||
-rw-r--r-- | java/sdk_library.go | 99 | ||||
-rw-r--r-- | java/sdk_test.go | 4 | ||||
-rw-r--r-- | java/testing.go | 4 |
16 files changed, 509 insertions, 177 deletions
diff --git a/java/androidmk.go b/java/androidmk.go index d76e29b21..136bb36ca 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -72,6 +72,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if !hideFromMake { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", + DistFile: android.OptionalPathForPath(library.distFile), OutputFile: android.OptionalPathForPath(library.outputFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ @@ -275,7 +276,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { } func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { - if !app.IsForPlatform() { + if !app.IsForPlatform() || app.appProperties.HideFromMake { return []android.AndroidMkEntries{android.AndroidMkEntries{ Disabled: true, }} @@ -288,6 +289,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { func(entries *android.AndroidMkEntries) { // App module names can be overridden. entries.SetString("LOCAL_MODULE", app.installApkName) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall) entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage) if app.dexJarFile != nil { entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile) @@ -347,6 +349,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { for _, jniLib := range app.installJniLibs { entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name) } + if len(app.jniCoverageOutputs) > 0 { + entries.AddStrings("LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.jniCoverageOutputs.Strings()...) + } if len(app.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled) } @@ -542,6 +547,7 @@ func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries { func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", + DistFile: android.OptionalPathForPath(dstubs.apiFile), OutputFile: android.OptionalPathForPath(dstubs.stubsSrcJar), Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ diff --git a/java/androidmk_test.go b/java/androidmk_test.go index acc6bf039..7daa6244f 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -16,6 +16,7 @@ package java import ( "reflect" + "strings" "testing" "android/soong/android" @@ -133,3 +134,38 @@ func TestHostdexSpecificRequired(t *testing.T) { t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual) } } + +func TestDistWithTag(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo_without_tag", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["hi"], + }, + } + java_library { + name: "foo_with_tag", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["hi"], + tag: ".jar", + }, + } + `) + + without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) + with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) + + if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries)) + } + if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile) + } + if without_tag_entries[0].DistFile.Valid() { + t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile) + } +} diff --git a/java/app.go b/java/app.go index 346f1551d..6a0aa8f41 100755 --- a/java/app.go +++ b/java/app.go @@ -105,6 +105,11 @@ type appProperties struct { // If set, find and merge all NOTICE files that this module and its dependencies have and store // it in the APK as an asset. Embed_notices *bool + + // cc.Coverage related properties + PreventInstall bool `blueprint:"mutated"` + HideFromMake bool `blueprint:"mutated"` + IsCoverageVariant bool `blueprint:"mutated"` } // android_app properties that can be overridden by override_android_app @@ -133,7 +138,8 @@ type AndroidApp struct { overridableAppProperties overridableAppProperties - installJniLibs []jniLib + installJniLibs []jniLib + jniCoverageOutputs android.Paths bundleFile android.Path @@ -171,6 +177,10 @@ func (a *AndroidApp) Certificate() Certificate { return a.certificate } +func (a *AndroidApp) JniCoverageOutputs() android.Paths { + return a.jniCoverageOutputs +} + var _ AndroidLibraryDependency = (*AndroidApp)(nil) type Certificate struct { @@ -380,6 +390,11 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext if a.shouldEmbedJnis(ctx) { jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip") TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx)) + for _, jni := range jniLibs { + if jni.coverageFile.Valid() { + a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path()) + } + } } else { a.installJniLibs = jniLibs } @@ -521,14 +536,28 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { // Build a final signed app package. packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk") - CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps) + v4SigningRequested := Bool(a.Module.deviceProperties.V4_signature) + var v4SignatureFile android.WritablePath = nil + if v4SigningRequested { + v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+".apk.idsig") + } + CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile) a.outputFile = packageFile + if v4SigningRequested { + a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) + } for _, split := range a.aapt.splits { // Sign the split APKs packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk") - CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps) + if v4SigningRequested { + v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig") + } + CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) + if v4SigningRequested { + a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) + } } // Build an app bundle. @@ -582,9 +611,10 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps if lib.Valid() { jniLibs = append(jniLibs, jniLib{ - name: ctx.OtherModuleName(module), - path: path, - target: module.Target(), + name: ctx.OtherModuleName(module), + path: path, + target: module.Target(), + coverageFile: dep.CoverageOutputFile(), }) } else { ctx.ModuleErrorf("dependency %q missing output file", otherName) @@ -638,6 +668,24 @@ func (a *AndroidApp) Privileged() bool { return Bool(a.appProperties.Privileged) } +func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { + return ctx.Device() && (ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled()) +} + +func (a *AndroidApp) PreventInstall() { + a.appProperties.PreventInstall = true +} + +func (a *AndroidApp) HideFromMake() { + a.appProperties.HideFromMake = true +} + +func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) { + a.appProperties.IsCoverageVariant = coverage +} + +var _ cc.Coverage = (*AndroidApp)(nil) + // android_app compiles sources and Android resources into an Android application package `.apk` file. func AndroidAppFactory() android.Module { module := &AndroidApp{} @@ -1129,7 +1177,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } a.certificate = certificates[0] signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk") - SignAppPackage(ctx, signed, dexOutput, certificates) + SignAppPackage(ctx, signed, dexOutput, certificates, nil) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk") @@ -1334,7 +1382,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC _, certificates := collectAppDeps(ctx, false, false) certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") - SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates) + SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil) r.certificate = certificates[0] r.outputFile = signed diff --git a/java/app_builder.go b/java/app_builder.go index 5e7fbe6de..b2780bc90 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -45,7 +45,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk", }) func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, - packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) { + packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath) { unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" unsignedApk := android.PathForModuleOut(ctx, unsignedApkName) @@ -66,10 +66,10 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa Implicits: deps, }) - SignAppPackage(ctx, outputFile, unsignedApk, certificates) + SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile) } -func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) { +func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, v4SignatureFile android.WritablePath) { var certificateArgs []string var deps android.Paths @@ -78,14 +78,22 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u deps = append(deps, c.Pem, c.Key) } + outputFiles := android.WritablePaths{signedApk} + var flag string = "" + if v4SignatureFile != nil { + outputFiles = append(outputFiles, v4SignatureFile) + flag = "--enable-v4" + } + ctx.Build(pctx, android.BuildParams{ Rule: Signapk, Description: "signapk", - Output: signedApk, + Outputs: outputFiles, Input: unsignedApk, Implicits: deps, Args: map[string]string{ "certificates": strings.Join(certificateArgs, " "), + "flags": flag, }, }) } diff --git a/java/app_test.go b/java/app_test.go index fa18e9dac..f2ec4837f 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1079,6 +1079,66 @@ func TestCertificates(t *testing.T) { } } +func TestRequestV4SigningFlag(t *testing.T) { + testCases := []struct { + name string + bp string + expected string + }{ + { + name: "default", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + } + `, + expected: "", + }, + { + name: "default", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + v4_signature: false, + } + `, + expected: "", + }, + { + name: "module certificate property", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + v4_signature: true, + } + `, + expected: "--enable-v4", + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + config := testAppConfig(nil, test.bp, nil) + ctx := testContext() + + run(t, ctx, config) + foo := ctx.ModuleForTests("foo", "android_common") + + signapk := foo.Output("foo.apk") + signFlags := signapk.Args["flags"] + if test.expected != signFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags) + } + }) + } +} + func TestPackageNameOverride(t *testing.T) { testCases := []struct { name string diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 40cfe4f5d..fba0b97fb 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -127,7 +127,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo global := dexpreopt.GetGlobalConfig(ctx) bootImage := defaultBootImageConfig(ctx) dexFiles := bootImage.dexPathsDeps.Paths() - dexLocations := bootImage.dexLocationsDeps + // The dex locations for all Android variants are identical. + dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps if global.UseArtImage { bootImage = artBootImageConfig(ctx) } @@ -155,6 +156,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo images = append(images, variant.images) imagesDeps = append(imagesDeps, variant.imagesDeps) } + // The image locations for all Android variants are identical. + imageLocations := bootImage.getAnyAndroidVariant().imageLocations() dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath) @@ -198,7 +201,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo Archs: archs, DexPreoptImages: images, DexPreoptImagesDeps: imagesDeps, - DexPreoptImageLocations: bootImage.imageLocations, + DexPreoptImageLocations: imageLocations, PreoptBootClassPathDexFiles: dexFiles, PreoptBootClassPathDexLocations: dexLocations, diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index a3b264ed8..543b2333c 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -16,6 +16,7 @@ package java import ( "path/filepath" + "sort" "strings" "android/soong/android" @@ -25,31 +26,13 @@ import ( ) func init() { - android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory) + RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext) } -// The image "location" is a symbolic path that with multiarchitecture -// support doesn't really exist on the device. Typically it is -// /system/framework/boot.art and should be the same for all supported -// architectures on the device. The concrete architecture specific -// content actually ends up in a "filename" that contains an -// architecture specific directory name such as arm, arm64, x86, x86_64. -// -// Here are some example values for an x86_64 / x86 configuration: -// -// bootImages["x86_64"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art" -// dexpreopt.PathToLocation(bootImages["x86_64"], "x86_64") = "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art" -// -// bootImages["x86"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86/boot.art" -// dexpreopt.PathToLocation(bootImages["x86"])= "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art" -// -// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools -// will then reconstruct the real path, so the rules must have a dependency on the real path. - // Target-independent description of pre-compiled boot image. type bootImageConfig struct { - // Whether this image is an extension. - extension bool + // If this image is an extension, the image that it extends. + extends *bootImageConfig // Image name (used in directory names and ninja rule names). name string @@ -69,17 +52,10 @@ type bootImageConfig struct { // The names of jars that constitute this image. modules []string - // The "locations" of jars. - dexLocations []string // for this image - dexLocationsDeps []string // for the dependency images and in this image - // File paths to jars. dexPaths android.WritablePaths // for this image dexPathsDeps android.WritablePaths // for the dependency images and in this image - // The "locations" of the dependency images and in this image. - imageLocations []string - // File path to a zip archive with all image files (or nil, if not needed). zip android.WritablePath @@ -97,6 +73,10 @@ type bootImageVariant struct { // Target for which the image is generated. target android.Target + // The "locations" of jars. + dexLocations []string // for this image + dexLocationsDeps []string // for the dependency images and in this image + // Paths to image files. images android.OutputPath // first image file imagesDeps android.OutputPaths // all files @@ -119,13 +99,23 @@ func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant return nil } +// Return any (the first) variant which is for the device (as opposed to for the host) +func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant { + for _, variant := range image.variants { + if variant.target.Os == android.Android { + return variant + } + } + return nil +} + func (image bootImageConfig) moduleName(idx int) string { // Dexpreopt on the boot class path produces multiple files. The first dex file // is converted into 'name'.art (to match the legacy assumption that 'name'.art // exists), and the rest are converted to 'name'-<jar>.art. m := image.modules[idx] name := image.stem - if idx != 0 || image.extension { + if idx != 0 || image.extends != nil { name += "-" + stemOf(m) } return name @@ -150,6 +140,24 @@ func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.Ou return ret } +// The image "location" is a symbolic path that, with multiarchitecture support, doesn't really +// exist on the device. Typically it is /apex/com.android.art/javalib/boot.art and should be the +// same for all supported architectures on the device. The concrete architecture specific files +// actually end up in architecture-specific sub-directory such as arm, arm64, x86, or x86_64. +// +// For example a physical file +// "/apex/com.android.art/javalib/x86/boot.art" has "image location" +// "/apex/com.android.art/javalib/boot.art" (which is not an actual file). +// +// The location is passed as an argument to the ART tools like dex2oat instead of the real path. +// ART tools will then reconstruct the architecture-specific real path. +func (image *bootImageVariant) imageLocations() (imageLocations []string) { + if image.extends != nil { + imageLocations = image.extends.getVariant(image.target).imageLocations() + } + return append(imageLocations, dexpreopt.PathToLocation(image.images, image.target.Arch.ArchType)) +} + func concat(lists ...[]string) []string { var size int for _, l := range lists { @@ -166,6 +174,10 @@ func dexpreoptBootJarsFactory() android.Singleton { return &dexpreoptBootJars{} } +func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { + ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory) +} + func skipDexpreoptBootJars(ctx android.PathContext) bool { if dexpreopt.GetGlobalConfig(ctx).DisablePreopt { return true @@ -234,16 +246,66 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) { dumpOatRules(ctx, d.defaultBootImage) } +// Inspect this module to see if it contains a bootclasspath dex jar. +// Note that the same jar may occur in multiple modules. +// This logic is tested in the apex package to avoid import cycle apex <-> java. +func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) { + // All apex Java libraries have non-installable platform variants, skip them. + if module.IsSkipInstall() { + return -1, nil + } + + jar, hasJar := module.(interface{ DexJar() android.Path }) + if !hasJar { + return -1, nil + } + + name := ctx.ModuleName(module) + index := android.IndexList(name, image.modules) + if index == -1 { + return -1, nil + } + + // Check that this module satisfies constraints for a particular boot image. + apex, isApexModule := module.(android.ApexModule) + if image.name == artBootImageName { + if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") { + // ok, found the jar in the ART apex + } else if isApexModule && !apex.IsForPlatform() { + // this jar is part of an updatable apex other than ART, fail immediately + ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName()) + } else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) { + // this is a special "hostdex" variant, skip it and resume search + return -1, nil + } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { + // this is Jacoco platform variant for a coverage build, skip it and resume search + return -1, nil + } else { + // this (installable) jar is part of the platform, fail immediately + ctx.Errorf("module '%s' is part of the platform and not allowed in the ART boot image", name) + } + } else if image.name == frameworkBootImageName { + if !isApexModule || apex.IsForPlatform() { + // ok, this jar is part of the platform + } else { + // this jar is part of an updatable apex, fail immediately + ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName()) + } + } else { + panic("unknown boot image: " + image.name) + } + + return index, jar.DexJar() +} + // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image. func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig { + // Collect dex jar paths for the boot image modules. + // This logic is tested in the apex package to avoid import cycle apex <-> java. bootDexJars := make(android.Paths, len(image.modules)) ctx.VisitAllModules(func(module android.Module) { - // Collect dex jar paths for the modules listed above. - if j, ok := module.(interface{ DexJar() android.Path }); ok { - name := ctx.ModuleName(module) - if i := android.IndexList(name, image.modules); i != -1 { - bootDexJars[i] = j.DexJar() - } + if i, j := getBootImageJar(ctx, image, module); i != -1 { + bootDexJars[i] = j } }) @@ -255,7 +317,8 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI missingDeps = append(missingDeps, image.modules[i]) bootDexJars[i] = android.PathForOutput(ctx, "missing") } else { - ctx.Errorf("failed to find dex jar path for module %q", + ctx.Errorf("failed to find a dex jar path for module '%s'"+ + ", note that some jars may be filtered out by module constraints", image.modules[i]) } } @@ -274,6 +337,7 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI profile := bootImageProfileRule(ctx, image, missingDeps) bootFrameworkProfileRule(ctx, image, missingDeps) + updatableBcpPackagesRule(ctx, image, missingDeps) var allFiles android.Paths for _, variant := range image.variants { @@ -351,7 +415,7 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path()) } - if image.extension { + if image.extends != nil { artImage := image.primaryImages cmd. Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). @@ -478,7 +542,7 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig, Tool(globalSoong.Profman). FlagWithInput("--create-profile-from=", bootImageProfile). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.dexLocationsDeps). + FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) rule.Install(profile, "/system/etc/boot-image.prof") @@ -529,7 +593,7 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConf Flag("--generate-boot-profile"). FlagWithInput("--create-profile-from=", bootFrameworkProfile). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.dexLocationsDeps). + FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) rule.Install(profile, "/system/etc/boot-image.bprof") @@ -542,6 +606,61 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConf var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule") +func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath { + if ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() { + return nil + } + + return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} { + global := dexpreopt.GetGlobalConfig(ctx) + updatableModules := dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars) + + // Collect `permitted_packages` for updatable boot jars. + var updatablePackages []string + ctx.VisitAllModules(func(module android.Module) { + if j, ok := module.(*Library); ok { + name := ctx.ModuleName(module) + if i := android.IndexList(name, updatableModules); i != -1 { + pp := j.properties.Permitted_packages + if len(pp) > 0 { + updatablePackages = append(updatablePackages, pp...) + } else { + ctx.Errorf("Missing permitted_packages for %s", name) + } + // Do not match the same library repeatedly. + updatableModules = append(updatableModules[:i], updatableModules[i+1:]...) + } + } + }) + + // Sort updatable packages to ensure deterministic ordering. + sort.Strings(updatablePackages) + + updatableBcpPackagesName := "updatable-bcp-packages.txt" + updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName) + + ctx.Build(pctx, android.BuildParams{ + Rule: android.WriteFile, + Output: updatableBcpPackages, + Args: map[string]string{ + // WriteFile automatically adds the last end-of-line. + "content": strings.Join(updatablePackages, "\\n"), + }, + }) + + rule := android.NewRuleBuilder() + rule.MissingDeps(missingDeps) + rule.Install(updatableBcpPackages, "/system/etc/"+updatableBcpPackagesName) + // TODO: Rename `profileInstalls` to `extraInstalls`? + // Maybe even move the field out of the bootImageConfig into some higher level type? + image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + + return updatableBcpPackages + }).(android.WritablePath) +} + +var updatableBcpPackagesRuleKey = android.NewOnceKey("updatableBcpPackagesRule") + func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) { var allPhonies android.Paths for _, image := range image.variants { @@ -559,7 +678,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) { BuiltTool(ctx, "oatdumpd"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()). + FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()). FlagWithOutput("--output=", output). FlagWithArg("--instruction-set=", arch.String()) rule.Build(pctx, ctx, "dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) @@ -573,10 +692,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) { Text("echo").FlagWithArg("Output in ", output.String()) rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) - // TODO: We need to make imageLocations per-variant to make oatdump work on host. - if image.target.Os == android.Android { - allPhonies = append(allPhonies, phony) - } + allPhonies = append(allPhonies, phony) } phony := android.PathForPhony(ctx, "dump-oat-boot") @@ -612,25 +728,25 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { if image != nil { ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " ")) - ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " ")) + ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " ")) var imageNames []string for _, current := range append(d.otherImages, image) { imageNames = append(imageNames, current.name) - for _, current := range current.variants { + for _, variant := range current.variants { suffix := "" - if current.target.Os.Class == android.Host { + if variant.target.Os.Class == android.Host { suffix = "_host" } - sfx := current.name + suffix + "_" + current.target.Arch.ArchType.String() - ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String()) - ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String()) - ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " ")) - ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs.String()) - ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls.String()) + sfx := variant.name + suffix + "_" + variant.target.Arch.ArchType.String() + ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, variant.vdexInstalls.String()) + ctx.Strict("DEXPREOPT_IMAGE_"+sfx, variant.images.String()) + ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(variant.imagesDeps.Strings(), " ")) + ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String()) + ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String()) } - - ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":")) + imageLocations := current.getAnyAndroidVariant().imageLocations() + ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":")) ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String()) } ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " ")) diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index 94ca8bb97..127c20159 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -53,7 +53,7 @@ func TestDexpreoptBootJars(t *testing.T) { ctx := testContext() - ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory) + RegisterDexpreoptBootJarsComponents(ctx) run(t, ctx, config) diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index ffce2a9ff..066694cc3 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -79,6 +79,14 @@ func stemOf(moduleName string) string { return moduleName } +func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string { + if target.Os.Class == android.Host { + return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name) + } else { + return filepath.Join("/", subdir, name) + } +} + var ( bootImageConfigKey = android.NewOnceKey("bootImageConfig") artBootImageName = "art" @@ -104,36 +112,23 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { artSubdir := "apex/com.android.art/javalib" frameworkSubdir := "system/framework" - var artLocations, frameworkLocations []string - for _, m := range artModules { - artLocations = append(artLocations, filepath.Join("/"+artSubdir, stemOf(m)+".jar")) - } - for _, m := range frameworkModules { - frameworkLocations = append(frameworkLocations, filepath.Join("/"+frameworkSubdir, stemOf(m)+".jar")) - } - // ART config for the primary boot image in the ART apex. // It includes the Core Libraries. artCfg := bootImageConfig{ - extension: false, - name: artBootImageName, - stem: "boot", - installSubdir: artSubdir, - modules: artModules, - dexLocations: artLocations, - dexLocationsDeps: artLocations, + name: artBootImageName, + stem: "boot", + installSubdir: artSubdir, + modules: artModules, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. frameworkCfg := bootImageConfig{ - extension: true, - name: frameworkBootImageName, - stem: "boot", - installSubdir: frameworkSubdir, - modules: frameworkModules, - dexLocations: frameworkLocations, - dexLocationsDeps: append(artLocations, frameworkLocations...), + extends: &artCfg, + name: frameworkBootImageName, + stem: "boot", + installSubdir: frameworkSubdir, + modules: frameworkModules, } configs := map[string]*bootImageConfig{ @@ -149,8 +144,6 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension imageName := c.firstModuleNameOrStem() + ".art" - c.imageLocations = []string{c.dir.Join(ctx, "android", c.installSubdir, imageName).String()} - // The path to bootclasspath dex files needs to be known at module // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. // Set up known paths for them, the singleton rules will copy them there. @@ -171,6 +164,10 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { images: imageDir.Join(ctx, imageName), imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), } + for _, m := range c.modules { + variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, c.installSubdir, stemOf(m)+".jar")) + } + variant.dexLocationsDeps = variant.dexLocations c.variants = append(c.variants, variant) } @@ -181,8 +178,8 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) for i := range targets { frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images + frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) } - frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...) return configs }).(map[string]*bootImageConfig) @@ -206,7 +203,7 @@ func defaultBootclasspath(ctx android.PathContext) []string { updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p) } - bootclasspath := append(copyOf(image.dexLocationsDeps), updatableBootclasspath...) + bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...) return bootclasspath }) } @@ -221,7 +218,7 @@ func init() { func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) - ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocationsDeps, ":")) + ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":")) ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":")) diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 7e7e955f5..c7f7cbdfe 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -211,23 +211,30 @@ func stubFlagsRule(ctx android.SingletonContext) { // the greylists. func flagsRule(ctx android.SingletonContext) android.Path { var flagsCSV android.Paths - - var greylistIgnoreConflicts android.Path + var greylistRemovedApis android.Paths ctx.VisitAllModules(func(module android.Module) { if h, ok := module.(hiddenAPIIntf); ok { if csv := h.flagsCSV(); csv != nil { flagsCSV = append(flagsCSV, csv) } - } else if ds, ok := module.(*Droidstubs); ok && ctx.ModuleName(module) == "hiddenapi-lists-docs" { - greylistIgnoreConflicts = ds.removedDexApiFile + } else if ds, ok := module.(*Droidstubs); ok { + // Track @removed public and system APIs via corresponding droidstubs targets. + // These APIs are not present in the stubs, however, we have to keep allowing access + // to them at runtime. + if m := ctx.ModuleName(module); m == "api-stubs-docs" || m == "system-api-stubs-docs" { + greylistRemovedApis = append(greylistRemovedApis, ds.removedDexApiFile) + } } }) - if greylistIgnoreConflicts == nil { - ctx.Errorf("failed to find removed_dex_api_filename from hiddenapi-lists-docs module") - return nil - } + combinedRemovedApis := android.PathForOutput(ctx, "hiddenapi", "combined-removed-dex.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cat, + Inputs: greylistRemovedApis, + Output: combinedRemovedApis, + Description: "Combine removed apis for " + combinedRemovedApis.String(), + }) rule := android.NewRuleBuilder() @@ -242,8 +249,7 @@ func flagsRule(ctx android.SingletonContext) android.Path { Inputs(flagsCSV). FlagWithInput("--greylist ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt")). - FlagWithInput("--greylist-ignore-conflicts ", - greylistIgnoreConflicts). + FlagWithInput("--greylist-ignore-conflicts ", combinedRemovedApis). FlagWithInput("--greylist-max-q ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-q.txt")). FlagWithInput("--greylist-max-p ", diff --git a/java/java.go b/java/java.go index 22d14ecfe..a8ca3ffef 100644 --- a/java/java.go +++ b/java/java.go @@ -325,6 +325,10 @@ type CompilerDeviceProperties struct { UncompressDex bool `blueprint:"mutated"` IsSDKLibrary bool `blueprint:"mutated"` + + // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file. + // Defaults to false. + V4_signature *bool } func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { @@ -421,6 +425,8 @@ type Module struct { // list of the xref extraction files kytheFiles android.Paths + + distFile android.Path } func (j *Module) OutputFiles(tag string) (android.Paths, error) { @@ -540,9 +546,10 @@ func (s sdkDep) hasFrameworkLibs() bool { } type jniLib struct { - name string - path android.Path - target android.Target + name string + path android.Path + target android.Target + coverageFile android.OptionalPath } func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool { @@ -800,7 +807,7 @@ func (m *Module) getLinkType(name string) (ret linkType, stubs bool) { return javaModule, true case ver.kind == sdkModule: return javaModule, false - case name == "services-stubs": + case name == "android_system_server_stubs_current": return javaSystemServer, true case ver.kind == sdkSystemServer: return javaSystemServer, false @@ -1753,11 +1760,6 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu if staticLibTag == ctx.OtherModuleDependencyTag(dep) { return true } - // Also, a dependency to an sdk member is also considered as such. This is required because - // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { - return true - } return false } @@ -1777,9 +1779,18 @@ func (j *Module) IsInstallable() bool { // Java libraries (.jar file) // +type LibraryProperties struct { + Dist struct { + // The tag of the output of this module that should be output. + Tag *string `android:"arch_variant"` + } `android:"arch_variant"` +} + type Library struct { Module + libraryProperties LibraryProperties + InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } @@ -1823,6 +1834,15 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...) } + + // Verify Dist.Tag is set to a supported output + if j.libraryProperties.Dist.Tag != nil { + distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag) + if err != nil { + ctx.PropertyErrorf("dist.tag", "%s", err.Error()) + } + j.distFile = distFiles[0] + } } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1943,7 +1963,8 @@ func LibraryFactory() android.Module { &module.Module.properties, &module.Module.deviceProperties, &module.Module.dexpreoptProperties, - &module.Module.protoProperties) + &module.Module.protoProperties, + &module.libraryProperties) android.InitApexModule(module) android.InitSdkAwareModule(module) @@ -2338,6 +2359,12 @@ type ImportProperties struct { // set the name of the output Stem *string + + Aidl struct { + // directories that should be added as include directories for any aidl sources of modules + // that depend on this module, as well as to aidl for this module. + Export_include_dirs []string + } } type Import struct { @@ -2351,6 +2378,7 @@ type Import struct { combinedClasspathFile android.Path exportedSdkLibs []string + exportAidlIncludeDirs android.Paths } func (j *Import) sdkVersion() sdkSpec { @@ -2424,6 +2452,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), jarName, outputFile) } + + j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs) } var _ Dependency = (*Import)(nil) @@ -2458,7 +2488,7 @@ func (j *Import) DexJar() android.Path { } func (j *Import) AidlIncludeDirs() android.Paths { - return nil + return j.exportAidlIncludeDirs } func (j *Import) ExportedSdkLibs() []string { @@ -2478,11 +2508,6 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu if staticLibTag == ctx.OtherModuleDependencyTag(dep) { return true } - // Also, a dependency to an sdk member is also considered as such. This is required because - // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { - return true - } return false } diff --git a/java/java_test.go b/java/java_test.go index 6d972bebd..e8a1a7c83 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1491,3 +1491,27 @@ func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, m t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) } } + +func TestAidlExportIncludeDirsFromImports(t *testing.T) { + ctx, _ := testJava(t, ` + java_library { + name: "foo", + srcs: ["aidl/foo/IFoo.aidl"], + libs: ["bar"], + } + + java_import { + name: "bar", + jars: ["a.jar"], + aidl: { + export_include_dirs: ["aidl/bar"], + }, + } + `) + + aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + expectedAidlFlag := "-Iaidl/bar" + if !strings.Contains(aidlCommand, expectedAidlFlag) { + t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) + } +} diff --git a/java/sdk.go b/java/sdk.go index ded2a061b..0e132d399 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -406,7 +406,7 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) case sdkSystemServer: // TODO(146757305): provide .apk and .aidl that have more APIs for modules - return toModule([]string{"android_module_lib_stubs_current", "services-stubs"}, "framework-res", sdkFrameworkAidlPath(ctx)) + return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) default: panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw)) } diff --git a/java/sdk_library.go b/java/sdk_library.go index 6921114bf..efee7da23 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -18,7 +18,6 @@ import ( "android/soong/android" "fmt" - "io" "path" "path/filepath" "sort" @@ -87,6 +86,9 @@ type apiScope struct { // *current. Older stubs library built with a numbered SDK version is created from // the prebuilt jar. sdkVersion string + + // Extra arguments to pass to droidstubs for this scope. + droidstubsArgs []string } // Initialize a scope, creating and adding appropriate dependency tags @@ -132,6 +134,7 @@ var ( moduleSuffix: sdkSystemApiSuffix, apiFileMakeVariableSuffix: "_SYSTEM", sdkVersion: "system_current", + droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"}, }) apiScopeTest = initApiScope(&apiScope{ name: "test", @@ -139,6 +142,7 @@ var ( moduleSuffix: sdkTestApiSuffix, apiFileMakeVariableSuffix: "_TEST", sdkVersion: "test_current", + droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"}, }) allApiScopes = apiScopes{ apiScopePublic, @@ -328,41 +332,6 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { entriesList := module.Library.AndroidMkEntries() entries := &entriesList[0] entries.Required = append(entries.Required, module.xmlFileName()) - - entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{ - func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) { - if !Bool(module.sdkLibraryProperties.No_dist) { - // Create a phony module that installs the impl library, for the case when this lib is - // in PRODUCT_PACKAGES. - owner := module.ModuleBase.Owner() - if owner == "" { - if Bool(module.sdkLibraryProperties.Core_lib) { - owner = "core" - } else { - owner = "android" - } - } - - // Create dist rules to install the stubs libs and api files to the dist dir - for _, apiScope := range module.getActiveApiScopes() { - if scopePaths, ok := module.scopePaths[apiScope]; ok { - if len(scopePaths.stubsHeaderPath) == 1 { - fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+ - scopePaths.stubsImplPath.Strings()[0]+ - ":"+path.Join("apistubs", owner, apiScope.name, - module.BaseModuleName()+".jar")+")") - } - if scopePaths.apiFilePath != nil { - fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+ - scopePaths.apiFilePath.String()+ - ":"+path.Join("apistubs", owner, apiScope.name, "api", - module.BaseModuleName()+".txt")+")") - } - } - } - } - }, - } return entriesList } @@ -386,6 +355,17 @@ func (module *SdkLibrary) xmlFileName() string { return module.BaseModuleName() + sdkXmlFileSuffix } +// The dist path of the stub artifacts +func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string { + if module.ModuleBase.Owner() != "" { + return path.Join("apistubs", module.ModuleBase.Owner(), apiScope.name) + } else if Bool(module.sdkLibraryProperties.Core_lib) { + return path.Join("apistubs", "core", apiScope.name) + } else { + return path.Join("apistubs", "android", apiScope.name) + } +} + // Get the sdk version for use when compiling the stubs library. func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) string { sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library)) @@ -438,6 +418,12 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiSc Srcs []string Javacflags []string } + Dist struct { + Targets []string + Dest *string + Dir *string + Tag *string + } }{} props.Name = proptools.StringPtr(module.stubsName(apiScope)) @@ -466,11 +452,18 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiSc } else if module.SystemExtSpecific() { props.System_ext_specific = proptools.BoolPtr(true) } + // Dist the class jar artifact for sdk builds. + if !Bool(module.sdkLibraryProperties.No_dist) { + props.Dist.Targets = []string{"sdk", "win_sdk"} + props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.BaseModuleName())) + props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope)) + props.Dist.Tag = proptools.StringPtr(".jar") + } mctx.CreateModule(LibraryFactory, &props) } -// Creates a droiddoc module that creates stubs source files from the given full source +// Creates a droidstubs module that creates stubs source files from the given full source // files func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) { props := struct { @@ -497,6 +490,11 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc Include_dirs []string Local_include_dirs []string } + Dist struct { + Targets []string + Dest *string + Dir *string + } }{} sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library)) @@ -523,15 +521,15 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs - droiddocArgs := []string{} + droidstubsArgs := []string{} if len(module.sdkLibraryProperties.Api_packages) != 0 { - droiddocArgs = append(droiddocArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":")) + droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":")) } if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 { - droiddocArgs = append(droiddocArgs, + droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package ")) } - droiddocArgs = append(droiddocArgs, module.sdkLibraryProperties.Droiddoc_options...) + droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...) disabledWarnings := []string{ "MissingPermission", "BroadcastBehavior", @@ -543,16 +541,12 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc "Todo", "Typo", } - droiddocArgs = append(droiddocArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) + droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) - switch apiScope { - case apiScopeSystem: - droiddocArgs = append(droiddocArgs, "-showAnnotation android.annotation.SystemApi") - case apiScopeTest: - droiddocArgs = append(droiddocArgs, " -showAnnotation android.annotation.TestApi") - } + // Add in scope specific arguments. + droidstubsArgs = append(droidstubsArgs, apiScope.droidstubsArgs...) props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files - props.Args = proptools.StringPtr(strings.Join(droiddocArgs, " ")) + props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " ")) // List of APIs identified from the provided source files are created. They are later // compared against to the not-yet-released (a.k.a current) list of APIs and to the @@ -578,6 +572,13 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc module.latestRemovedApiFilegroupName(apiScope)) props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) + // Dist the api txt artifact for sdk builds. + if !Bool(module.sdkLibraryProperties.No_dist) { + props.Dist.Targets = []string{"sdk", "win_sdk"} + props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName())) + props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) + } + mctx.CreateModule(DroidstubsFactory, &props) } diff --git a/java/sdk_test.go b/java/sdk_test.go index ea6733d86..088db9e70 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -222,9 +222,9 @@ func TestClasspath(t *testing.T) { { name: "system_server_current", properties: `sdk_version: "system_server_current",`, - bootclasspath: []string{"android_module_lib_stubs_current", "services-stubs", "core-lambda-stubs"}, + bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"}, system: "core-current-stubs-system-modules", - java9classpath: []string{"android_module_lib_stubs_current", "services-stubs"}, + java9classpath: []string{"android_system_server_stubs_current"}, aidl: "-p" + buildDir + "/framework.aidl", }, } diff --git a/java/testing.go b/java/testing.go index 5b6a39b2a..6929bb724 100644 --- a/java/testing.go +++ b/java/testing.go @@ -50,6 +50,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "api/test-current.txt": nil, "api/test-removed.txt": nil, "framework/aidl/a.aidl": nil, + "aidl/foo/IFoo.aidl": nil, + "aidl/bar/IBar.aidl": nil, "assets_a/a": nil, "assets_b/b": nil, @@ -148,7 +150,7 @@ func GatherRequiredDepsForTest() string { "android_system_stubs_current", "android_test_stubs_current", "android_module_lib_stubs_current", - "services-stubs", + "android_system_server_stubs_current", "core.current.stubs", "core.platform.api.stubs", "kotlin-stdlib", |