diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/androidmk.go | 17 | ||||
-rwxr-xr-x | java/app.go | 221 | ||||
-rw-r--r-- | java/app_builder.go | 13 | ||||
-rw-r--r-- | java/app_test.go | 323 | ||||
-rw-r--r-- | java/builder.go | 12 | ||||
-rw-r--r-- | java/config/config.go | 2 | ||||
-rw-r--r-- | java/droiddoc.go | 28 | ||||
-rw-r--r-- | java/java.go | 59 | ||||
-rw-r--r-- | java/java_test.go | 26 | ||||
-rw-r--r-- | java/prebuilt_apis.go | 35 | ||||
-rw-r--r-- | java/sdk.go | 26 | ||||
-rw-r--r-- | java/sdk_library.go | 575 | ||||
-rw-r--r-- | java/sdk_test.go | 67 | ||||
-rw-r--r-- | java/testing.go | 81 |
14 files changed, 1190 insertions, 295 deletions
diff --git a/java/androidmk.go b/java/androidmk.go index 2c2919218..ba1af0d77 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -681,3 +681,20 @@ func (r *RuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEntries { }, }} } + +func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{ + android.AndroidMkEntries{ + Class: "APPS", + OutputFile: android.OptionalPathForPath(apkSet.packedOutput), + Include: "$(BUILD_SYSTEM)/soong_android_app_set.mk", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged()) + entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile) + entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...) + }, + }, + }, + } +} diff --git a/java/app.go b/java/app.go index f1af2adf4..215b07b28 100755 --- a/java/app.go +++ b/java/app.go @@ -20,6 +20,7 @@ import ( "path/filepath" "reflect" "sort" + "strconv" "strings" "github.com/google/blueprint" @@ -49,6 +50,127 @@ func RegisterAppBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory) ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory) ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory) + ctx.RegisterModuleType("android_app_set", AndroidApkSetFactory) +} + +type AndroidAppSetProperties struct { + // APK Set path + Set *string + + // 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 + + // APKs in this set use prerelease SDK version + Prerelease *bool + + // Names of modules to be overridden. Listed modules can only be other apps + // (in Make or Soong). + Overrides []string +} + +type AndroidAppSet struct { + android.ModuleBase + android.DefaultableModuleBase + prebuilt android.Prebuilt + + properties AndroidAppSetProperties + packedOutput android.WritablePath + masterFile string +} + +func (as *AndroidAppSet) Name() string { + return as.prebuilt.Name(as.ModuleBase.Name()) +} + +func (as *AndroidAppSet) IsInstallable() bool { + return true +} + +func (as *AndroidAppSet) Prebuilt() *android.Prebuilt { + return &as.prebuilt +} + +func (as *AndroidAppSet) Privileged() bool { + return Bool(as.properties.Privileged) +} + +var TargetCpuAbi = map[string]string{ + "arm": "ARMEABI_V7A", + "arm64": "ARM64_V8A", + "x86": "X86", + "x86_64": "X86_64", +} + +func SupportedAbis(ctx android.ModuleContext) []string { + abiName := func(archVar string, deviceArch string) string { + if abi, found := TargetCpuAbi[deviceArch]; found { + return abi + } + ctx.ModuleErrorf("Invalid %s: %s", archVar, deviceArch) + return "BAD_ABI" + } + + result := []string{abiName("TARGET_ARCH", ctx.DeviceConfig().DeviceArch())} + if s := ctx.DeviceConfig().DeviceSecondaryArch(); s != "" { + result = append(result, abiName("TARGET_2ND_ARCH", s)) + } + return result +} + +func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { + as.packedOutput = android.PathForModuleOut(ctx, "extracted.zip") + // We are assuming here that the master file in the APK + // set has `.apk` suffix. If it doesn't the build will fail. + // APK sets containing APEX files are handled elsewhere. + as.masterFile = ctx.ModuleName() + ".apk" + screenDensities := "all" + if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 { + screenDensities = strings.ToUpper(strings.Join(dpis, ",")) + } + // TODO(asmundak): handle locales. + // TODO(asmundak): do we support device features + ctx.Build(pctx, + android.BuildParams{ + Rule: extractMatchingApks, + Description: "Extract APKs from APK set", + Output: as.packedOutput, + Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)}, + Args: map[string]string{ + "abis": strings.Join(SupportedAbis(ctx), ","), + "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)), + "screen-densities": screenDensities, + "sdk-version": ctx.Config().PlatformSdkVersion(), + "stem": ctx.ModuleName(), + }, + }) + // TODO(asmundak): add this (it's wrong now, will cause copying extracted.zip) + /* + var installDir android.InstallPath + if Bool(as.properties.Privileged) { + installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName()) + } else if ctx.InstallInTestcases() { + installDir = android.PathForModuleInstall(ctx, as.BaseModuleName(), ctx.DeviceConfig().DeviceArch()) + } else { + installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName()) + } + ctx.InstallFile(installDir, as.masterFile", as.packedOutput) + */ +} + +// android_app_set extracts a set of APKs based on the target device +// configuration and installs this set as "split APKs". +// The set will always contain `base-master.apk` and every APK built +// to the target device. All density-specific APK will be included, too, +// unless PRODUCT_APPT_PREBUILT_DPI is defined (should contain comma-sepearated +// list of density names (LDPI, MDPI, HDPI, etc.) +func AndroidApkSetFactory() android.Module { + module := &AndroidAppSet{} + module.AddProperties(&module.properties) + InitJavaModule(module, android.DeviceSupported) + android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set") + return module } // AndroidManifest.xml merging @@ -129,6 +251,9 @@ type overridableAppProperties struct { // or an android_app_certificate module name in the form ":module". Certificate *string + // Name of the signing certificate lineage file. + Lineage *string + // the package name of this app. The package name in the manifest file is used if one was not given. Package_name *string @@ -249,7 +374,10 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { // If the app builds against an Android SDK use the SDK variant of JNI dependencies // unless jni_uses_platform_apis is set. - if (usesSDK && !Bool(a.appProperties.Jni_uses_platform_apis)) || + // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already + // have stable APIs through the VNDK. + if (usesSDK && !a.RequiresStableAPIs(ctx) && + !Bool(a.appProperties.Jni_uses_platform_apis)) || Bool(a.appProperties.Jni_uses_sdk_apis) { variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) } @@ -286,19 +414,47 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { - if Bool(a.appProperties.Updatable) { + if Bool(a.appProperties.Updatable) || a.ApexModuleBase.Updatable() { if !a.sdkVersion().stable() { ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion()) } if String(a.deviceProperties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") } + if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { + a.checkJniLibsSdkVersion(ctx, minSdkVersion) + } else { + ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) + } } a.checkPlatformAPI(ctx) a.checkSdkVersions(ctx) } +// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. +// This check is enforced for "updatable" APKs (including APK-in-APEX). +// b/155209650: until min_sdk_version is properly supported, use sdk_version instead. +// because, sdk_version is overridden by min_sdk_version (if set as smaller) +// and linkType is checked with dependencies so we can be sure that the whole dependency tree +// will meet the requirements. +func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) { + // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() + ctx.VisitDirectDeps(func(m android.Module) { + if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { + return + } + dep, _ := m.(*cc.Module) + jniSdkVersion, err := android.ApiStrToNum(ctx, dep.SdkVersion()) + if err != nil || int(minSdkVersion) < jniSdkVersion { + ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", + dep.SdkVersion(), minSdkVersion, ctx.ModuleName()) + return + } + + }) +} + // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { @@ -584,7 +740,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile := a.dexBuildActions(ctx) - jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) + jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) jniJarFile := a.jniBuildActions(jniLibs, ctx) if ctx.Failed() { @@ -596,13 +752,17 @@ 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) + var lineageFile android.Path + if lineage := String(a.overridableAppProperties.Lineage); lineage != "" { + lineageFile = android.PathForModuleSrc(ctx, lineage) + } + CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, lineageFile) a.outputFile = packageFile 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) + CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, lineageFile) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) } @@ -622,12 +782,25 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.buildAppDependencyInfo(ctx) } -func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool, +type appDepsInterface interface { + sdkVersion() sdkSpec + minSdkVersion() sdkSpec + RequiresStableAPIs(ctx android.BaseModuleContext) bool +} + +func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, + shouldCollectRecursiveNativeDeps bool, checkNativeSdkVersion bool) ([]jniLib, []Certificate) { + var jniLibs []jniLib var certificates []Certificate seenModulePaths := make(map[string]bool) + if checkNativeSdkVersion { + checkNativeSdkVersion = app.sdkVersion().specified() && + app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx) + } + ctx.WalkDeps(func(module android.Module, parent android.Module) bool { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -645,16 +818,9 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps } seenModulePaths[path.String()] = true - if checkNativeSdkVersion { - if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok { - if app.sdkVersion().specified() && - app.sdkVersion().kind != sdkCorePlatform && - dep.SdkVersion() == "" { - ctx.PropertyErrorf("jni_libs", - "JNI dependency %q uses platform APIs, but this module does not", - otherName) - } - } + if checkNativeSdkVersion && dep.SdkVersion() == "" { + ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", + otherName) } if lib.Valid() { @@ -835,6 +1001,7 @@ func (a *AndroidTest) InstallInTestcases() bool { } func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { + var configs []tradefed.Config if a.appTestProperties.Instrumentation_target_package != nil { a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+*a.appTestProperties.Instrumentation_target_package) @@ -847,8 +1014,12 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } a.generateAndroidBuildActions(ctx) + for _, module := range a.testProperties.Test_mainline_modules { + configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) + } + testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, - a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config) + a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config, configs) a.testConfig = a.FixTestConfig(ctx, testConfig) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) } @@ -1244,7 +1415,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set") } - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, a, false, false) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_PACKAGE_SPLITS @@ -1299,7 +1470,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } a.certificate = certificates[0] signed := android.PathForModuleOut(ctx, "signed", apkFilename) - SignAppPackage(ctx, signed, dexOutput, certificates) + SignAppPackage(ctx, signed, dexOutput, certificates, nil) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename) @@ -1370,6 +1541,14 @@ func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep an return false } +func (a *AndroidAppImport) sdkVersion() sdkSpec { + return sdkSpecFrom("") +} + +func (a *AndroidAppImport) minSdkVersion() sdkSpec { + return sdkSpecFrom("") +} + func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { props := reflect.TypeOf((*AndroidAppImportProperties)(nil)) @@ -1555,10 +1734,10 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC r.aapt.buildActions(ctx, r, aaptLinkFlags...) // Sign the built package - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, r, 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..fb9ab4295 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, lineageFile android.Path) { 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, lineageFile) } -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, lineageFile android.Path) { var certificateArgs []string var deps android.Paths @@ -78,6 +78,12 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u deps = append(deps, c.Pem, c.Key) } + var flags []string + if lineageFile != nil { + flags = append(flags, "--lineage", lineageFile.String()) + deps = append(deps, lineageFile) + } + ctx.Build(pctx, android.BuildParams{ Rule: Signapk, Description: "signapk", @@ -86,6 +92,7 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u Implicits: deps, Args: map[string]string{ "certificates": strings.Join(certificateArgs, " "), + "flags": strings.Join(flags, " "), }, }) } diff --git a/java/app_test.go b/java/app_test.go index 4bcfa5a81..2195afdb0 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -141,6 +141,94 @@ func TestAppSplits(t *testing.T) { } } +func TestAndroidAppSet(t *testing.T) { + ctx, config := testJava(t, ` + android_app_set { + name: "foo", + set: "prebuilts/apks/app.apks", + prerelease: true, + }`) + module := ctx.ModuleForTests("foo", "android_common") + const packedSplitApks = "extracted.zip" + params := module.Output(packedSplitApks) + if params.Rule == nil { + t.Errorf("expected output %s is missing", packedSplitApks) + } + if s := params.Args["allow-prereleased"]; s != "true" { + t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s) + } + mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0] + actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"] + expectedMaster := []string{"foo.apk"} + if !reflect.DeepEqual(actualMaster, expectedMaster) { + t.Errorf("Unexpected LOCAL_APK_SET_MASTER_FILE value: '%s', expected: '%s',", + actualMaster, expectedMaster) + } +} + +func TestAndroidAppSet_Variants(t *testing.T) { + bp := ` + android_app_set { + name: "foo", + set: "prebuilts/apks/app.apks", + }` + testCases := []struct { + name string + deviceArch *string + deviceSecondaryArch *string + aaptPrebuiltDPI []string + sdkVersion int + expected map[string]string + }{ + { + name: "One", + deviceArch: proptools.StringPtr("x86"), + aaptPrebuiltDPI: []string{"ldpi", "xxhdpi"}, + sdkVersion: 29, + expected: map[string]string{ + "abis": "X86", + "allow-prereleased": "false", + "screen-densities": "LDPI,XXHDPI", + "sdk-version": "29", + "stem": "foo", + }, + }, + { + name: "Two", + deviceArch: proptools.StringPtr("x86_64"), + deviceSecondaryArch: proptools.StringPtr("x86"), + aaptPrebuiltDPI: nil, + sdkVersion: 30, + expected: map[string]string{ + "abis": "X86_64,X86", + "allow-prereleased": "false", + "screen-densities": "all", + "sdk-version": "30", + "stem": "foo", + }, + }, + } + + for _, test := range testCases { + config := testAppConfig(nil, bp, nil) + config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI + config.TestProductVariables.Platform_sdk_version = &test.sdkVersion + config.TestProductVariables.DeviceArch = test.deviceArch + config.TestProductVariables.DeviceSecondaryArch = test.deviceSecondaryArch + ctx := testContext() + run(t, ctx, config) + module := ctx.ModuleForTests("foo", "android_common") + const packedSplitApks = "extracted.zip" + params := module.Output(packedSplitApks) + for k, v := range test.expected { + if actual := params.Args[k]; actual != v { + t.Errorf("%s: bad build arg value for '%s': '%s', expected '%s'", + test.name, k, actual, v) + } + } + } +} + func TestPlatformAPIs(t *testing.T) { testJava(t, ` android_app { @@ -385,6 +473,127 @@ func TestUpdatableApps(t *testing.T) { } } +func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { + testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "current", + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + system_shared_libs: [], + sdk_version: "current", + } + `) +} + +func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + system_shared_libs: [], + sdk_version: "29", + } + + ndk_prebuilt_object { + name: "ndk_crtbegin_so.29", + sdk_version: "29", + } + + ndk_prebuilt_object { + name: "ndk_crtend_so.29", + sdk_version: "29", + } + ` + fs := map[string][]byte{ + "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil, + } + + ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs)) + + inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits + var crtbeginFound, crtendFound bool + for _, input := range inputs { + switch input.String() { + case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": + crtbeginFound = true + case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": + crtendFound = true + } + } + if !crtbeginFound || !crtendFound { + t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29") + } +} + +func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", // this APK should support 29 + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + sdk_version: "current", + } + ` + testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp) +} + +func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", // this APK should support 29 + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + shared_libs: ["libbar"], + system_shared_libs: [], + sdk_version: "27", + } + + cc_library { + name: "libbar", + stl: "none", + system_shared_libs: [], + sdk_version: "current", + } + ` + testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp) +} + func TestResourceDirs(t *testing.T) { testCases := []struct { name string @@ -1144,25 +1353,44 @@ func TestJNISDK(t *testing.T) { platform_apis: true, jni_uses_sdk_apis: true, } + + cc_library { + name: "libvendorjni", + system_shared_libs: [], + stl: "none", + vendor: true, + } + + android_test { + name: "app_vendor", + jni_libs: ["libvendorjni"], + sdk_version: "current", + vendor: true, + } `) testCases := []struct { - name string - sdkJNI bool + name string + sdkJNI bool + vendorJNI bool }{ - {"app_platform", false}, - {"app_sdk", true}, - {"app_force_platform", false}, - {"app_force_sdk", true}, + {name: "app_platform"}, + {name: "app_sdk", sdkJNI: true}, + {name: "app_force_platform"}, + {name: "app_force_sdk", sdkJNI: true}, + {name: "app_vendor", vendorJNI: true}, } + platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). + Output("libjni.so").Output.String() + sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). + Output("libjni.so").Output.String() + vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared"). + Output("libvendorjni.so").Output.String() + for _, test := range testCases { t.Run(test.name, func(t *testing.T) { app := ctx.ModuleForTests(test.name, "android_common") - platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). - Output("libjni.so").Output.String() - sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). - Output("libjni.so").Output.String() jniLibZip := app.MaybeOutput("jnilibs.zip") if len(jniLibZip.Implicits) != 1 { @@ -1174,6 +1402,10 @@ func TestJNISDK(t *testing.T) { if gotJNI != sdkJNI { t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI) } + } else if test.vendorJNI { + if gotJNI != vendorJNI { + t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI) + } } else { if gotJNI != platformJNI { t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI) @@ -1209,7 +1441,8 @@ func TestCertificates(t *testing.T) { name string bp string certificateOverride string - expected string + expectedLineage string + expectedCertificate string }{ { name: "default", @@ -1221,7 +1454,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8", + expectedLineage: "", + expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8", }, { name: "module certificate property", @@ -1239,7 +1473,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "cert/new_cert.x509.pem cert/new_cert.pk8", + expectedLineage: "", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", }, { name: "path certificate property", @@ -1252,7 +1487,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + expectedLineage: "", + expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", }, { name: "certificate overrides", @@ -1270,7 +1506,28 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "foo:new_certificate", - expected: "cert/new_cert.x509.pem cert/new_cert.pk8", + expectedLineage: "", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", + }, + { + name: "certificate lineage", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + certificate: ":new_certificate", + lineage: "lineage.bin", + sdk_version: "current", + } + + android_app_certificate { + name: "new_certificate", + certificate: "cert/new_cert", + } + `, + certificateOverride: "", + expectedLineage: "--lineage lineage.bin", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", }, } @@ -1286,9 +1543,14 @@ func TestCertificates(t *testing.T) { foo := ctx.ModuleForTests("foo", "android_common") signapk := foo.Output("foo.apk") - signFlags := signapk.Args["certificates"] - if test.expected != signFlags { - t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags) + signCertificateFlags := signapk.Args["certificates"] + if test.expectedCertificate != signCertificateFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedCertificate, signCertificateFlags) + } + + signFlags := signapk.Args["flags"] + if test.expectedLineage != signFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedLineage, signFlags) } }) } @@ -1402,6 +1664,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "bar", base: "foo", certificate: ":new_certificate", + lineage: "lineage.bin", logging_parent: "bah", } @@ -1422,7 +1685,8 @@ func TestOverrideAndroidApp(t *testing.T) { variantName string apkName string apkPath string - signFlag string + certFlag string + lineageFlag string overrides []string aaptFlag string logging_parent string @@ -1431,7 +1695,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "foo", variantName: "android_common", apkPath: "/target/product/test_device/system/app/foo/foo.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", overrides: []string{"qux"}, aaptFlag: "", logging_parent: "", @@ -1440,7 +1705,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "bar", variantName: "android_common_bar", apkPath: "/target/product/test_device/system/app/bar/bar.apk", - signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + lineageFlag: "--lineage lineage.bin", overrides: []string{"qux", "foo"}, aaptFlag: "", logging_parent: "bah", @@ -1449,7 +1715,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "baz", variantName: "android_common_baz", apkPath: "/target/product/test_device/system/app/baz/baz.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", overrides: []string{"qux", "foo"}, aaptFlag: "--rename-manifest-package org.dandroid.bp", logging_parent: "", @@ -1474,9 +1741,15 @@ func TestOverrideAndroidApp(t *testing.T) { // Check the certificate paths signapk := variant.Output(expected.moduleName + ".apk") - signFlag := signapk.Args["certificates"] - if expected.signFlag != signFlag { - t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag) + certFlag := signapk.Args["certificates"] + if expected.certFlag != certFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.certFlag, certFlag) + } + + // Check the lineage flags + lineageFlag := signapk.Args["flags"] + if expected.lineageFlag != lineageFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.lineageFlag, lineageFlag) } // Check if the overrides field values are correctly aggregated. diff --git a/java/builder.go b/java/builder.go index 3a4a10d3c..b8340295b 100644 --- a/java/builder.go +++ b/java/builder.go @@ -104,6 +104,18 @@ var ( "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", "outDir", "annoDir", "javaVersion") + extractMatchingApks = pctx.StaticRule( + "extractMatchingApks", + blueprint.RuleParams{ + Command: `rm -rf "$out" && ` + + `${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` + + `-sdk-version=${sdk-version} -abis=${abis} ` + + `--screen-densities=${screen-densities} --stem=${stem} ` + + `${in}`, + CommandDeps: []string{"${config.ExtractApksCmd}"}, + }, + "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem") + turbine = pctx.AndroidStaticRule("turbine", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + diff --git a/java/config/config.go b/java/config/config.go index c4f236346..1344ceb22 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -122,7 +122,7 @@ func init() { pctx.HostBinToolVariable("D8Cmd", "d8") pctx.HostBinToolVariable("R8Cmd", "r8-compat-proguard") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") - + pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string { turbine := "turbine.jar" if ctx.Config().UnbundledBuild() { diff --git a/java/droiddoc.go b/java/droiddoc.go index 78ecb09e3..414882c3f 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -222,8 +222,22 @@ type DroidstubsProperties struct { Current ApiToCheck - // do not perform API check against Last_released, in the case that both two specified API - // files by Last_released are modules which don't exist. + // The java_sdk_library module generates references to modules (i.e. filegroups) + // from which information about the latest API version can be obtained. As those + // modules may not exist (e.g. because a previous version has not been released) it + // sets ignore_missing_latest_api=true on the droidstubs modules it creates so + // that droidstubs can ignore those references if the modules do not yet exist. + // + // If true then this will ignore module references for modules that do not exist + // in properties that supply the previous version of the API. + // + // There are two sets of those: + // * Api_file, Removed_api_file in check_api.last_released + // * New_since in check_api.api_lint.new_since + // + // The first two must be set as a pair, so either they should both exist or neither + // should exist - in which case when this property is true they are ignored. If one + // exists and the other does not then it is an error. Ignore_missing_latest_api *bool `blueprint:"mutated"` Api_lint struct { @@ -1200,8 +1214,18 @@ func (d *Droidstubs) StubsSrcJar() android.Path { func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) { d.Javadoc.addDeps(ctx) + // If requested clear any properties that provide information about the latest version + // of an API and which reference non-existent modules. if Bool(d.properties.Check_api.Ignore_missing_latest_api) { ignoreMissingModules(ctx, &d.properties.Check_api.Last_released) + + // If the new_since references a module, e.g. :module-latest-api and the module + // does not exist then clear it. + newSinceSrc := d.properties.Check_api.Api_lint.New_since + newSinceSrcModule := android.SrcIsModule(proptools.String(newSinceSrc)) + if newSinceSrcModule != "" && !ctx.OtherModuleExists(newSinceSrcModule) { + d.properties.Check_api.Api_lint.New_since = nil + } } if len(d.properties.Merge_annotations_dirs) != 0 { diff --git a/java/java.go b/java/java.go index 9d75c74c7..5b1dcd7cf 100644 --- a/java/java.go +++ b/java/java.go @@ -95,8 +95,7 @@ func (j *Module) CheckStableSdkVersion() error { } func (j *Module) checkSdkVersions(ctx android.ModuleContext) { - if j.SocSpecific() || j.DeviceSpecific() || - (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { + if j.RequiresStableAPIs(ctx) { if sc, ok := ctx.Module().(sdkContext); ok { if !sc.sdkVersion().specified() { ctx.PropertyErrorf("sdk_version", @@ -351,6 +350,22 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault) } +// Functionality common to Module and Import +type embeddableInModuleAndImport struct { +} + +// Module/Import's DepIsInSameApex(...) delegates to this method. +// +// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with +// the one provided by ApexModuleBase. +func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { + // dependencies other than the static linkage are all considered crossing APEX boundary + if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + return true + } + return false +} + // Module contains the properties and members used by all java module types type Module struct { android.ModuleBase @@ -358,6 +373,9 @@ type Module struct { android.ApexModuleBase android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties CompilerProperties protoProperties android.ProtoProperties deviceProperties CompilerDeviceProperties @@ -625,13 +643,15 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } } else if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) - ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) } } + if sdkDep.systemModules != "" { + ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) + } if ctx.ModuleName() == "android_stubs_current" || ctx.ModuleName() == "android_system_stubs_current" || @@ -1034,19 +1054,10 @@ func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) { } func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion { - sdk, err := sdkContext.sdkVersion().effectiveVersion(ctx) - if err != nil { - ctx.PropertyErrorf("sdk_version", "%s", err) - } if javaVersion != "" { return normalizeJavaVersion(ctx, javaVersion) - } else if ctx.Device() && sdk <= 23 { - return JAVA_VERSION_7 - } else if ctx.Device() && sdk <= 29 { - return JAVA_VERSION_8 - } else if ctx.Device() && ctx.Config().UnbundledBuildUsePrebuiltSdks() { - // TODO(b/142896162): once we have prebuilt system modules we can use 1.9 for unbundled builds - return JAVA_VERSION_8 + } else if ctx.Device() { + return sdkContext.sdkVersion().defaultJavaLanguageVersion(ctx) } else { return JAVA_VERSION_9 } @@ -1769,11 +1780,7 @@ func (j *Module) hasCode(ctx android.ModuleContext) bool { } func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // Dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } func (j *Module) Stem() string { @@ -2033,6 +2040,10 @@ type testProperties struct { // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. Auto_gen_config *bool + + // Add parameterized mainline modules to auto generated test config. The options will be + // handled by TradeFed to do downloading and installing the specified modules on the device. + Test_mainline_modules []string } type testHelperLibraryProperties struct { @@ -2387,6 +2398,9 @@ type Import struct { prebuilt android.Prebuilt android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties ImportProperties combinedClasspathFile android.Path @@ -2521,11 +2535,7 @@ func (j *Import) SrcJarArgs() ([]string, android.Paths) { } func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } // Add compile time check for interface implementation @@ -2764,6 +2774,7 @@ func DefaultsFactory() android.Module { &ImportProperties{}, &AARImportProperties{}, &sdkLibraryProperties{}, + &commonToSdkLibraryAndImportProperties{}, &DexImportProperties{}, &android.ApexProperties{}, &RuntimeResourceOverlayProperties{}, diff --git a/java/java_test.go b/java/java_test.go index 0033f319d..f61f4bb20 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1177,12 +1177,12 @@ func TestJavaSdkLibrary(t *testing.T) { // check the existence of the internal modules ctx.ModuleForTests("foo", "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkTestApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkSystemApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkTestApiSuffix, "android_common") + ctx.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common") ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common") ctx.ModuleForTests("foo.api.public.28", "") ctx.ModuleForTests("foo.api.system.28", "") @@ -1247,6 +1247,20 @@ func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { `) } +func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { + testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java", "b.java"], + api_packages: ["foo"], + system: { + enabled: true, + sdk_version: "module_current", + }, + } + `) +} + var compilerFlagsTestCases = []struct { in string out bool diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 03bc76bf2..999c72f3c 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -15,11 +15,12 @@ package java import ( - "android/soong/android" "sort" "strings" "github.com/google/blueprint/proptools" + + "android/soong/android" ) func init() { @@ -69,6 +70,10 @@ func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, return } +func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope string, apiver string) string { + return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module +} + func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) { props := struct { Name *string @@ -76,7 +81,7 @@ func createImport(mctx android.LoadHookContext, module string, scope string, api Sdk_version *string Installable *bool }{} - props.Name = proptools.StringPtr(mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module) + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver)) props.Jars = append(props.Jars, path) // TODO(hansson): change to scope after migration is done. props.Sdk_version = proptools.StringPtr("current") @@ -124,6 +129,27 @@ func prebuiltSdkStubs(mctx android.LoadHookContext) { } } +func createSystemModules(mctx android.LoadHookContext, apiver string) { + props := struct { + Name *string + Libs []string + }{} + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver)) + props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver)) + + mctx.CreateModule(SystemModulesFactory, &props) +} + +func prebuiltSdkSystemModules(mctx android.LoadHookContext) { + for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs { + jar := android.ExistentPathForSource(mctx, + mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar") + if jar.Valid() { + createSystemModules(mctx, apiver) + } + } +} + func prebuiltApiFiles(mctx android.LoadHookContext) { mydir := mctx.ModuleDir() + "/" // <apiver>/<scope>/api/<module>.txt @@ -178,6 +204,7 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { if _, ok := mctx.Module().(*prebuiltApis); ok { prebuiltApiFiles(mctx) prebuiltSdkStubs(mctx) + prebuiltSdkSystemModules(mctx) } } @@ -191,7 +218,9 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { // Similarly, it generates a java_import for all API .jar files found under the // directory where the Android.bp is located. Specifically, an API file located // at ./<ver>/<scope>/api/<module>.jar generates a java_import module named -// <prebuilt-api-module>.<scope>.<ver>.<module>. +// <prebuilt-api-module>_<scope>_<ver>_<module>, and for SDK versions >= 30 +// a java_system_modules module named +// <prebuilt-api-module>_public_<ver>_system_modules func PrebuiltApisFactory() android.Module { module := &prebuiltApis{} module.AddProperties(&module.properties) diff --git a/java/sdk.go b/java/sdk.go index 690451c60..9310f7846 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -252,6 +252,20 @@ func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, return ver.String(), err } +func (s sdkSpec) defaultJavaLanguageVersion(ctx android.EarlyModuleContext) javaVersion { + sdk, err := s.effectiveVersion(ctx) + if err != nil { + ctx.PropertyErrorf("sdk_version", "%s", err) + } + if sdk <= 23 { + return JAVA_VERSION_7 + } else if sdk <= 29 { + return JAVA_VERSION_8 + } else { + return JAVA_VERSION_9 + } +} + func sdkSpecFrom(str string) sdkSpec { switch str { // special cases first @@ -370,10 +384,16 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep return sdkDep{} } + var systemModules string + if sdkVersion.defaultJavaLanguageVersion(ctx).usesJavaModules() { + systemModules = "sdk_public_" + sdkVersion.version.String() + "_system_modules" + } + return sdkDep{ - useFiles: true, - jars: android.Paths{jarPath.Path(), lambdaStubsPath}, - aidl: android.OptionalPathForPath(aidlPath.Path()), + useFiles: true, + jars: android.Paths{jarPath.Path(), lambdaStubsPath}, + aidl: android.OptionalPathForPath(aidlPath.Path()), + systemModules: systemModules, } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 2c85c8c09..61bb106d8 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -30,12 +30,8 @@ import ( ) const ( - sdkStubsLibrarySuffix = ".stubs" - sdkSystemApiSuffix = ".system" - sdkTestApiSuffix = ".test" - sdkStubsSourceSuffix = ".stubs.source" - sdkXmlFileSuffix = ".xml" - permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` + + sdkXmlFileSuffix = ".xml" + permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` + `<!-- Copyright (C) 2018 The Android Open Source Project\n` + `\n` + ` Licensed under the Apache License, Version 2.0 (the \"License\");\n` + @@ -96,9 +92,18 @@ type apiScope struct { // The name of the field in the dynamically created structure. fieldName string + // The name of the property in the java_sdk_library_import + propertyName string + // The tag to use to depend on the stubs library module. stubsTag scopeDependencyTag + // The tag to use to depend on the stubs source module (if separate from the API module). + stubsSourceTag scopeDependencyTag + + // The tag to use to depend on the API file generating module (if separate from the stubs source module). + apiFileTag scopeDependencyTag + // The tag to use to depend on the stubs source and API module. stubsSourceAndApiTag scopeDependencyTag @@ -117,6 +122,22 @@ type apiScope struct { // Extra arguments to pass to droidstubs for this scope. droidstubsArgs []string + // The args that must be passed to droidstubs to generate the stubs source + // for this scope. + // + // The stubs source must include the definitions of everything that is in this + // api scope and all the scopes that this one extends. + droidstubsArgsForGeneratingStubsSource []string + + // The args that must be passed to droidstubs to generate the API for this scope. + // + // The API only includes the additional members that this scope adds over the scope + // that it extends. + droidstubsArgsForGeneratingApi []string + + // True if the stubs source and api can be created by the same metalava invocation. + createStubsSourceAndApiTogether bool + // Whether the api scope can be treated as unstable, and should skip compat checks. unstable bool } @@ -124,26 +145,61 @@ type apiScope struct { // Initialize a scope, creating and adding appropriate dependency tags func initApiScope(scope *apiScope) *apiScope { name := scope.name - scope.fieldName = proptools.FieldNameForProperty(name) + scope.propertyName = strings.ReplaceAll(name, "-", "_") + scope.fieldName = proptools.FieldNameForProperty(scope.propertyName) scope.stubsTag = scopeDependencyTag{ name: name + "-stubs", apiScope: scope, depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency, } + scope.stubsSourceTag = scopeDependencyTag{ + name: name + "-stubs-source", + apiScope: scope, + depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep, + } + scope.apiFileTag = scopeDependencyTag{ + name: name + "-api", + apiScope: scope, + depInfoExtractor: (*scopePaths).extractApiInfoFromDep, + } scope.stubsSourceAndApiTag = scopeDependencyTag{ name: name + "-stubs-source-and-api", apiScope: scope, depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider, } + + // To get the args needed to generate the stubs source append all the args from + // this scope and all the scopes it extends as each set of args adds additional + // members to the stubs. + var stubsSourceArgs []string + for s := scope; s != nil; s = s.extends { + stubsSourceArgs = append(stubsSourceArgs, s.droidstubsArgs...) + } + scope.droidstubsArgsForGeneratingStubsSource = stubsSourceArgs + + // Currently the args needed to generate the API are the same as the args + // needed to add additional members. + apiArgs := scope.droidstubsArgs + scope.droidstubsArgsForGeneratingApi = apiArgs + + // If the args needed to generate the stubs and API are the same then they + // can be generated in a single invocation of metalava, otherwise they will + // need separate invocations. + scope.createStubsSourceAndApiTogether = reflect.DeepEqual(stubsSourceArgs, apiArgs) + return scope } -func (scope *apiScope) stubsModuleName(baseName string) string { - return baseName + sdkStubsLibrarySuffix + scope.moduleSuffix +func (scope *apiScope) stubsLibraryModuleName(baseName string) string { + return baseName + ".stubs" + scope.moduleSuffix } func (scope *apiScope) stubsSourceModuleName(baseName string) string { - return baseName + sdkStubsSourceSuffix + scope.moduleSuffix + return baseName + ".stubs.source" + scope.moduleSuffix +} + +func (scope *apiScope) apiModuleName(baseName string) string { + return baseName + ".api" + scope.moduleSuffix } func (scope *apiScope) String() string { @@ -183,7 +239,7 @@ var ( return &module.sdkLibraryProperties.System }, apiFilePrefix: "system-", - moduleSuffix: sdkSystemApiSuffix, + moduleSuffix: ".system", sdkVersion: "system_current", droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"}, }) @@ -195,13 +251,13 @@ var ( return &module.sdkLibraryProperties.Test }, apiFilePrefix: "test-", - moduleSuffix: sdkTestApiSuffix, + moduleSuffix: ".test", sdkVersion: "test_current", droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"}, unstable: true, }) apiScopeModuleLib = initApiScope(&apiScope{ - name: "module_lib", + name: "module-lib", extends: apiScopeSystem, // Module_lib scope is disabled by default in legacy mode. // @@ -268,6 +324,22 @@ type ApiScopeProperties struct { // Otherwise, if this is not set for any scope then the default behavior is // scope specific so please refer to the scope specific property documentation. Enabled *bool + + // The sdk_version to use for building the stubs. + // + // If not specified then it will use an sdk_version determined as follows: + // 1) If the sdk_version specified on the java_sdk_library is none then this + // will be none. This is used for java_sdk_library instances that are used + // to create stubs that contribute to the core_current sdk version. + // 2) Otherwise, it is assumed that this library extends but does not contribute + // directly to a specific sdk_version and so this uses the sdk_version appropriate + // for the api scope. e.g. public will use sdk_version: current, system will use + // sdk_version: system_current, etc. + // + // This does not affect the sdk_version used for either generating the stubs source + // or the API file. They both have to use the same sdk_version as is used for + // compiling the implementation library. + Sdk_version *string } type sdkLibraryProperties struct { @@ -351,6 +423,12 @@ type sdkLibraryProperties struct { // disabled by default. Module_lib ApiScopeProperties + // Properties related to api linting. + Api_lint struct { + // Enable api linting. + Enabled *bool + } + // TODO: determines whether to create HTML doc or not //Html_doc *bool } @@ -373,20 +451,104 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(dep android.Modul } } -func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep android.Module) error { - if provider, ok := dep.(ApiStubsProvider); ok { - paths.currentApiFilePath = provider.ApiFilePath() - paths.removedApiFilePath = provider.RemovedApiFilePath() - paths.stubsSrcJar = provider.StubsSrcJar() +func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider)) error { + if apiStubsProvider, ok := dep.(ApiStubsProvider); ok { + action(apiStubsProvider) return nil } else { return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs") } } +func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) { + paths.currentApiFilePath = provider.ApiFilePath() + paths.removedApiFilePath = provider.RemovedApiFilePath() +} + +func (paths *scopePaths) extractApiInfoFromDep(dep android.Module) error { + return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) { + paths.extractApiInfoFromApiStubsProvider(provider) + }) +} + +func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsProvider) { + paths.stubsSrcJar = provider.StubsSrcJar() +} + +func (paths *scopePaths) extractStubsSourceInfoFromDep(dep android.Module) error { + return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) { + paths.extractStubsSourceInfoFromApiStubsProviders(provider) + }) +} + +func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep android.Module) error { + return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) { + paths.extractApiInfoFromApiStubsProvider(provider) + paths.extractStubsSourceInfoFromApiStubsProviders(provider) + }) +} + +type commonToSdkLibraryAndImportProperties struct { + // The naming scheme to use for the components that this module creates. + // + // If not specified then it defaults to "default". The other allowable value is + // "framework-modules" which matches the scheme currently used by framework modules + // for the equivalent components represented as separate Soong modules. + // + // This is a temporary mechanism to simplify conversion from separate modules for each + // component that follow a different naming pattern to the default one. + // + // TODO(b/155480189) - Remove once naming inconsistencies have been resolved. + Naming_scheme *string +} + // Common code between sdk library and sdk library import type commonToSdkLibraryAndImport struct { + moduleBase *android.ModuleBase + scopePaths map[*apiScope]*scopePaths + + namingScheme sdkLibraryComponentNamingScheme + + commonProperties commonToSdkLibraryAndImportProperties +} + +func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { + c.moduleBase = moduleBase + + moduleBase.AddProperties(&c.commonProperties) +} + +func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { + schemeProperty := proptools.StringDefault(c.commonProperties.Naming_scheme, "default") + switch schemeProperty { + case "default": + c.namingScheme = &defaultNamingScheme{} + case "framework-modules": + c.namingScheme = &frameworkModulesNamingScheme{} + default: + ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty) + return false + } + + return true +} + +// Name of the java_library module that compiles the stubs source. +func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string { + return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName()) +} + +// Name of the droidstubs module that generates the stubs source and may also +// generate/check the API. +func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string { + return c.namingScheme.stubsSourceModuleName(apiScope, c.moduleBase.BaseModuleName()) +} + +// Name of the droidstubs module that generates/checks the API. Only used if it +// requires different arts to the stubs source generating module. +func (c *commonToSdkLibraryAndImport) apiModuleName(apiScope *apiScope) string { + return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName()) } func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths { @@ -480,10 +642,18 @@ func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { for _, apiScope := range module.getGeneratedApiScopes(ctx) { // Add dependencies to the stubs library - ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) - // And the stubs source and api files - ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceName(apiScope)) + // If the stubs source and API cannot be generated together then add an additional dependency on + // the API module. + if apiScope.createStubsSourceAndApiTogether { + // Add a dependency on the stubs source in order to access both stubs source and api information. + ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope)) + } else { + // Add separate dependencies on the creators of the stubs source files and the API. + ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.apiModuleName(apiScope)) + } } if !proptools.Bool(module.sdkLibraryProperties.Api_only) { @@ -528,17 +698,6 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { return entriesList } -// Name of the java_library module that compiles the stubs source. -func (module *SdkLibrary) stubsName(apiScope *apiScope) string { - return apiScope.stubsModuleName(module.BaseModuleName()) -} - -// // Name of the droidstubs module that generates the stubs source and -// generates/checks the API. -func (module *SdkLibrary) stubsSourceName(apiScope *apiScope) string { - return apiScope.stubsSourceModuleName(module.BaseModuleName()) -} - // Module name of the runtime implementation library func (module *SdkLibrary) implName() string { return module.BaseModuleName() @@ -561,7 +720,12 @@ func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string { } // Get the sdk version for use when compiling the stubs library. -func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) string { +func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string { + scopeProperties := module.scopeToProperties[apiScope] + if scopeProperties.Sdk_version != nil { + return proptools.String(scopeProperties.Sdk_version) + } + sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library)) if sdkDep.hasStandardLibs() { // If building against a standard sdk then use the sdk version appropriate for the scope. @@ -583,21 +747,17 @@ func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) stri // Creates a static java library that has API stubs func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { props := struct { - Name *string - Visibility []string - Srcs []string - Installable *bool - Sdk_version *string - System_modules *string - Patch_module *string - Libs []string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Compile_dex *bool - Java_version *string - Product_variables struct { + Name *string + Visibility []string + Srcs []string + Installable *bool + Sdk_version *string + System_modules *string + Patch_module *string + Libs []string + Compile_dex *bool + Java_version *string + Product_variables struct { Pdk struct { Enabled *bool } @@ -614,7 +774,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext } }{} - props.Name = proptools.StringPtr(module.stubsName(apiScope)) + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) // If stubs_library_visibility is not set then the created module will use the // visibility of this module. @@ -622,30 +782,21 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Visibility = visibility // sources are generated from the droiddoc - props.Srcs = []string{":" + module.stubsSourceName(apiScope)} + props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) props.Sdk_version = proptools.StringPtr(sdkVersion) - props.System_modules = module.Library.Module.deviceProperties.System_modules - props.Patch_module = module.Library.Module.properties.Patch_module + props.System_modules = module.deviceProperties.System_modules + props.Patch_module = module.properties.Patch_module props.Installable = proptools.BoolPtr(false) props.Libs = module.sdkLibraryProperties.Stub_only_libs props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false) - props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs - props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags - props.Java_version = module.Library.Module.properties.Java_version - if module.Library.Module.deviceProperties.Compile_dex != nil { - props.Compile_dex = module.Library.Module.deviceProperties.Compile_dex + props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs + props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags + props.Java_version = module.properties.Java_version + if module.deviceProperties.Compile_dex != nil { + props.Compile_dex = module.deviceProperties.Compile_dex } - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } 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"} @@ -659,7 +810,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext // Creates a droidstubs module that creates stubs source files from the given full source // files and also updates and checks the API specification files. -func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope) { +func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, createStubSources, createApi bool, scopeSpecificDroidstubsArgs []string) { props := struct { Name *string Visibility []string @@ -673,10 +824,17 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC Java_version *string Merge_annotations_dirs []string Merge_inclusion_annotations_dirs []string + Generate_stubs *bool Check_api struct { Current ApiToCheck Last_released ApiToCheck Ignore_missing_latest_api *bool + + Api_lint struct { + Enabled *bool + New_since *string + Baseline_file *string + } } Aidl struct { Include_dirs []string @@ -695,24 +853,24 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC // * system_modules // * libs (static_libs/libs) - props.Name = proptools.StringPtr(module.stubsSourceName(apiScope)) + props.Name = proptools.StringPtr(name) // If stubs_source_visibility is not set then the created module will use the // visibility of this module. visibility := module.sdkLibraryProperties.Stubs_source_visibility props.Visibility = visibility - props.Srcs = append(props.Srcs, module.Library.Module.properties.Srcs...) - props.Sdk_version = module.Library.Module.deviceProperties.Sdk_version - props.System_modules = module.Library.Module.deviceProperties.System_modules + props.Srcs = append(props.Srcs, module.properties.Srcs...) + props.Sdk_version = module.deviceProperties.Sdk_version + props.System_modules = module.deviceProperties.System_modules props.Installable = proptools.BoolPtr(false) // A droiddoc module has only one Libs property and doesn't distinguish between // shared libs and static libs. So we need to add both of these libs to Libs property. - props.Libs = module.Library.Module.properties.Libs - props.Libs = append(props.Libs, module.Library.Module.properties.Static_libs...) - props.Aidl.Include_dirs = module.Library.Module.deviceProperties.Aidl.Include_dirs - props.Aidl.Local_include_dirs = module.Library.Module.deviceProperties.Aidl.Local_include_dirs - props.Java_version = module.Library.Module.properties.Java_version + props.Libs = module.properties.Libs + props.Libs = append(props.Libs, module.properties.Static_libs...) + props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs + props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs + props.Java_version = module.properties.Java_version props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs @@ -739,38 +897,64 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC } droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) + if !createStubSources { + // Stubs are not required. + props.Generate_stubs = proptools.BoolPtr(false) + } + // Add in scope specific arguments. - droidstubsArgs = append(droidstubsArgs, apiScope.droidstubsArgs...) + droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files 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 - // last-released (a.k.a numbered) list of API. - currentApiFileName := apiScope.apiFilePrefix + "current.txt" - removedApiFileName := apiScope.apiFilePrefix + "removed.txt" - apiDir := module.getApiDir() - currentApiFileName = path.Join(apiDir, currentApiFileName) - removedApiFileName = path.Join(apiDir, removedApiFileName) - - // check against the not-yet-release API - props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) - props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) - - if !apiScope.unstable { - // check against the latest released API - props.Check_api.Last_released.Api_file = proptools.StringPtr( - module.latestApiFilegroupName(apiScope)) - props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( - module.latestRemovedApiFilegroupName(apiScope)) - props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) - } + if createApi { + // 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 + // last-released (a.k.a numbered) list of API. + currentApiFileName := apiScope.apiFilePrefix + "current.txt" + removedApiFileName := apiScope.apiFilePrefix + "removed.txt" + apiDir := module.getApiDir() + currentApiFileName = path.Join(apiDir, currentApiFileName) + removedApiFileName = path.Join(apiDir, removedApiFileName) + + // check against the not-yet-release API + props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) + props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) + + if !apiScope.unstable { + // check against the latest released API + latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) + props.Check_api.Last_released.Api_file = latestApiFilegroupName + props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( + module.latestRemovedApiFilegroupName(apiScope)) + props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) + + if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { + // Enable api lint. + props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) + props.Check_api.Api_lint.New_since = latestApiFilegroupName + + // If it exists then pass a lint-baseline.txt through to droidstubs. + baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") + baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) + paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) + if err != nil { + mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) + } + if len(paths) == 1 { + props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) + } else if len(paths) != 0 { + mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) + } + } + } - // 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")) + // 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) @@ -787,29 +971,15 @@ func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep an // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { props := struct { - Name *string - Lib_name *string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Apex_available []string + Name *string + Lib_name *string + Apex_available []string }{ Name: proptools.StringPtr(module.xmlFileName()), Lib_name: proptools.StringPtr(module.BaseModuleName()), Apex_available: module.ApexProperties.Apex_available, } - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } else if module.SystemExtSpecific() { - props.System_ext_specific = proptools.BoolPtr(true) - } - mctx.CreateModule(sdkLibraryXmlFactory, &props) } @@ -851,9 +1021,9 @@ func (module *SdkLibrary) sdkJars( } else { if !sdkVersion.specified() { if headerJars { - return module.Library.HeaderJars() + return module.HeaderJars() } else { - return module.Library.ImplementationJars() + return module.ImplementationJars() } } var apiScope *apiScope @@ -863,7 +1033,7 @@ func (module *SdkLibrary) sdkJars( case sdkTest: apiScope = apiScopeTest case sdkPrivate: - return module.Library.HeaderJars() + return module.HeaderJars() default: apiScope = apiScopePublic } @@ -912,7 +1082,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont return } - if len(module.Library.Module.properties.Srcs) == 0 { + if len(module.properties.Srcs) == 0 { mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs") return } @@ -958,8 +1128,24 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont } for _, scope := range generatedScopes { + stubsSourceArgs := scope.droidstubsArgsForGeneratingStubsSource + stubsSourceModuleName := module.stubsSourceModuleName(scope) + + // If the args needed to generate the stubs and API are the same then they + // can be generated in a single invocation of metalava, otherwise they will + // need separate invocations. + if scope.createStubsSourceAndApiTogether { + // Use the stubs source name for legacy reasons. + module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, true, stubsSourceArgs) + } else { + module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, false, stubsSourceArgs) + + apiArgs := scope.droidstubsArgsForGeneratingApi + apiName := module.apiModuleName(scope) + module.createStubsSourcesAndApi(mctx, scope, apiName, false, true, apiArgs) + } + module.createStubsLibrary(mctx, scope) - module.createStubsSourcesAndApi(mctx, scope) } if !proptools.Bool(module.sdkLibraryProperties.Api_only) { @@ -977,16 +1163,67 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont func (module *SdkLibrary) InitSdkLibraryProperties() { module.AddProperties( &module.sdkLibraryProperties, - &module.Library.Module.properties, - &module.Library.Module.dexpreoptProperties, - &module.Library.Module.deviceProperties, - &module.Library.Module.protoProperties, + &module.properties, + &module.dexpreoptProperties, + &module.deviceProperties, + &module.protoProperties, ) - module.Library.Module.properties.Installable = proptools.BoolPtr(true) - module.Library.Module.deviceProperties.IsSDKLibrary = true + module.properties.Installable = proptools.BoolPtr(true) + module.deviceProperties.IsSDKLibrary = true +} + +// Defines how to name the individual component modules the sdk library creates. +type sdkLibraryComponentNamingScheme interface { + stubsLibraryModuleName(scope *apiScope, baseName string) string + + stubsSourceModuleName(scope *apiScope, baseName string) string + + apiModuleName(scope *apiScope, baseName string) string +} + +type defaultNamingScheme struct { +} + +func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { + return scope.stubsLibraryModuleName(baseName) } +func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { + return scope.stubsSourceModuleName(baseName) +} + +func (s *defaultNamingScheme) apiModuleName(scope *apiScope, baseName string) string { + return scope.apiModuleName(baseName) +} + +var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) + +type frameworkModulesNamingScheme struct { +} + +func (s *frameworkModulesNamingScheme) moduleSuffix(scope *apiScope) string { + suffix := scope.name + if scope == apiScopeModuleLib { + suffix = "module_libs_" + } + return suffix +} + +func (s *frameworkModulesNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-stubs-%sapi", baseName, s.moduleSuffix(scope)) +} + +func (s *frameworkModulesNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-stubs-srcs-%sapi", baseName, s.moduleSuffix(scope)) +} + +func (s *frameworkModulesNamingScheme) apiModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-api-%sapi", baseName, s.moduleSuffix(scope)) +} + +var _ sdkLibraryComponentNamingScheme = (*frameworkModulesNamingScheme)(nil) + // java_sdk_library is a special Java library that provides optional platform APIs to apps. // In practice, it can be viewed as a combination of several modules: 1) stubs library that clients // are linked against to, 2) droiddoc module that internally generates API stubs source files, @@ -994,6 +1231,10 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { // the runtime lib to the classpath at runtime if requested via <uses-library>. func SdkLibraryFactory() android.Module { module := &SdkLibrary{} + + // Initialize information common between source and prebuilt. + module.initCommon(&module.ModuleBase) + module.InitSdkLibraryProperties() android.InitApexModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -1009,7 +1250,11 @@ func SdkLibraryFactory() android.Module { android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility) android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) - module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { module.CreateInternalModules(ctx) }) + module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + if module.initCommonAfterDefaultsApplied(ctx) { + module.CreateInternalModules(ctx) + } + }) return module } @@ -1105,12 +1350,19 @@ func sdkLibraryImportFactory() android.Module { module.scopeProperties = scopeToProperties module.AddProperties(&module.properties, allScopeProperties) + // Initialize information common between source and prebuilt. + module.initCommon(&module.ModuleBase) + android.InitPrebuiltModule(module, &[]string{""}) android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) - module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { module.createInternalModules(mctx) }) + module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { + if module.initCommonAfterDefaultsApplied(mctx) { + module.createInternalModules(mctx) + } + }) return module } @@ -1148,47 +1400,36 @@ func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHo func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { // Creates a java import for the jar with ".stubs" suffix props := struct { - Name *string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Sdk_version *string - Libs []string - Jars []string - Prefer *bool + Name *string + Sdk_version *string + Libs []string + Jars []string + Prefer *bool }{} - props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName())) + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) props.Sdk_version = scopeProperties.Sdk_version // Prepend any of the libs from the legacy public properties to the libs for each of the // scopes to avoid having to duplicate them in each scope. props.Libs = append(module.properties.Libs, scopeProperties.Libs...) props.Jars = scopeProperties.Jars - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } else if module.SystemExtSpecific() { - props.System_ext_specific = proptools.BoolPtr(true) - } - // If the build should use prebuilt sdks then set prefer to true on the stubs library. - // That will cause the prebuilt version of the stubs to override the source version. - if mctx.Config().UnbundledBuildUsePrebuiltSdks() { - props.Prefer = proptools.BoolPtr(true) - } + + // The imports are preferred if the java_sdk_library_import is preferred. + props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) mctx.CreateModule(ImportFactory, &props) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { props := struct { - Name *string - Srcs []string + Name *string + Srcs []string + Prefer *bool }{} - props.Name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName())) + props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope)) props.Srcs = scopeProperties.Stub_srcs mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) + + // The stubs source is preferred if the java_sdk_library_import is preferred. + props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) } func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1198,7 +1439,7 @@ func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) } // Add dependencies to the prebuilt stubs library - ctx.AddVariationDependencies(nil, apiScope.stubsTag, apiScope.stubsModuleName(module.BaseModuleName())) + ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) } } @@ -1392,6 +1633,9 @@ type sdkLibrarySdkMemberProperties struct { // The Java stubs source files. Stub_srcs []string + + // The naming scheme. + Naming_scheme *string } type scopeProperties struct { @@ -1412,7 +1656,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe if len(jars) > 0 { properties := scopeProperties{} properties.Jars = jars - properties.SdkVersion = apiScope.sdkVersion + properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope) properties.StubsSrcJar = paths.stubsSrcJar properties.CurrentApiFile = paths.currentApiFilePath properties.RemovedApiFile = paths.removedApiFilePath @@ -1421,12 +1665,17 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe } s.Libs = sdk.properties.Libs + s.Naming_scheme = sdk.commonProperties.Naming_scheme } func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { + if s.Naming_scheme != nil { + propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme)) + } + for _, apiScope := range allApiScopes { if properties, ok := s.Scopes[apiScope]; ok { - scopeSet := propertySet.AddPropertySet(apiScope.name) + scopeSet := propertySet.AddPropertySet(apiScope.propertyName) scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name) diff --git a/java/sdk_test.go b/java/sdk_test.go index 088db9e70..fb8646313 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -83,6 +83,16 @@ func TestClasspath(t *testing.T) { }, { + name: "sdk v30", + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "current", properties: `sdk_version: "current",`, bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"}, @@ -110,6 +120,16 @@ func TestClasspath(t *testing.T) { }, { + name: "system_30", + properties: `sdk_version: "system_30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "test_current", properties: `sdk_version: "test_current",`, bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"}, @@ -176,12 +196,24 @@ func TestClasspath(t *testing.T) { }, { + name: "unbundled sdk v30", + unbundled: true, + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "unbundled current", unbundled: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, + system: "sdk_public_current_system_modules", java8classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/current/public/framework.aidl", }, @@ -189,27 +221,30 @@ func TestClasspath(t *testing.T) { name: "pdk default", pdk: true, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk current", pdk: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk 29", pdk: true, properties: `sdk_version: "29",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "module_current", @@ -292,12 +327,16 @@ func TestClasspath(t *testing.T) { if testcase.system == "none" { system = "--system=none" } else if testcase.system != "" { - system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + dir := "" + if strings.HasPrefix(testcase.system, "sdk_public_") { + dir = "prebuilts/sdk" + } + system = "--system=" + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system") // The module-relative parts of these paths are hardcoded in system_modules.go: systemDeps = []string{ - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "modules"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "release"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "modules"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "release"), } } diff --git a/java/testing.go b/java/testing.go index 6929bb724..196714852 100644 --- a/java/testing.go +++ b/java/testing.go @@ -55,36 +55,54 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "assets_a/a": nil, "assets_b/b": nil, - "prebuilts/sdk/14/public/android.jar": nil, - "prebuilts/sdk/14/public/framework.aidl": nil, - "prebuilts/sdk/14/system/android.jar": nil, - "prebuilts/sdk/17/public/android.jar": nil, - "prebuilts/sdk/17/public/framework.aidl": nil, - "prebuilts/sdk/17/system/android.jar": nil, - "prebuilts/sdk/29/public/android.jar": nil, - "prebuilts/sdk/29/public/framework.aidl": nil, - "prebuilts/sdk/29/system/android.jar": nil, - "prebuilts/sdk/29/system/foo.jar": nil, - "prebuilts/sdk/current/core/android.jar": nil, - "prebuilts/sdk/current/public/android.jar": nil, - "prebuilts/sdk/current/public/framework.aidl": nil, - "prebuilts/sdk/current/public/core.jar": nil, - "prebuilts/sdk/current/system/android.jar": nil, - "prebuilts/sdk/current/test/android.jar": nil, - "prebuilts/sdk/28/public/api/foo.txt": nil, - "prebuilts/sdk/28/system/api/foo.txt": nil, - "prebuilts/sdk/28/test/api/foo.txt": nil, - "prebuilts/sdk/28/public/api/foo-removed.txt": nil, - "prebuilts/sdk/28/system/api/foo-removed.txt": nil, - "prebuilts/sdk/28/test/api/foo-removed.txt": nil, - "prebuilts/sdk/28/public/api/bar.txt": nil, - "prebuilts/sdk/28/system/api/bar.txt": nil, - "prebuilts/sdk/28/test/api/bar.txt": nil, - "prebuilts/sdk/28/public/api/bar-removed.txt": nil, - "prebuilts/sdk/28/system/api/bar-removed.txt": nil, - "prebuilts/sdk/28/test/api/bar-removed.txt": nil, - "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, - "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), + "prebuilts/sdk/14/public/android.jar": nil, + "prebuilts/sdk/14/public/framework.aidl": nil, + "prebuilts/sdk/14/system/android.jar": nil, + "prebuilts/sdk/17/public/android.jar": nil, + "prebuilts/sdk/17/public/framework.aidl": nil, + "prebuilts/sdk/17/system/android.jar": nil, + "prebuilts/sdk/29/public/android.jar": nil, + "prebuilts/sdk/29/public/framework.aidl": nil, + "prebuilts/sdk/29/system/android.jar": nil, + "prebuilts/sdk/29/system/foo.jar": nil, + "prebuilts/sdk/30/public/android.jar": nil, + "prebuilts/sdk/30/public/framework.aidl": nil, + "prebuilts/sdk/30/system/android.jar": nil, + "prebuilts/sdk/30/system/foo.jar": nil, + "prebuilts/sdk/30/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/core/android.jar": nil, + "prebuilts/sdk/current/public/android.jar": nil, + "prebuilts/sdk/current/public/framework.aidl": nil, + "prebuilts/sdk/current/public/core.jar": nil, + "prebuilts/sdk/current/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/system/android.jar": nil, + "prebuilts/sdk/current/test/android.jar": nil, + "prebuilts/sdk/28/public/api/foo.txt": nil, + "prebuilts/sdk/28/system/api/foo.txt": nil, + "prebuilts/sdk/28/test/api/foo.txt": nil, + "prebuilts/sdk/28/public/api/foo-removed.txt": nil, + "prebuilts/sdk/28/system/api/foo-removed.txt": nil, + "prebuilts/sdk/28/test/api/foo-removed.txt": nil, + "prebuilts/sdk/28/public/api/bar.txt": nil, + "prebuilts/sdk/28/system/api/bar.txt": nil, + "prebuilts/sdk/28/test/api/bar.txt": nil, + "prebuilts/sdk/28/public/api/bar-removed.txt": nil, + "prebuilts/sdk/28/system/api/bar-removed.txt": nil, + "prebuilts/sdk/28/test/api/bar-removed.txt": nil, + "prebuilts/sdk/30/public/api/foo.txt": nil, + "prebuilts/sdk/30/system/api/foo.txt": nil, + "prebuilts/sdk/30/test/api/foo.txt": nil, + "prebuilts/sdk/30/public/api/foo-removed.txt": nil, + "prebuilts/sdk/30/system/api/foo-removed.txt": nil, + "prebuilts/sdk/30/test/api/foo-removed.txt": nil, + "prebuilts/sdk/30/public/api/bar.txt": nil, + "prebuilts/sdk/30/system/api/bar.txt": nil, + "prebuilts/sdk/30/test/api/bar.txt": nil, + "prebuilts/sdk/30/public/api/bar-removed.txt": nil, + "prebuilts/sdk/30/system/api/bar-removed.txt": nil, + "prebuilts/sdk/30/test/api/bar-removed.txt": nil, + "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, + "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), "prebuilts/apk/app.apk": nil, "prebuilts/apk/app_arm.apk": nil, @@ -92,6 +110,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/apk/app_xhdpi.apk": nil, "prebuilts/apk/app_xxhdpi.apk": nil, + "prebuilts/apks/app.apks": nil, + // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, "build/make/target/product/security/testkey": nil, @@ -116,6 +136,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "cert/new_cert.x509.pem": nil, "cert/new_cert.pk8": nil, + "lineage.bin": nil, "testdata/data": nil, |