diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/aar.go | 10 | ||||
-rw-r--r-- | java/androidmk.go | 25 | ||||
-rw-r--r-- | java/androidmk_test.go | 190 | ||||
-rwxr-xr-x | java/app.go | 135 | ||||
-rw-r--r-- | java/app_test.go | 180 | ||||
-rw-r--r-- | java/config/config.go | 12 | ||||
-rw-r--r-- | java/config/makevars.go | 8 | ||||
-rw-r--r-- | java/device_host_converter.go | 6 | ||||
-rw-r--r-- | java/dexpreopt.go | 23 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 187 | ||||
-rw-r--r-- | java/dexpreopt_bootjars_test.go | 95 | ||||
-rw-r--r-- | java/dexpreopt_config.go | 86 | ||||
-rw-r--r-- | java/droiddoc.go | 81 | ||||
-rw-r--r-- | java/hiddenapi_singleton.go | 4 | ||||
-rw-r--r-- | java/java.go | 157 | ||||
-rw-r--r-- | java/java_test.go | 202 | ||||
-rw-r--r-- | java/jdeps.go | 1 | ||||
-rw-r--r-- | java/kotlin.go | 70 | ||||
-rw-r--r-- | java/prebuilt_apis.go | 3 | ||||
-rw-r--r-- | java/sdk.go | 63 | ||||
-rw-r--r-- | java/sdk_library.go | 48 | ||||
-rw-r--r-- | java/sdk_test.go | 35 | ||||
-rw-r--r-- | java/testing.go | 59 |
23 files changed, 1243 insertions, 437 deletions
diff --git a/java/aar.go b/java/aar.go index 8dd752f12..ad9b5e7d2 100644 --- a/java/aar.go +++ b/java/aar.go @@ -734,7 +734,11 @@ func (a *AARImport) ImplementationAndResourcesJars() android.Paths { return android.Paths{a.classpathFile} } -func (a *AARImport) DexJar() android.Path { +func (a *AARImport) DexJarBuildPath() android.Path { + return nil +} + +func (a *AARImport) DexJarInstallPath() android.Path { return nil } @@ -758,6 +762,10 @@ func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.M return a.depIsInSameApex(ctx, dep) } +func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + return nil +} + var _ android.PrebuiltInterface = (*Import)(nil) // android_library_import imports an `.aar` file into the build graph as if it was built with android_library. diff --git a/java/androidmk.go b/java/androidmk.go index 62f97067c..03994bfd6 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -91,7 +91,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { } else { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", - DistFile: android.OptionalPathForPath(library.distFile), + DistFiles: library.distFiles, OutputFile: android.OptionalPathForPath(library.outputFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ @@ -545,14 +545,12 @@ func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries { fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:", ddoc.checkLastReleasedApiTimestamp.String()) - if ddoc.Name() == "api-stubs-docs" || ddoc.Name() == "system-api-stubs-docs" { - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - ddoc.checkLastReleasedApiTimestamp.String()) + fmt.Fprintln(w, ".PHONY: checkapi") + fmt.Fprintln(w, "checkapi:", + ddoc.checkLastReleasedApiTimestamp.String()) - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - } + fmt.Fprintln(w, ".PHONY: droidcore") + fmt.Fprintln(w, "droidcore: checkapi") } }, }, @@ -566,14 +564,14 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries { // needed because an invalid output file would prevent the make entries from // being written. // TODO(b/146727827): Revert when we do not need to generate stubs and API separately. - distFile := android.OptionalPathForPath(dstubs.apiFile) + distFile := dstubs.apiFile outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar) if !outputFile.Valid() { - outputFile = distFile + outputFile = android.OptionalPathForPath(distFile) } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", - DistFile: distFile, + DistFiles: android.MakeDefaultDistFiles(distFile), OutputFile: outputFile, Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ @@ -669,6 +667,11 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries { } func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries { + if !a.IsForPlatform() { + // The non-platform variant is placed inside APEX. No reason to + // make it available to Make. + return nil + } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "APPS", OutputFile: android.OptionalPathForPath(a.outputFile), diff --git a/java/androidmk_test.go b/java/androidmk_test.go index 7daa6244f..075b7aa6f 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -156,16 +156,190 @@ func TestDistWithTag(t *testing.T) { } `) - without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) - with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) + withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) + withTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) - if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 { - t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries)) + if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries)) } - if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") { - t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile) + if len(withTagEntries[0].DistFiles[".jar"]) != 1 || + !strings.Contains(withTagEntries[0].DistFiles[".jar"][0].String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected DistFiles to contain classes.jar, got %v", withTagEntries[0].DistFiles) } - if without_tag_entries[0].DistFile.Valid() { - t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile) + if len(withoutTagEntries[0].DistFiles[".jar"]) > 0 { + t.Errorf("did not expect explicit DistFile for .jar tag, got %v", withoutTagEntries[0].DistFiles[".jar"]) + } +} + +func TestDistWithDest(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["my_goal"], + dest: "my/custom/dest/dir", + }, + } + `) + + module := ctx.ModuleForTests("foo", "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, config, "", module) + if len(entries) != 2 { + t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries)) + } + + distStrings := entries[0].GetDistForGoals(module) + + if len(distStrings) != 2 { + t.Errorf("Expected 2 entries for dist: PHONY and dist-for-goals, but got %q", distStrings) + } + + if distStrings[0] != ".PHONY: my_goal\n" { + t.Errorf("Expected .PHONY entry to declare my_goal, but got: %s", distStrings[0]) + } + + if !strings.Contains(distStrings[1], "$(call dist-for-goals,my_goal") || + !strings.Contains(distStrings[1], ".intermediates/foo/android_common/dex/foo.jar:my/custom/dest/dir") { + t.Errorf( + "Expected dist-for-goals entry to contain my_goal and new dest dir, but got: %s", distStrings[1]) + } +} + +func TestDistsWithAllProperties(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["baz"], + }, + dists: [ + { + targets: ["bar"], + tag: ".jar", + dest: "bar.jar", + dir: "bar/dir", + suffix: ".qux", + }, + ] + } + `) + + module := ctx.ModuleForTests("foo", "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, config, "", module) + if len(entries) != 2 { + t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries)) + } + + distStrings := entries[0].GetDistForGoals(module) + + if len(distStrings) != 4 { + t.Errorf("Expected 4 entries for dist: PHONY and dist-for-goals, but got %d", len(distStrings)) + } + + if distStrings[0] != ".PHONY: bar\n" { + t.Errorf("Expected .PHONY entry to declare bar, but got: %s", distStrings[0]) + } + + if !strings.Contains(distStrings[1], "$(call dist-for-goals,bar") || + !strings.Contains( + distStrings[1], + ".intermediates/foo/android_common/javac/foo.jar:bar/dir/bar.qux.jar") { + t.Errorf( + "Expected dist-for-goals entry to contain bar and new dest dir, but got: %s", distStrings[1]) + } + + if distStrings[2] != ".PHONY: baz\n" { + t.Errorf("Expected .PHONY entry to declare baz, but got: %s", distStrings[2]) + } + + if !strings.Contains(distStrings[3], "$(call dist-for-goals,baz") || + !strings.Contains(distStrings[3], ".intermediates/foo/android_common/dex/foo.jar:foo.jar") { + t.Errorf( + "Expected dist-for-goals entry to contain my_other_goal and new dest dir, but got: %s", + distStrings[3]) + } +} + +func TestDistsWithTag(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo_without_tag", + srcs: ["a.java"], + compile_dex: true, + dists: [ + { + targets: ["hi"], + }, + ], + } + java_library { + name: "foo_with_tag", + srcs: ["a.java"], + compile_dex: true, + dists: [ + { + targets: ["hi"], + tag: ".jar", + }, + ], + } + `) + + moduleWithoutTag := ctx.ModuleForTests("foo_without_tag", "android_common").Module() + moduleWithTag := ctx.ModuleForTests("foo_with_tag", "android_common").Module() + + withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithoutTag) + withTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithTag) + + if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries)) + } + + distFilesWithoutTag := withoutTagEntries[0].DistFiles + distFilesWithTag := withTagEntries[0].DistFiles + + if len(distFilesWithTag[".jar"]) != 1 || + !strings.Contains(distFilesWithTag[".jar"][0].String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected foo_with_tag's .jar-tagged DistFiles to contain classes.jar, got %v", distFilesWithTag[".jar"]) + } + if len(distFilesWithoutTag[".jar"]) > 0 { + t.Errorf("did not expect foo_without_tag's .jar-tagged DistFiles to contain files, but got %v", distFilesWithoutTag[".jar"]) + } +} + +func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { + ctx, config := testJava(t, ` + java_sdk_library { + name: "foo-shared_library", + srcs: ["a.java"], + } + java_sdk_library { + name: "foo-no_shared_library", + srcs: ["a.java"], + shared_library: false, + } + `) + + // Verify the existence of internal modules + ctx.ModuleForTests("foo-shared_library.xml", "android_common") + + testCases := []struct { + moduleName string + expected []string + }{ + {"foo-shared_library", []string{"foo-shared_library.xml"}}, + {"foo-no_shared_library", nil}, + } + for _, tc := range testCases { + mod := ctx.ModuleForTests(tc.moduleName, "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] + actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"] + if !reflect.DeepEqual(tc.expected, actual) { + t.Errorf("Unexpected required modules - expected: %q, actual: %q", tc.expected, actual) + } } } diff --git a/java/app.go b/java/app.go index e75d8749f..b4bc39e0f 100755 --- a/java/app.go +++ b/java/app.go @@ -28,6 +28,7 @@ import ( "android/soong/android" "android/soong/cc" + "android/soong/dexpreopt" "android/soong/tradefed" ) @@ -267,6 +268,9 @@ type overridableAppProperties struct { // the logging parent of this app. Logging_parent *string + + // Whether to rename the package in resources to the override name rather than the base name. Defaults to true. + Rename_resources_package *bool } // runtime_resource_overlay properties that can be overridden by override_runtime_resource_overlay @@ -431,8 +435,10 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { 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) + android.CheckMinSdkVersion(a, ctx, int(minSdkVersion)) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } @@ -504,10 +510,23 @@ func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool { !a.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs } +func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { + aaptFlags := []string{"--rename-manifest-package " + packageName} + if renameResourcesPackage { + // Required to rename the package name in the resources table. + aaptFlags = append(aaptFlags, "--rename-resources-package "+packageName) + } + return aaptFlags +} + func (a *AndroidApp) OverriddenManifestPackageName() string { return a.overriddenManifestPackageName } +func (a *AndroidApp) renameResourcesPackage() bool { + return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true) +} + func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis) @@ -540,7 +559,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { if !overridden { manifestPackageName = *a.overridableAppProperties.Package_name } - aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName) + aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...) a.overriddenManifestPackageName = manifestPackageName } @@ -663,16 +682,20 @@ func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) { return false } - path := child.(android.Module).NoticeFile() - if path.Valid() { - noticePathSet[path.Path()] = true + paths := child.(android.Module).NoticeFiles() + if len(paths) > 0 { + for _, path := range paths { + noticePathSet[path] = true + } } return true }) // If the app has one, add it too. - if a.NoticeFile().Valid() { - noticePathSet[a.NoticeFile().Path()] = true + if len(a.NoticeFiles()) > 0 { + for _, path := range a.NoticeFiles() { + noticePathSet[path] = true + } } if len(noticePathSet) == 0 { @@ -769,7 +792,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.linter.mergedManifest = a.aapt.mergedManifestFile a.linter.manifest = a.aapt.manifestPath a.linter.resources = a.aapt.resourceFiles - a.linter.buildModuleReportZip = ctx.Config().UnbundledBuild() + a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps() dexJarFile := a.dexBuildActions(ctx) @@ -902,13 +925,13 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, return jniLibs, certificates } -func (a *AndroidApp) walkPayloadDeps(ctx android.ModuleContext, - do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) { - +func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) { ctx.WalkDeps(func(child, parent android.Module) bool { isExternal := !a.DepIsInSameApex(ctx, child) if am, ok := child.(android.ApexModule); ok { - do(ctx, parent, am, isExternal) + if !do(ctx, parent, am, isExternal) { + return false + } } return !isExternal }) @@ -920,7 +943,7 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { } depsInfo := android.DepNameToDepInfoMap{} - a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { + a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { depName := to.Name() if info, exist := depsInfo[depName]; exist { info.From = append(info.From, from.Name()) @@ -940,6 +963,7 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { MinSdkVersion: toMinSdkVersion, } } + return true }) a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo) @@ -993,6 +1017,8 @@ func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) { a.appProperties.IsCoverageVariant = coverage } +func (a *AndroidApp) EnableCoverageIfNeeded() {} + var _ cc.Coverage = (*AndroidApp)(nil) // android_app compiles sources and Android resources into an Android application package `.apk` file. @@ -1012,10 +1038,6 @@ func AndroidAppFactory() android.Module { &module.overridableAppProperties, &module.usesLibrary.usesLibraryProperties) - module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { - return class == android.Device && ctx.Config().DevicePrefer32BitApps() - }) - android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) android.InitOverridableModule(module, &module.appProperties.Overrides) @@ -1025,6 +1047,7 @@ func AndroidAppFactory() android.Module { } type appTestProperties struct { + // The name of the android_app module that the tests will run against. Instrumentation_for *string // if specified, the instrumentation target package name in the manifest is overwritten by it. @@ -1285,6 +1308,7 @@ func OverrideRuntimeResourceOverlayModuleFactory() android.Module { type AndroidAppImport struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase prebuilt android.Prebuilt properties AndroidAppImportProperties @@ -1535,7 +1559,9 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // TODO: Optionally compress the output apk. - a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile) + if a.IsForPlatform() { + a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile) + } // TODO: androidmk converter jni libs } @@ -1586,6 +1612,13 @@ func (a *AndroidAppImport) Privileged() bool { return Bool(a.properties.Privileged) } +func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool { + // android_app_import might have extra dependencies via uses_libs property. + // Don't track the dependency as we don't automatically add those libraries + // to the classpath. It should be explicitly added to java_libs property of APEX + return false +} + func (a *AndroidAppImport) sdkVersion() sdkSpec { return sdkSpecFrom("") } @@ -1594,6 +1627,11 @@ func (a *AndroidAppImport) minSdkVersion() sdkSpec { return sdkSpecFrom("") } +func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + // Do not check for prebuilts against the min_sdk_version of enclosing APEX + return nil +} + func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { props := reflect.TypeOf((*AndroidAppImportProperties)(nil)) @@ -1640,6 +1678,7 @@ func AndroidAppImportFactory() android.Module { module.processVariants(ctx) }) + android.InitApexModule(module) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk") @@ -1690,6 +1729,7 @@ func AndroidTestImportFactory() android.Module { module.dexpreopter.isTest = true + android.InitApexModule(module) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk") @@ -1746,6 +1786,15 @@ type RuntimeResourceOverlayProperties struct { Overrides []string } +// RuntimeResourceOverlayModule interface is used by the apex package to gather information from +// a RuntimeResourceOverlay module. +type RuntimeResourceOverlayModule interface { + android.Module + OutputFile() android.Path + Certificate() Certificate + Theme() string +} + func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) { sdkDep := decodeSdkDep(ctx, sdkContext(r)) if sdkDep.hasFrameworkLibs() { @@ -1773,7 +1822,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC if !overridden { manifestPackageName = *r.overridableProperties.Package_name } - aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName) + aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, false)...) } if r.overridableProperties.Target_package_name != nil { aaptLinkFlags = append(aaptLinkFlags, @@ -1816,6 +1865,18 @@ func (r *RuntimeResourceOverlay) targetSdkVersion() sdkSpec { return r.sdkVersion() } +func (r *RuntimeResourceOverlay) Certificate() Certificate { + return r.certificate +} + +func (r *RuntimeResourceOverlay) OutputFile() android.Path { + return r.outputFile +} + +func (r *RuntimeResourceOverlay) Theme() string { + return String(r.properties.Theme) +} + // runtime_resource_overlay generates a resource-only apk file that can overlay application and // system resources at run time. func RuntimeResourceOverlayFactory() android.Module { @@ -1860,13 +1921,13 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs // creating a cyclic dependency: // e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res. if hasFrameworkLibs { - // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs - // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each - // library to dexpreopt. + // Dexpreopt needs paths to the dex jars of these libraries in order to construct + // class loader context for dex2oat. Add them as a dependency with a special tag. ctx.AddVariationDependencies(nil, usesLibTag, "org.apache.http.legacy", "android.hidl.base-V1.0-java", "android.hidl.manager-V1.0-java") + ctx.AddVariationDependencies(nil, usesLibTag, optionalUsesLibs...) } } } @@ -1878,24 +1939,36 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s return optionalUsesLibs } -// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars. -func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path { - usesLibPaths := make(map[string]android.Path) +// usesLibraryPaths returns a map of module names of shared library dependencies to the paths +// to their dex jars on host and on device. +func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths { + usesLibPaths := make(dexpreopt.LibraryPaths) if !ctx.Config().UnbundledBuild() { ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) { + dep := ctx.OtherModuleName(m) if lib, ok := m.(Dependency); ok { - if dexJar := lib.DexJar(); dexJar != nil { - usesLibPaths[ctx.OtherModuleName(m)] = dexJar + buildPath := lib.DexJarBuildPath() + if buildPath == nil { + ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must"+ + " produce a dex jar, does it have installable: true?", dep) + return + } + + var devicePath string + installPath := lib.DexJarInstallPath() + if installPath == nil { + devicePath = filepath.Join("/system/framework", dep+".jar") } else { - ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?", - ctx.OtherModuleName(m)) + devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath)) } + + usesLibPaths[dep] = &dexpreopt.LibraryPath{buildPath, devicePath} } else if ctx.Config().AllowMissingDependencies() { - ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)}) + ctx.AddMissingDependencies([]string{dep}) } else { - ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", - ctx.OtherModuleName(m)) + ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be "+ + "a java library", dep) } }) } diff --git a/java/app_test.go b/java/app_test.go index 8ef315206..6b83cd2e1 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -478,6 +478,24 @@ func TestUpdatableApps(t *testing.T) { } } +func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) { + testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", + static_libs: ["bar"], + } + + java_library { + name: "bar", + sdk_version: "current", + } + `) +} + func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` android_app { @@ -1743,52 +1761,125 @@ func TestOverrideAndroidApp(t *testing.T) { base: "foo", package_name: "org.dandroid.bp", } + + override_android_app { + name: "baz_no_rename_resources", + base: "foo", + package_name: "org.dandroid.bp", + rename_resources_package: false, + } + + android_app { + name: "foo_no_rename_resources", + srcs: ["a.java"], + certificate: "expiredkey", + overrides: ["qux"], + rename_resources_package: false, + sdk_version: "current", + } + + override_android_app { + name: "baz_base_no_rename_resources", + base: "foo_no_rename_resources", + package_name: "org.dandroid.bp", + } + + override_android_app { + name: "baz_override_base_rename_resources", + base: "foo_no_rename_resources", + package_name: "org.dandroid.bp", + rename_resources_package: true, + } `) expectedVariants := []struct { - moduleName string - variantName string - apkName string - apkPath string - certFlag string - lineageFlag string - overrides []string - aaptFlag string - logging_parent string + name string + moduleName string + variantName string + apkName string + apkPath string + certFlag string + lineageFlag string + overrides []string + packageFlag string + renameResources bool + logging_parent string }{ { - moduleName: "foo", - variantName: "android_common", - apkPath: "/target/product/test_device/system/app/foo/foo.apk", - certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", - lineageFlag: "", - overrides: []string{"qux"}, - aaptFlag: "", - logging_parent: "", - }, - { - moduleName: "bar", - variantName: "android_common_bar", - apkPath: "/target/product/test_device/system/app/bar/bar.apk", - certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", - lineageFlag: "--lineage lineage.bin", - overrides: []string{"qux", "foo"}, - aaptFlag: "", - logging_parent: "bah", - }, - { - moduleName: "baz", - variantName: "android_common_baz", - apkPath: "/target/product/test_device/system/app/baz/baz.apk", - 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: "", + name: "foo", + moduleName: "foo", + variantName: "android_common", + apkPath: "/target/product/test_device/system/app/foo/foo.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux"}, + packageFlag: "", + renameResources: false, + logging_parent: "", + }, + { + name: "foo", + moduleName: "bar", + variantName: "android_common_bar", + apkPath: "/target/product/test_device/system/app/bar/bar.apk", + certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + lineageFlag: "--lineage lineage.bin", + overrides: []string{"qux", "foo"}, + packageFlag: "", + renameResources: false, + logging_parent: "bah", + }, + { + name: "foo", + moduleName: "baz", + variantName: "android_common_baz", + apkPath: "/target/product/test_device/system/app/baz/baz.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo"}, + packageFlag: "org.dandroid.bp", + renameResources: true, + logging_parent: "", + }, + { + name: "foo", + moduleName: "baz_no_rename_resources", + variantName: "android_common_baz_no_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo"}, + packageFlag: "org.dandroid.bp", + renameResources: false, + logging_parent: "", + }, + { + name: "foo_no_rename_resources", + moduleName: "baz_base_no_rename_resources", + variantName: "android_common_baz_base_no_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo_no_rename_resources"}, + packageFlag: "org.dandroid.bp", + renameResources: false, + logging_parent: "", + }, + { + name: "foo_no_rename_resources", + moduleName: "baz_override_base_rename_resources", + variantName: "android_common_baz_override_base_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo_no_rename_resources"}, + packageFlag: "org.dandroid.bp", + renameResources: true, + logging_parent: "", }, } for _, expected := range expectedVariants { - variant := ctx.ModuleForTests("foo", expected.variantName) + variant := ctx.ModuleForTests(expected.name, expected.variantName) // Check the final apk name outputs := variant.AllOutputs() @@ -1834,9 +1925,12 @@ func TestOverrideAndroidApp(t *testing.T) { // Check the package renaming flag, if exists. res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] - if !strings.Contains(aapt2Flags, expected.aaptFlag) { - t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags) + checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + expectedPackage := expected.packageFlag + if !expected.renameResources { + expectedPackage = "" } + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expectedPackage) } } @@ -1973,6 +2067,7 @@ func TestOverrideAndroidTest(t *testing.T) { res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expected.packageFlag) checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag) } } @@ -2634,13 +2729,13 @@ func TestUsesLibraries(t *testing.T) { // Test that only present libraries are preopted cmd = app.Rule("dexpreopt").RuleParams.Command - if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) { + if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) { t.Errorf("wanted %q in %q", w, cmd) } cmd = prebuilt.Rule("dexpreopt").RuleParams.Command - if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) { + if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) { t.Errorf("wanted %q in %q", w, cmd) } } @@ -3190,6 +3285,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "") checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag) } } diff --git a/java/config/config.go b/java/config/config.go index 95add017d..54a709c5e 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -28,11 +28,11 @@ import ( var ( pctx = android.NewPackageContext("android/soong/java/config") - DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"} - DefaultSystemModules = "core-platform-api-stubs-system-modules" - DefaultLibraries = []string{"ext", "framework"} - DefaultLambdaStubsLibrary = "core-lambda-stubs" - SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar" + LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"} + LegacyCorePlatformSystemModules = "legacy-core-platform-api-stubs-system-modules" + FrameworkLibraries = []string{"ext", "framework"} + DefaultLambdaStubsLibrary = "core-lambda-stubs" + SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar" DefaultMakeJacocoExcludeFilter = []string{"org.junit.*", "org.jacoco.*", "org.mockito.*"} DefaultJacocoExcludeFilter = []string{"org.junit.**", "org.jacoco.**", "org.mockito.**"} @@ -112,7 +112,7 @@ func init() { pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar") pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime") - pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh") + pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file.py") pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh") pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh") diff --git a/java/config/makevars.go b/java/config/makevars.go index b355fad87..708a72aa4 100644 --- a/java/config/makevars.go +++ b/java/config/makevars.go @@ -25,9 +25,11 @@ func init() { } func makeVarsProvider(ctx android.MakeVarsContext) { - ctx.Strict("TARGET_DEFAULT_JAVA_LIBRARIES", strings.Join(DefaultLibraries, " ")) - ctx.Strict("TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES", strings.Join(DefaultBootclasspathLibraries, " ")) - ctx.Strict("DEFAULT_SYSTEM_MODULES", DefaultSystemModules) + ctx.Strict("FRAMEWORK_LIBRARIES", strings.Join(FrameworkLibraries, " ")) + + // These are used by make when LOCAL_PRIVATE_PLATFORM_APIS is set (equivalent to platform_apis in blueprint): + ctx.Strict("LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES", strings.Join(LegacyCorePlatformBootclasspathLibraries, " ")) + ctx.Strict("LEGACY_CORE_PLATFORM_SYSTEM_MODULES", LegacyCorePlatformSystemModules) ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}") ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}") diff --git a/java/device_host_converter.go b/java/device_host_converter.go index 11e68eb6c..9191a8321 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -150,7 +150,11 @@ func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths { return d.implementationAndResourceJars } -func (d *DeviceHostConverter) DexJar() android.Path { +func (d *DeviceHostConverter) DexJarBuildPath() android.Path { + return nil +} + +func (d *DeviceHostConverter) DexJarInstallPath() android.Path { return nil } diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 28a2c8ae6..f1b717874 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -37,7 +37,7 @@ type dexpreopter struct { usesLibs []string optionalUsesLibs []string enforceUsesLibs bool - libraryPaths map[string]android.Path + libraryPaths dexpreopt.LibraryPaths builtInstalled string } @@ -77,10 +77,6 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { return true } - if ctx.Config().UnbundledBuild() { - return true - } - if d.isTest { return true } @@ -131,7 +127,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo global := dexpreopt.GetGlobalConfig(ctx) bootImage := defaultBootImageConfig(ctx) dexFiles := bootImage.dexPathsDeps.Paths() - dexLocations := bootImage.dexLocationsDeps + // The dex locations for all Android variants are identical. + dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps if global.UseArtImage { bootImage = artBootImageConfig(ctx) } @@ -159,6 +156,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo images = append(images, variant.images) imagesDeps = append(imagesDeps, variant.imagesDeps) } + // The image locations for all Android variants are identical. + imageLocations := bootImage.getAnyAndroidVariant().imageLocations() dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath) @@ -174,7 +173,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo profileBootListing = android.ExistentPathForSource(ctx, ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot") profileIsTextListing = true - } else { + } else if global.ProfileDir != "" { profileClassListing = android.ExistentPathForSource(ctx, global.ProfileDir, ctx.ModuleName()+".prof") } @@ -194,15 +193,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo ProfileIsTextListing: profileIsTextListing, ProfileBootListing: profileBootListing, - EnforceUsesLibraries: d.enforceUsesLibs, - PresentOptionalUsesLibraries: d.optionalUsesLibs, - UsesLibraries: d.usesLibs, - LibraryPaths: d.libraryPaths, + EnforceUsesLibraries: d.enforceUsesLibs, + OptionalUsesLibraries: d.optionalUsesLibs, + UsesLibraries: d.usesLibs, + LibraryPaths: d.libraryPaths, Archs: archs, DexPreoptImages: images, DexPreoptImagesDeps: imagesDeps, - DexPreoptImageLocations: bootImage.imageLocations, + DexPreoptImageLocations: imageLocations, PreoptBootClassPathDexFiles: dexFiles, PreoptBootClassPathDexLocations: dexLocations, diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 2f0cbdb8c..41205598e 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -29,29 +29,10 @@ func init() { RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext) } -// The image "location" is a symbolic path that with multiarchitecture -// support doesn't really exist on the device. Typically it is -// /system/framework/boot.art and should be the same for all supported -// architectures on the device. The concrete architecture specific -// content actually ends up in a "filename" that contains an -// architecture specific directory name such as arm, arm64, mips, -// mips64, x86, x86_64. -// -// Here are some example values for an x86_64 / x86 configuration: -// -// bootImages["x86_64"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art" -// dexpreopt.PathToLocation(bootImages["x86_64"], "x86_64") = "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art" -// -// bootImages["x86"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86/boot.art" -// dexpreopt.PathToLocation(bootImages["x86"])= "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art" -// -// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools -// will then reconstruct the real path, so the rules must have a dependency on the real path. - // Target-independent description of pre-compiled boot image. type bootImageConfig struct { - // Whether this image is an extension. - extension bool + // If this image is an extension, the image that it extends. + extends *bootImageConfig // Image name (used in directory names and ninja rule names). name string @@ -71,17 +52,10 @@ type bootImageConfig struct { // The names of jars that constitute this image. modules []string - // The "locations" of jars. - dexLocations []string // for this image - dexLocationsDeps []string // for the dependency images and in this image - // File paths to jars. dexPaths android.WritablePaths // for this image dexPathsDeps android.WritablePaths // for the dependency images and in this image - // The "locations" of the dependency images and in this image. - imageLocations []string - // File path to a zip archive with all image files (or nil, if not needed). zip android.WritablePath @@ -99,6 +73,10 @@ type bootImageVariant struct { // Target for which the image is generated. target android.Target + // The "locations" of jars. + dexLocations []string // for this image + dexLocationsDeps []string // for the dependency images and in this image + // Paths to image files. images android.OutputPath // first image file imagesDeps android.OutputPaths // all files @@ -121,21 +99,31 @@ func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant return nil } -func (image bootImageConfig) moduleName(idx int) string { +// Return any (the first) variant which is for the device (as opposed to for the host) +func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant { + for _, variant := range image.variants { + if variant.target.Os == android.Android { + return variant + } + } + return nil +} + +func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string { // Dexpreopt on the boot class path produces multiple files. The first dex file // is converted into 'name'.art (to match the legacy assumption that 'name'.art // exists), and the rest are converted to 'name'-<jar>.art. - m := image.modules[idx] + _, m := android.SplitApexJarPair(ctx, image.modules[idx]) name := image.stem - if idx != 0 || image.extension { + if idx != 0 || image.extends != nil { name += "-" + stemOf(m) } return name } -func (image bootImageConfig) firstModuleNameOrStem() string { +func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string { if len(image.modules) > 0 { - return image.moduleName(0) + return image.moduleName(ctx, 0) } else { return image.stem } @@ -144,7 +132,7 @@ func (image bootImageConfig) firstModuleNameOrStem() string { func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths { ret := make(android.OutputPaths, 0, len(image.modules)*len(exts)) for i := range image.modules { - name := image.moduleName(i) + name := image.moduleName(ctx, i) for _, ext := range exts { ret = append(ret, dir.Join(ctx, name+ext)) } @@ -152,6 +140,24 @@ func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.Ou return ret } +// The image "location" is a symbolic path that, with multiarchitecture support, doesn't really +// exist on the device. Typically it is /apex/com.android.art/javalib/boot.art and should be the +// same for all supported architectures on the device. The concrete architecture specific files +// actually end up in architecture-specific sub-directory such as arm, arm64, x86, or x86_64. +// +// For example a physical file +// "/apex/com.android.art/javalib/x86/boot.art" has "image location" +// "/apex/com.android.art/javalib/boot.art" (which is not an actual file). +// +// The location is passed as an argument to the ART tools like dex2oat instead of the real path. +// ART tools will then reconstruct the architecture-specific real path. +func (image *bootImageVariant) imageLocations() (imageLocations []string) { + if image.extends != nil { + imageLocations = image.extends.getVariant(image.target).imageLocations() + } + return append(imageLocations, dexpreopt.PathToLocation(image.images, image.target.Arch.ArchType)) +} + func concat(lists ...[]string) []string { var size int for _, l := range lists { @@ -173,20 +179,7 @@ func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { } func skipDexpreoptBootJars(ctx android.PathContext) bool { - if dexpreopt.GetGlobalConfig(ctx).DisablePreopt { - return true - } - - if ctx.Config().UnbundledBuild() { - return true - } - - if len(ctx.Config().Targets[android.Android]) == 0 { - // Host-only build - return true - } - - return false + return dexpreopt.GetGlobalConfig(ctx).DisablePreopt } type dexpreoptBootJars struct { @@ -204,7 +197,10 @@ func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]and // Include dexpreopt files for the primary boot image. files := map[android.ArchType]android.OutputPaths{} for _, variant := range artBootImageConfig(ctx).variants { - files[variant.target.Arch.ArchType] = variant.imagesDeps + // We also generate boot images for host (for testing), but we don't need those in the apex. + if variant.target.Os == android.Android { + files[variant.target.Arch.ArchType] = variant.imagesDeps + } } return files } @@ -251,13 +247,13 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul return -1, nil } - jar, hasJar := module.(interface{ DexJar() android.Path }) + jar, hasJar := module.(interface{ DexJarBuildPath() android.Path }) if !hasJar { return -1, nil } name := ctx.ModuleName(module) - index := android.IndexList(name, image.modules) + index := android.IndexList(name, android.GetJarsFromApexJarPairs(ctx, image.modules)) if index == -1 { return -1, nil } @@ -292,7 +288,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul panic("unknown boot image: " + image.name) } - return index, jar.DexJar() + return index, jar.DexJarBuildPath() } // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image. @@ -310,13 +306,13 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI // Ensure all modules were converted to paths for i := range bootDexJars { if bootDexJars[i] == nil { + _, m := android.SplitApexJarPair(ctx, image.modules[i]) if ctx.Config().AllowMissingDependencies() { - missingDeps = append(missingDeps, image.modules[i]) + missingDeps = append(missingDeps, m) bootDexJars[i] = android.PathForOutput(ctx, "missing") } else { ctx.Errorf("failed to find a dex jar path for module '%s'"+ - ", note that some jars may be filtered out by module constraints", - image.modules[i]) + ", note that some jars may be filtered out by module constraints", m) } } } @@ -336,10 +332,12 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI bootFrameworkProfileRule(ctx, image, missingDeps) updatableBcpPackagesRule(ctx, image, missingDeps) - var allFiles android.Paths + var zipFiles android.Paths for _, variant := range image.variants { files := buildBootImageVariant(ctx, variant, profile, missingDeps) - allFiles = append(allFiles, files.Paths()...) + if variant.target.Os == android.Android { + zipFiles = append(zipFiles, files.Paths()...) + } } if image.zip != nil { @@ -347,8 +345,8 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI rule.Command(). BuiltTool(ctx, "soong_zip"). FlagWithOutput("-o ", image.zip). - FlagWithArg("-C ", image.dir.String()). - FlagWithInputList("-f ", allFiles, " -f ") + FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()). + FlagWithInputList("-f ", zipFiles, " -f ") rule.Build(pctx, ctx, "zip_"+image.name, "zip "+image.name+" image") } @@ -363,9 +361,10 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant global := dexpreopt.GetGlobalConfig(ctx) arch := image.target.Arch.ArchType - symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String()) + os := image.target.Os.String() // We need to distinguish host-x86 and device-x86. + symbolsDir := image.symbolsDir.Join(ctx, os, image.installSubdir, arch.String()) symbolsFile := symbolsDir.Join(ctx, image.stem+".oat") - outputDir := image.dir.Join(ctx, image.installSubdir, arch.String()) + outputDir := image.dir.Join(ctx, os, image.installSubdir, arch.String()) outputPath := outputDir.Join(ctx, image.stem+".oat") oatLocation := dexpreopt.PathToLocation(outputPath, arch) imagePath := outputPath.ReplaceExtension(ctx, "art") @@ -411,7 +410,7 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path()) } - if image.extension { + if image.extends != nil { artImage := image.primaryImages cmd. Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). @@ -433,13 +432,18 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant FlagWithArg("--oat-location=", oatLocation). FlagWithArg("--image=", imagePath.String()). FlagWithArg("--instruction-set=", arch.String()). - FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]). - FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]). FlagWithArg("--android-root=", global.EmptyDirectory). FlagWithArg("--no-inline-from=", "core-oj.jar"). Flag("--force-determinism"). Flag("--abort-on-hard-verifier-error") + // Use the default variant/features for host builds. + // The map below contains only device CPU info (which might be x86 on some devices). + if image.target.Os == android.Android { + cmd.FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]) + cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]) + } + if global.BootFlags != "" { cmd.Flag(global.BootFlags) } @@ -451,7 +455,6 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage)) installDir := filepath.Join("/", image.installSubdir, arch.String()) - vdexInstallDir := filepath.Join("/", image.installSubdir) var vdexInstalls android.RuleBuilderInstalls var unstrippedInstalls android.RuleBuilderInstalls @@ -470,11 +473,10 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant cmd.ImplicitOutput(vdex) zipFiles = append(zipFiles, vdex) - // The vdex files are identical between architectures, install them to a shared location. The Make rules will - // only use the install rules for one architecture, and will create symlinks into the architecture-specific - // directories. + // Note that the vdex files are identical between architectures. + // Make rules will create symlinks to share them between architectures. vdexInstalls = append(vdexInstalls, - android.RuleBuilderInstall{vdex, filepath.Join(vdexInstallDir, vdex.Base())}) + android.RuleBuilderInstall{vdex, filepath.Join(installDir, vdex.Base())}) } for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") { @@ -485,7 +487,7 @@ func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())}) } - rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String()) + rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String()) // save output and installed files for makevars image.installs = rule.Installs() @@ -535,7 +537,7 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig, Tool(globalSoong.Profman). FlagWithInput("--create-profile-from=", bootImageProfile). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.dexLocationsDeps). + FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) rule.Install(profile, "/system/etc/boot-image.prof") @@ -586,7 +588,7 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConf Flag("--generate-boot-profile"). FlagWithInput("--create-profile-from=", bootFrameworkProfile). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.dexLocationsDeps). + FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) rule.Install(profile, "/system/etc/boot-image.bprof") @@ -606,7 +608,7 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} { global := dexpreopt.GetGlobalConfig(ctx) - updatableModules := dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars) + updatableModules := android.GetJarsFromApexJarPairs(ctx, global.UpdatableBootJars) // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string @@ -658,27 +660,32 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) { var allPhonies android.Paths for _, image := range image.variants { arch := image.target.Arch.ArchType + suffix := arch.String() + // Host and target might both use x86 arch. We need to ensure the names are unique. + if image.target.Os.Class == android.Host { + suffix = "host-" + suffix + } // Create a rule to call oatdump. - output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt") + output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt") rule := android.NewRuleBuilder() rule.Command(). // TODO: for now, use the debug version for better error reporting BuiltTool(ctx, "oatdumpd"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()). + FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()). FlagWithOutput("--output=", output). FlagWithArg("--instruction-set=", arch.String()) - rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String()) + rule.Build(pctx, ctx, "dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) // Create a phony rule that depends on the output file and prints the path. - phony := android.PathForPhony(ctx, "dump-oat-boot-"+arch.String()) + phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix) rule = android.NewRuleBuilder() rule.Command(). Implicit(output). ImplicitOutput(phony). Text("echo").FlagWithArg("Output in ", output.String()) - rule.Build(pctx, ctx, "phony-dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String()) + rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) allPhonies = append(allPhonies, phony) } @@ -716,21 +723,25 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { if image != nil { ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " ")) - ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " ")) + ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " ")) var imageNames []string for _, current := range append(d.otherImages, image) { imageNames = append(imageNames, current.name) - for _, current := range current.variants { - sfx := current.name + "_" + current.target.Arch.ArchType.String() - ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String()) - ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String()) - ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " ")) - ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs.String()) - ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls.String()) + for _, variant := range current.variants { + suffix := "" + if variant.target.Os.Class == android.Host { + suffix = "_host" + } + sfx := variant.name + suffix + "_" + variant.target.Arch.ArchType.String() + ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, variant.vdexInstalls.String()) + ctx.Strict("DEXPREOPT_IMAGE_"+sfx, variant.images.String()) + ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(variant.imagesDeps.Strings(), " ")) + ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String()) + ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String()) } - - ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":")) + imageLocations := current.getAnyAndroidVariant().imageLocations() + ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":")) ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String()) } ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " ")) diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index e7b3c3ba9..9670c7f4b 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -24,7 +24,7 @@ import ( "android/soong/dexpreopt" ) -func TestDexpreoptBootJars(t *testing.T) { +func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOutputs []string) { bp := ` java_sdk_library { name: "foo", @@ -48,67 +48,88 @@ func TestDexpreoptBootJars(t *testing.T) { pathCtx := android.PathContextForTesting(config) dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx) - dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"} + dexpreoptConfig.BootJars = []string{"platform:foo", "platform:bar", "platform:baz"} dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig) ctx := testContext() - RegisterDexpreoptBootJarsComponents(ctx) - run(t, ctx, config) dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars") - - bootArt := dexpreoptBootJars.Output("boot-foo.art") - - expectedInputs := []string{ - "dex_artjars/apex/com.android.art/javalib/arm64/boot.art", - "dex_bootjars_input/foo.jar", - "dex_bootjars_input/bar.jar", - "dex_bootjars_input/baz.jar", - } + rule := dexpreoptBootJars.Output(ruleFile) for i := range expectedInputs { expectedInputs[i] = filepath.Join(buildDir, "test_device", expectedInputs[i]) } - inputs := bootArt.Implicits.Strings() + for i := range expectedOutputs { + expectedOutputs[i] = filepath.Join(buildDir, "test_device", expectedOutputs[i]) + } + + inputs := rule.Implicits.Strings() sort.Strings(inputs) sort.Strings(expectedInputs) + outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Strings() + sort.Strings(outputs) + sort.Strings(expectedOutputs) + if !reflect.DeepEqual(inputs, expectedInputs) { t.Errorf("want inputs %q\n got inputs %q", expectedInputs, inputs) } - expectedOutputs := []string{ - "dex_bootjars/system/framework/arm64/boot.invocation", - - "dex_bootjars/system/framework/arm64/boot-foo.art", - "dex_bootjars/system/framework/arm64/boot-bar.art", - "dex_bootjars/system/framework/arm64/boot-baz.art", - - "dex_bootjars/system/framework/arm64/boot-foo.oat", - "dex_bootjars/system/framework/arm64/boot-bar.oat", - "dex_bootjars/system/framework/arm64/boot-baz.oat", + if !reflect.DeepEqual(outputs, expectedOutputs) { + t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs) + } +} - "dex_bootjars/system/framework/arm64/boot-foo.vdex", - "dex_bootjars/system/framework/arm64/boot-bar.vdex", - "dex_bootjars/system/framework/arm64/boot-baz.vdex", +func TestDexpreoptBootJars(t *testing.T) { + ruleFile := "boot-foo.art" - "dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat", - "dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat", - "dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat", + expectedInputs := []string{ + "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art", + "dex_bootjars_input/foo.jar", + "dex_bootjars_input/bar.jar", + "dex_bootjars_input/baz.jar", } - for i := range expectedOutputs { - expectedOutputs[i] = filepath.Join(buildDir, "test_device", expectedOutputs[i]) + expectedOutputs := []string{ + "dex_bootjars/android/system/framework/arm64/boot.invocation", + "dex_bootjars/android/system/framework/arm64/boot-foo.art", + "dex_bootjars/android/system/framework/arm64/boot-bar.art", + "dex_bootjars/android/system/framework/arm64/boot-baz.art", + "dex_bootjars/android/system/framework/arm64/boot-foo.oat", + "dex_bootjars/android/system/framework/arm64/boot-bar.oat", + "dex_bootjars/android/system/framework/arm64/boot-baz.oat", + "dex_bootjars/android/system/framework/arm64/boot-foo.vdex", + "dex_bootjars/android/system/framework/arm64/boot-bar.vdex", + "dex_bootjars/android/system/framework/arm64/boot-baz.vdex", + "dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat", + "dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat", + "dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat", } - outputs := append(android.WritablePaths{bootArt.Output}, bootArt.ImplicitOutputs...).Strings() - sort.Strings(outputs) - sort.Strings(expectedOutputs) + testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs) +} - if !reflect.DeepEqual(outputs, expectedOutputs) { - t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs) +// Changes to the boot.zip structure may break the ART APK scanner. +func TestDexpreoptBootZip(t *testing.T) { + ruleFile := "boot.zip" + + ctx := android.PathContextForTesting(testConfig(nil, "", nil)) + expectedInputs := []string{} + for _, target := range ctx.Config().Targets[android.Android] { + for _, ext := range []string{".art", ".oat", ".vdex"} { + for _, jar := range []string{"foo", "bar", "baz"} { + expectedInputs = append(expectedInputs, + filepath.Join("dex_bootjars", target.Os.String(), "system/framework", target.Arch.ArchType.String(), "boot-"+jar+ext)) + } + } } + + expectedOutputs := []string{ + "dex_bootjars/boot.zip", + } + + testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs) } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index f8356d188..f13d9f210 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -39,7 +39,7 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string { // 2) The jars that are from an updatable apex. for _, m := range global.UpdatableSystemServerJars { systemServerClasspathLocations = append(systemServerClasspathLocations, - dexpreopt.GetJarLocationFromApexJarPair(m)) + dexpreopt.GetJarLocationFromApexJarPair(ctx, m)) } if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) { panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d", @@ -61,6 +61,10 @@ func dexpreoptTargets(ctx android.PathContext) []android.Target { targets = append(targets, target) } } + // We may also need the images on host in order to run host-based tests. + for _, target := range ctx.Config().Targets[android.BuildOs] { + targets = append(targets, target) + } return targets } @@ -75,6 +79,29 @@ func stemOf(moduleName string) string { return moduleName } +func getDexLocation(ctx android.PathContext, target android.Target, module string) string { + apex, jar := android.SplitApexJarPair(ctx, module) + + name := stemOf(jar) + ".jar" + + var subdir string + if apex == "platform" { + // Special apex name "platform" denotes jars do not come from an apex, but are part + // of the platform. Such jars are installed on the /system partition on device. + subdir = "system/framework" + } else if apex == "system_ext" { + subdir = "system_ext/framework" + } else { + subdir = filepath.Join("apex", apex, "javalib") + } + + if target.Os.Class == android.Host { + return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name) + } else { + return filepath.Join("/", subdir, name) + } +} + var ( bootImageConfigKey = android.NewOnceKey("bootImageConfig") artBootImageName = "art" @@ -92,44 +119,30 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { artModules := global.ArtApexJars // With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco. if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { - artModules = append(artModules, "jacocoagent") + artModules = append(artModules, "com.android.art:jacocoagent") } - frameworkModules := android.RemoveListFromList(global.BootJars, - concat(artModules, dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars))) + frameworkModules := android.RemoveListFromList(global.BootJars, artModules) artSubdir := "apex/com.android.art/javalib" frameworkSubdir := "system/framework" - var artLocations, frameworkLocations []string - for _, m := range artModules { - artLocations = append(artLocations, filepath.Join("/"+artSubdir, stemOf(m)+".jar")) - } - for _, m := range frameworkModules { - frameworkLocations = append(frameworkLocations, filepath.Join("/"+frameworkSubdir, stemOf(m)+".jar")) - } - // ART config for the primary boot image in the ART apex. // It includes the Core Libraries. artCfg := bootImageConfig{ - extension: false, - name: artBootImageName, - stem: "boot", - installSubdir: artSubdir, - modules: artModules, - dexLocations: artLocations, - dexLocationsDeps: artLocations, + name: artBootImageName, + stem: "boot", + installSubdir: artSubdir, + modules: artModules, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. frameworkCfg := bootImageConfig{ - extension: true, - name: frameworkBootImageName, - stem: "boot", - installSubdir: frameworkSubdir, - modules: frameworkModules, - dexLocations: frameworkLocations, - dexLocationsDeps: append(artLocations, frameworkLocations...), + extends: &artCfg, + name: frameworkBootImageName, + stem: "boot", + installSubdir: frameworkSubdir, + modules: frameworkModules, } configs := map[string]*bootImageConfig{ @@ -143,9 +156,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped") // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension - imageName := c.firstModuleNameOrStem() + ".art" - - c.imageLocations = []string{c.dir.Join(ctx, c.installSubdir, imageName).String()} + imageName := c.firstModuleNameOrStem(ctx) + ".art" // The path to bootclasspath dex files needs to be known at module // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. @@ -153,20 +164,25 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { // TODO(b/143682396): use module dependencies instead inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") for _, m := range c.modules { - c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(m)+".jar")) + _, jar := android.SplitApexJarPair(ctx, m) + c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(jar)+".jar")) } c.dexPathsDeps = c.dexPaths // Create target-specific variants. for _, target := range targets { arch := target.Arch.ArchType - imageDir := c.dir.Join(ctx, c.installSubdir, arch.String()) + imageDir := c.dir.Join(ctx, target.Os.String(), c.installSubdir, arch.String()) variant := &bootImageVariant{ bootImageConfig: c, target: target, images: imageDir.Join(ctx, imageName), imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), } + for _, m := range c.modules { + variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, m)) + } + variant.dexLocationsDeps = variant.dexLocations c.variants = append(c.variants, variant) } @@ -177,8 +193,8 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) for i := range targets { frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images + frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) } - frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...) return configs }).(map[string]*bootImageConfig) @@ -199,10 +215,10 @@ func defaultBootclasspath(ctx android.PathContext) []string { updatableBootclasspath := make([]string, len(global.UpdatableBootJars)) for i, p := range global.UpdatableBootJars { - updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p) + updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(ctx, p) } - bootclasspath := append(copyOf(image.dexLocationsDeps), updatableBootclasspath...) + bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...) return bootclasspath }) } @@ -217,7 +233,7 @@ func init() { func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) - ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocationsDeps, ":")) + ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":")) ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":")) diff --git a/java/droiddoc.go b/java/droiddoc.go index 230b1f026..e3aaf6566 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -112,13 +112,20 @@ type JavadocProperties struct { // local files that are used within user customized droiddoc options. Arg_files []string `android:"path"` - // user customized droiddoc args. + // user customized droiddoc args. Deprecated, use flags instead. // Available variables for substitution: // // $(location <label>): the path to the arg_files with name <label> // $$: a literal $ Args *string + // user customized droiddoc args. Not compatible with property args. + // Available variables for substitution: + // + // $(location <label>): the path to the arg_files with name <label> + // $$: a literal $ + Flags []string + // names of the output files used in args that will be generated Out []string @@ -382,7 +389,7 @@ type Javadoc struct { argFiles android.Paths implicits android.Paths - args string + args []string docZip android.WritablePath stubsSrcJar android.WritablePath @@ -440,16 +447,11 @@ func (j *Javadoc) targetSdkVersion() sdkSpec { func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) { if ctx.Device() { sdkDep := decodeSdkDep(ctx, sdkContext(j)) - if sdkDep.useDefaultLibs { - ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) - ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules) - if sdkDep.hasFrameworkLibs() { - ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...) - } - } else if sdkDep.useModule { + if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) + ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...) } } @@ -624,8 +626,8 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { } srcFiles = filterHtml(srcFiles) - flags := j.collectAidlFlags(ctx, deps) - srcFiles = j.genSources(ctx, srcFiles, flags) + aidlFlags := j.collectAidlFlags(ctx, deps) + srcFiles = j.genSources(ctx, srcFiles, aidlFlags) // srcs may depend on some genrule output. j.srcJars = srcFiles.FilterByExt(".srcjar") @@ -654,24 +656,38 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { } } - var err error - j.args, err = android.Expand(String(j.properties.Args), func(name string) (string, error) { - if strings.HasPrefix(name, "location ") { - label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) - if paths, ok := argFilesMap[label]; ok { - return paths, nil - } else { - return "", fmt.Errorf("unknown location label %q, expecting one of %q", - label, strings.Join(argFileLabels, ", ")) + var argsPropertyName string + flags := make([]string, 0) + if j.properties.Args != nil && j.properties.Flags != nil { + ctx.PropertyErrorf("args", "flags is set. Cannot set args") + } else if args := proptools.String(j.properties.Args); args != "" { + flags = append(flags, args) + argsPropertyName = "args" + } else { + flags = append(flags, j.properties.Flags...) + argsPropertyName = "flags" + } + + for _, flag := range flags { + args, err := android.Expand(flag, func(name string) (string, error) { + if strings.HasPrefix(name, "location ") { + label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) + if paths, ok := argFilesMap[label]; ok { + return paths, nil + } else { + return "", fmt.Errorf("unknown location label %q, expecting one of %q", + label, strings.Join(argFileLabels, ", ")) + } + } else if name == "genDir" { + return android.PathForModuleGen(ctx).String(), nil } - } else if name == "genDir" { - return android.PathForModuleGen(ctx).String(), nil - } - return "", fmt.Errorf("unknown variable '$(%s)'", name) - }) + return "", fmt.Errorf("unknown variable '$(%s)'", name) + }) - if err != nil { - ctx.PropertyErrorf("args", "%s", err.Error()) + if err != nil { + ctx.PropertyErrorf(argsPropertyName, "%s", err.Error()) + } + j.args = append(j.args, args) } return deps @@ -1015,7 +1031,7 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { d.stubsFlags(ctx, cmd, stubsDir) - cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles) + cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles) if d.properties.Compat_config != nil { compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config)) @@ -1332,7 +1348,7 @@ func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.Ru cmd.Flag("--include-annotations") validatingNullability := - strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") || + android.InList("--validate-nullability-from-merged-stubs", d.Javadoc.args) || String(d.properties.Validate_nullability_from_list) != "" migratingNullability := String(d.properties.Previous_api) != "" @@ -1452,7 +1468,6 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi labels["shallow"] = "true" } inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()} - inputs = append(inputs, sourcepaths.Strings()...) if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" { inputs = append(inputs, strings.Split(v, ",")...) } @@ -1545,14 +1560,14 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { d.apiLevelsAnnotationsFlags(ctx, cmd) d.apiToXmlFlags(ctx, cmd) - if strings.Contains(d.Javadoc.args, "--generate-documentation") { + if android.InList("--generate-documentation", d.Javadoc.args) { // Currently Metalava have the ability to invoke Javadoc in a seperate process. // Pass "-nodocs" to suppress the Javadoc invocation when Metalava receives // "--generate-documentation" arg. This is not needed when Metalava removes this feature. - d.Javadoc.args = d.Javadoc.args + " -nodocs " + d.Javadoc.args = append(d.Javadoc.args, "-nodocs") } - cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles) + cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles) for _, o := range d.Javadoc.properties.Out { cmd.ImplicitOutput(android.PathForModuleGen(ctx, o)) } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 95dd0bb09..857894958 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -116,7 +116,7 @@ func stubFlagsRule(ctx android.SingletonContext) { // Core Platform API stubs corePlatformStubModules := []string{ - "core.platform.api.stubs", + "legacy.core.platform.api.stubs", } // Allow products to define their own stubs for custom product jars that apps can use. @@ -147,7 +147,7 @@ func stubFlagsRule(ctx android.SingletonContext) { name := ctx.ModuleName(module) for moduleList, pathList := range moduleListToPathList { if i := android.IndexList(name, *moduleList); i != -1 { - pathList[i] = j.DexJar() + pathList[i] = j.DexJarBuildPath() } } } diff --git a/java/java.go b/java/java.go index 0a764e636..ebff4e01b 100644 --- a/java/java.go +++ b/java/java.go @@ -44,7 +44,7 @@ func init() { PropertyName: "java_libs", }, func(j *Library) android.Path { - implementationJars := j.ImplementationJars() + implementationJars := j.ImplementationAndResourcesJars() if len(implementationJars) != 1 { panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) } @@ -140,10 +140,15 @@ func (j *Module) checkPlatformAPI(ctx android.ModuleContext) { // Findbugs type CompilerProperties struct { - // list of source files used to compile the Java module. May be .java, .logtags, .proto, + // list of source files used to compile the Java module. May be .java, .kt, .logtags, .proto, // or .aidl files. Srcs []string `android:"path,arch_variant"` + // list Kotlin of source files containing Kotlin code that should be treated as common code in + // a codebase that supports Kotlin multiplatform. See + // https://kotlinlang.org/docs/reference/multiplatform.html. May be only be .kt files. + Common_srcs []string `android:"path,arch_variant"` + // list of source files that should not be used to build the Java module. // This is most useful in the arch/multilib variants to remove non-common files Exclude_srcs []string `android:"path,arch_variant"` @@ -489,7 +494,10 @@ type Module struct { // list of the xref extraction files kytheFiles android.Paths - distFile android.Path + distFiles android.TaggedDistFiles + + // Collect the module directory for IDE info in java/jdeps.go. + modulePaths []string } func (j *Module) addHostProperties() { @@ -533,7 +541,8 @@ type Dependency interface { ApexDependency ImplementationJars() android.Paths ResourceJars() android.Paths - DexJar() android.Path + DexJarBuildPath() android.Path + DexJarInstallPath() android.Path AidlIncludeDirs() android.Paths ExportedSdkLibs() []string ExportedPlugins() (android.Paths, []string) @@ -597,7 +606,7 @@ func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool { } type sdkDep struct { - useModule, useFiles, useDefaultLibs, invalidVersion bool + useModule, useFiles, invalidVersion bool // The modules that will be added to the bootclasspath when targeting 1.8 or lower bootclasspath []string @@ -606,7 +615,11 @@ type sdkDep struct { // modules are to be used. systemModules string + // The modules that will be added to the classpath regardless of the Java language level targeted + classpath []string + // The modules that will be added ot the classpath when targeting 1.9 or higher + // (normally these will be on the bootclasspath when targeting 1.8 or lower) java9Classpath []string frameworkResModule string @@ -645,6 +658,21 @@ func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool { ctx.Config().UnbundledBuild()) } +func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { + // Force enable the instrumentation for java code that is built for APEXes ... + // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent + // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true. + isJacocoAgent := ctx.ModuleName() == "jacocoagent" + if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() { + if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) { + return true + } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { + return true + } + } + return false +} + func (j *Module) sdkVersion() sdkSpec { return sdkSpecFrom(String(j.deviceProperties.Sdk_version)) } @@ -686,18 +714,15 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { j.linter.deps(ctx) sdkDep := decodeSdkDep(ctx, sdkContext(j)) - if sdkDep.useDefaultLibs { - ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) - ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules) - if sdkDep.hasFrameworkLibs() { - ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...) - } - } else if sdkDep.useModule { + if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) + ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...) if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { - ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) - ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) + ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...) + } + if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() { + ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...) } } if sdkDep.systemModules != "" { @@ -875,8 +900,9 @@ type linkTypeContext interface { func (m *Module) getLinkType(name string) (ret linkType, stubs bool) { switch name { - case "core.current.stubs", "core.platform.api.stubs", "stub-annotations", - "private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs": + case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs", + "stub-annotations", "private-stub-annotations-jar", + "core-lambda-stubs", "core-generated-annotation-stubs": return javaCore, true case "android_stubs_current": return javaSdk, true @@ -1186,9 +1212,9 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB if flags.javaVersion.usesJavaModules() { javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...) } - if ctx.Config().MinimizeJavaDebugInfo() { - // Override the -g flag passed globally to remove local variable debug info to reduce - // disk and memory usage. + if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() { + // For non-host binaries, override the -g flag passed globally to remove + // local variable debug info to reduce disk and memory usage. javacFlags = append(javacFlags, "-g:source,lines") } javacFlags = append(javacFlags, "-Xlint:-dep-ann") @@ -1284,6 +1310,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags) } + kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil) + if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 { + ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files") + } + srcFiles = j.genSources(ctx, srcFiles, flags) srcJars := srcFiles.FilterByExt(".srcjar") @@ -1337,6 +1368,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Collect .kt files for AIDEGen j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...) + j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...) flags.classpath = append(flags.classpath, deps.kotlinStdlib...) flags.classpath = append(flags.classpath, deps.kotlinAnnotations...) @@ -1348,7 +1380,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Use kapt for annotation processing kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar") kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar") - kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, srcJars, flags) + kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags) srcJars = append(srcJars, kaptSrcJar) kotlinJars = append(kotlinJars, kaptResJar) // Disable annotation processing in javac, it's already been handled by kapt @@ -1357,7 +1389,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) - kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags) + kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags) if ctx.Failed() { return } @@ -1583,11 +1615,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.headerJarFile = j.implementationJarFile } - // Force enable the instrumentation for java code that is built for APEXes ... - // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent - // doesn't make sense) - isJacocoAgent := ctx.ModuleName() == "jacocoagent" - if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() { + if j.shouldInstrumentInApex(ctx) { j.properties.Instrument = true } @@ -1811,10 +1839,14 @@ func (j *Module) ImplementationJars() android.Paths { return android.Paths{j.implementationJarFile} } -func (j *Module) DexJar() android.Path { +func (j *Module) DexJarBuildPath() android.Path { return j.dexJarFile } +func (j *Module) DexJarInstallPath() android.Path { + return j.installFile +} + func (j *Module) ResourceJars() android.Paths { if j.resourceJar == nil { return nil @@ -1862,6 +1894,7 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { if j.expandJarjarRules != nil { dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) } + dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...) } func (j *Module) CompilerDeps() []string { @@ -1880,6 +1913,24 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } +func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + sdkSpec := j.minSdkVersion() + if !sdkSpec.specified() { + return fmt.Errorf("min_sdk_version is not specified") + } + if sdkSpec.kind == sdkCore { + return nil + } + ver, err := sdkSpec.effectiveVersion(ctx) + if err != nil { + return err + } + if int(ver) > sdkVersion { + return fmt.Errorf("newer SDK(%v)", ver) + } + return nil +} + func (j *Module) Stem() string { return proptools.StringDefault(j.deviceProperties.Stem, j.Name()) } @@ -1900,18 +1951,9 @@ func (j *Module) IsInstallable() bool { // Java libraries (.jar file) // -type LibraryProperties struct { - Dist struct { - // The tag of the output of this module that should be output. - Tag *string `android:"arch_variant"` - } `android:"arch_variant"` -} - type Library struct { Module - libraryProperties LibraryProperties - InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } @@ -1960,6 +2002,9 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex j.compile(ctx, nil) + // Collect the module directory for IDE info in java/jdeps.go. + j.modulePaths = append(j.modulePaths, ctx.ModuleDir()) + exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { var extraInstallDeps android.Paths @@ -1970,14 +2015,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.Stem()+".jar", j.outputFile, extraInstallDeps...) } - // Verify Dist.Tag is set to a supported output - if j.libraryProperties.Dist.Tag != nil { - distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag) - if err != nil { - ctx.PropertyErrorf("dist.tag", "%s", err.Error()) - } - j.distFile = distFiles[0] - } + j.distFiles = j.GenerateTaggedDistFiles(ctx) } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -2095,7 +2133,6 @@ func LibraryFactory() android.Module { module := &Library{} module.addHostAndDeviceProperties() - module.AddProperties(&module.libraryProperties) module.initModuleAndImport(&module.ModuleBase) @@ -2480,6 +2517,12 @@ type ImportProperties struct { // set the name of the output Stem *string + + Aidl struct { + // directories that should be added as include directories for any aidl sources of modules + // that depend on this module, as well as to aidl for this module. + Export_include_dirs []string + } } type Import struct { @@ -2496,6 +2539,7 @@ type Import struct { combinedClasspathFile android.Path exportedSdkLibs []string + exportAidlIncludeDirs android.Paths } func (j *Import) sdkVersion() sdkSpec { @@ -2579,6 +2623,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), jarName, outputFile) } + + j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs) } var _ Dependency = (*Import)(nil) @@ -2608,14 +2654,18 @@ func (j *Import) ImplementationAndResourcesJars() android.Paths { return android.Paths{j.combinedClasspathFile} } -func (j *Import) DexJar() android.Path { +func (j *Import) DexJarBuildPath() android.Path { return nil } -func (j *Import) AidlIncludeDirs() android.Paths { +func (j *Import) DexJarInstallPath() android.Path { return nil } +func (j *Import) AidlIncludeDirs() android.Paths { + return j.exportAidlIncludeDirs +} + func (j *Import) ExportedSdkLibs() []string { return j.exportedSdkLibs } @@ -2632,6 +2682,11 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } +func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + // Do not check for prebuilts against the min_sdk_version of enclosing APEX + return nil +} + // Add compile time check for interface implementation var _ android.IDEInfo = (*Import)(nil) var _ android.IDECustomizedModuleName = (*Import)(nil) @@ -2797,10 +2852,15 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } -func (j *DexImport) DexJar() android.Path { +func (j *DexImport) DexJarBuildPath() android.Path { return j.dexJarFile } +func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + // we don't check prebuilt modules for sdk_version + return nil +} + // dex_import imports a `.jar` file containing classes.dex files. // // A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed @@ -2873,6 +2933,7 @@ func DefaultsFactory() android.Module { &appProperties{}, &appTestProperties{}, &overridableAppProperties{}, + &testProperties{}, &ImportProperties{}, &AARImportProperties{}, &sdkLibraryProperties{}, diff --git a/java/java_test.go b/java/java_test.go index f0de52fb9..db3f18740 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -85,6 +85,7 @@ func testContext() *android.TestContext { RegisterStubsBuildComponents(ctx) RegisterSdkLibraryBuildComponents(ctx) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) + ctx.PreArchMutators(android.RegisterComponentsMutator) RegisterPrebuiltApisBuildComponents(ctx) @@ -466,7 +467,41 @@ func TestBinary(t *testing.T) { t.Errorf("expected binary wrapper implicits [%q], got %v", barJar, barWrapperDeps) } +} +func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { + bp := ` + java_library { + name: "target_library", + srcs: ["a.java"], + } + + java_binary_host { + name: "host_binary", + srcs: ["b.java"], + } + ` + config := testConfig(nil, bp, nil) + config.TestProductVariables.MinimizeJavaDebugInfo = proptools.BoolPtr(true) + + ctx, _ := testJavaWithConfig(t, config) + + // first, sanity check that the -g flag is added to target modules + targetLibrary := ctx.ModuleForTests("target_library", "android_common") + targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"] + if !strings.Contains(targetJavaFlags, "-g:source,lines") { + t.Errorf("target library javac flags %v should contain "+ + "-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags) + } + + // check that -g is not overridden for host modules + buildOS := android.BuildOs.String() + hostBinary := ctx.ModuleForTests("host_binary", buildOS+"_common") + hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"] + if strings.Contains(hostJavaFlags, "-g:source,lines") { + t.Errorf("java_binary_host javac flags %v should not have "+ + "-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags) + } } func TestPrebuilts(t *testing.T) { @@ -596,6 +631,89 @@ func TestJavaSdkLibraryImport(t *testing.T) { t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) } } + + CheckModuleDependencies(t, ctx, "sdklib", "android_common", []string{ + `prebuilt_sdklib.stubs`, + `prebuilt_sdklib.stubs.source.test`, + `prebuilt_sdklib.stubs.system`, + `prebuilt_sdklib.stubs.test`, + }) +} + +func TestJavaSdkLibraryImport_WithSource(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + } + + java_sdk_library_import { + name: "sdklib", + public: { + jars: ["a.jar"], + }, + } + `) + + CheckModuleDependencies(t, ctx, "sdklib", "android_common", []string{ + `dex2oatd`, + `prebuilt_sdklib`, + `sdklib.impl`, + `sdklib.stubs`, + `sdklib.stubs.source`, + `sdklib.xml`, + }) + + CheckModuleDependencies(t, ctx, "prebuilt_sdklib", "android_common", []string{ + `prebuilt_sdklib.stubs`, + `sdklib.impl`, + // This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the + // dependency is added after prebuilts may have been renamed and so has to use + // the renamed name. + `sdklib.xml`, + }) +} + +func TestJavaSdkLibraryImport_Preferred(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + } + + java_sdk_library_import { + name: "sdklib", + prefer: true, + public: { + jars: ["a.jar"], + }, + } + `) + + CheckModuleDependencies(t, ctx, "sdklib", "android_common", []string{ + `dex2oatd`, + `prebuilt_sdklib`, + `sdklib.impl`, + `sdklib.stubs`, + `sdklib.stubs.source`, + `sdklib.xml`, + }) + + CheckModuleDependencies(t, ctx, "prebuilt_sdklib", "android_common", []string{ + `prebuilt_sdklib.stubs`, + `sdklib.impl`, + `sdklib.xml`, + }) } func TestDefaults(t *testing.T) { @@ -979,7 +1097,7 @@ func TestDroiddoc(t *testing.T) { ], proofread_file: "libcore-proofread.txt", todo_file: "libcore-docs-todo.html", - args: "-offlinemode -title \"libcore\"", + flags: ["-offlinemode -title \"libcore\""], } `, map[string][]byte{ @@ -1006,6 +1124,42 @@ func TestDroiddoc(t *testing.T) { } } +func TestDroiddocArgsAndFlagsCausesError(t *testing.T) { + testJavaError(t, "flags is set. Cannot set args", ` + droiddoc_exported_dir { + name: "droiddoc-templates-sdk", + path: ".", + } + filegroup { + name: "bar-doc-aidl-srcs", + srcs: ["bar-doc/IBar.aidl"], + path: "bar-doc", + } + droiddoc { + name: "bar-doc", + srcs: [ + "bar-doc/a.java", + "bar-doc/IFoo.aidl", + ":bar-doc-aidl-srcs", + ], + exclude_srcs: [ + "bar-doc/b.java" + ], + custom_template: "droiddoc-templates-sdk", + hdf: [ + "android.whichdoc offline", + ], + knowntags: [ + "bar-doc/known_oj_tags.txt", + ], + proofread_file: "libcore-proofread.txt", + todo_file: "libcore-docs-todo.html", + flags: ["-offlinemode -title \"libcore\""], + args: "-offlinemode -title \"libcore\"", + } + `) +} + func TestDroidstubsWithSystemModules(t *testing.T) { ctx, _ := testJava(t, ` droidstubs { @@ -1345,6 +1499,28 @@ func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { `) } +func TestJavaSdkLibrary_Deps(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + } + `) + + CheckModuleDependencies(t, ctx, "sdklib", "android_common", []string{ + `dex2oatd`, + `sdklib.impl`, + `sdklib.stubs`, + `sdklib.stubs.source`, + `sdklib.xml`, + }) +} + func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { testJava(t, ` java_sdk_library_import { @@ -1808,3 +1984,27 @@ func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, m t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) } } + +func TestAidlExportIncludeDirsFromImports(t *testing.T) { + ctx, _ := testJava(t, ` + java_library { + name: "foo", + srcs: ["aidl/foo/IFoo.aidl"], + libs: ["bar"], + } + + java_import { + name: "bar", + jars: ["a.jar"], + aidl: { + export_include_dirs: ["aidl/bar"], + }, + } + `) + + aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + expectedAidlFlag := "-Iaidl/bar" + if !strings.Contains(aidlCommand, expectedAidlFlag) { + t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) + } +} diff --git a/java/jdeps.go b/java/jdeps.go index 4f636a59f..2b5ee7491 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -75,6 +75,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules) dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars) dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars) + dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths) moduleInfos[name] = dpInfo mkProvider, ok := module.(android.AndroidMkDataProvider) diff --git a/java/kotlin.go b/java/kotlin.go index 673970b9c..e8c030aa7 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -31,7 +31,9 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` + `mkdir -p "$classesDir" "$srcJarDir" "$emptyDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.GenKotlinBuildFileCmd} $classpath "$name" $classesDir $out.rsp $srcJarDir/list > $kotlinBuildFile &&` + + `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` + + ` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` + + ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` + `${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` + `-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile -kotlin-home $emptyDir && ` + `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` + @@ -52,21 +54,43 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports Rspfile: "$out.rsp", RspfileContent: `$in`, }, - "kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile", - "emptyDir", "name") + "kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir", + "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name") + +func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath { + if len(commonSrcFiles) > 0 { + // The list of common_srcs may be too long to put on the command line, but + // we can't use the rsp file because it is already being used for srcs. + // Insert a second rule to write out the list of resources to a file. + commonSrcsList := android.PathForModuleOut(ctx, "kotlinc_common_srcs.list") + rule := android.NewRuleBuilder() + rule.Command().Text("cp").FlagWithRspFileInputList("", commonSrcFiles).Output(commonSrcsList) + rule.Build(pctx, ctx, "kotlin_common_srcs_list", "kotlin common_srcs list") + return android.OptionalPathForPath(commonSrcsList) + } + return android.OptionalPath{} +} // kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile. func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath, - srcFiles, srcJars android.Paths, + srcFiles, commonSrcFiles, srcJars android.Paths, flags javaBuilderFlags) { var deps android.Paths deps = append(deps, flags.kotlincClasspath...) deps = append(deps, srcJars...) + deps = append(deps, commonSrcFiles...) kotlinName := filepath.Join(ctx.ModuleDir(), ctx.ModuleSubDir(), ctx.ModuleName()) kotlinName = strings.ReplaceAll(kotlinName, "/", "__") + commonSrcsList := kotlinCommonSrcsList(ctx, commonSrcFiles) + commonSrcFilesArg := "" + if commonSrcsList.Valid() { + deps = append(deps, commonSrcsList.Path()) + commonSrcFilesArg = "--common_srcs " + commonSrcsList.String() + } + ctx.Build(pctx, android.BuildParams{ Rule: kotlinc, Description: "kotlinc", @@ -74,13 +98,14 @@ func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath, Inputs: srcFiles, Implicits: deps, Args: map[string]string{ - "classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"), - "kotlincFlags": flags.kotlincFlags, - "srcJars": strings.Join(srcJars.Strings(), " "), - "classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(), - "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(), - "kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(), - "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(), + "classpath": flags.kotlincClasspath.FormJavaClassPath(""), + "kotlincFlags": flags.kotlincFlags, + "commonSrcFilesArg": commonSrcFilesArg, + "srcJars": strings.Join(srcJars.Strings(), " "), + "classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(), + "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(), + "kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(), + "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(), // http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8 "kotlinJvmTarget": "1.8", "name": kotlinName, @@ -93,7 +118,9 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` + `mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.GenKotlinBuildFileCmd} $classpath "$name" "" $out.rsp $srcJarDir/list > $kotlinBuildFile &&` + + `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` + + ` --srcs "$out.rsp" --srcs "$srcJarDir/list"` + + ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` + `${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` + `-Xplugin=${config.KotlinKaptJar} ` + `-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` + @@ -120,21 +147,31 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: RspfileContent: `$in`, }, "kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor", - "classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name", - "classesJarOut") + "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget", + "kotlinBuildFile", "name", "classesJarOut") // kotlinKapt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs // annotation processors over all of them, producing a srcjar of generated code in outputFile. The srcjar should be // added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing // disabled. func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath, - srcFiles, srcJars android.Paths, + srcFiles, commonSrcFiles, srcJars android.Paths, flags javaBuilderFlags) { + srcFiles = append(android.Paths(nil), srcFiles...) + var deps android.Paths deps = append(deps, flags.kotlincClasspath...) deps = append(deps, srcJars...) deps = append(deps, flags.processorPath...) + deps = append(deps, commonSrcFiles...) + + commonSrcsList := kotlinCommonSrcsList(ctx, commonSrcFiles) + commonSrcFilesArg := "" + if commonSrcsList.Valid() { + deps = append(deps, commonSrcsList.Path()) + commonSrcFilesArg = "--common_srcs " + commonSrcsList.String() + } kaptProcessorPath := flags.processorPath.FormRepeatedClassPath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=") @@ -162,8 +199,9 @@ func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile an Inputs: srcFiles, Implicits: deps, Args: map[string]string{ - "classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"), + "classpath": flags.kotlincClasspath.FormJavaClassPath(""), "kotlincFlags": flags.kotlincFlags, + "commonSrcFilesArg": commonSrcFilesArg, "srcJars": strings.Join(srcJars.Strings(), " "), "srcJarDir": android.PathForModuleOut(ctx, "kapt", "srcJars").String(), "kotlinBuildFile": android.PathForModuleOut(ctx, "kapt", "build.xml").String(), diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 999c72f3c..b10e6c7fe 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -83,8 +83,7 @@ func createImport(mctx android.LoadHookContext, module string, scope string, api }{} 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") + props.Sdk_version = proptools.StringPtr(scope) props.Installable = proptools.BoolPtr(false) mctx.CreateModule(ImportFactory, &props) diff --git a/java/sdk.go b/java/sdk.go index f96ecded4..6564f6d28 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -94,9 +94,9 @@ func (k sdkKind) String() string { case sdkCorePlatform: return "core_platform" case sdkModule: - return "module" + return "module-lib" case sdkSystemServer: - return "system_server" + return "system-server" default: return "invalid" } @@ -321,6 +321,28 @@ func sdkSpecFrom(str string) sdkSpec { } } +func (s sdkSpec) validateSystemSdk(ctx android.EarlyModuleContext) bool { + // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module) + // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29, + // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current + if s.kind != sdkSystem || !s.version.isNumbered() { + return true + } + allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions() + if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { + systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions() + if len(systemSdkVersions) > 0 { + allowedVersions = systemSdkVersions + } + } + if len(allowedVersions) > 0 && !android.InList(s.version.String(), allowedVersions) { + ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q", + s.raw, allowedVersions) + return false + } + return true +} + func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep { sdkVersion := sdkContext.sdkVersion() if !sdkVersion.valid() { @@ -331,6 +353,9 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep if ctx.Config().IsPdkBuild() { sdkVersion = sdkVersion.forPdkBuild(ctx) } + if !sdkVersion.validateSystemSdk(ctx) { + return sdkDep{} + } if sdkVersion.usePrebuilt(ctx) { dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), sdkVersion.kind.String()) @@ -384,25 +409,13 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep } } - // Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks) - // or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set) - if sdkVersion.kind == sdkSystem && sdkVersion.version.isNumbered() { - allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions() - if ctx.DeviceSpecific() || ctx.SocSpecific() { - if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 { - allowed_versions = ctx.DeviceConfig().SystemSdkVersions() - } - } - if len(allowed_versions) > 0 && !android.InList(sdkVersion.version.String(), allowed_versions) { - ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q", - sdkVersion.raw, allowed_versions) - } - } - switch sdkVersion.kind { case sdkPrivate: return sdkDep{ - useDefaultLibs: true, + useModule: true, + systemModules: config.LegacyCorePlatformSystemModules, + bootclasspath: config.LegacyCorePlatformBootclasspathLibraries, + classpath: config.FrameworkLibraries, frameworkResModule: "framework-res", } case sdkNone: @@ -424,9 +437,10 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep } case sdkCorePlatform: return sdkDep{ - useDefaultLibs: true, - frameworkResModule: "framework-res", - noFrameworksLibs: true, + useModule: true, + systemModules: config.LegacyCorePlatformSystemModules, + bootclasspath: config.LegacyCorePlatformBootclasspathLibraries, + noFrameworksLibs: true, } case sdkPublic: return toModule([]string{"android_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) @@ -435,7 +449,12 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep case sdkTest: return toModule([]string{"android_test_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) case sdkCore: - return toModule([]string{"core.current.stubs"}, "", nil) + return sdkDep{ + useModule: true, + bootclasspath: []string{"core.current.stubs", config.DefaultLambdaStubsLibrary}, + systemModules: "core-current-stubs-system-modules", + noFrameworksLibs: true, + } case sdkModule: // TODO(146757305): provide .apk and .aidl that have more APIs for modules return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx)) diff --git a/java/sdk_library.go b/java/sdk_library.go index 679c07597..68713df82 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -70,6 +70,12 @@ func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep andr } } +var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil) + +func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool { + return false +} + // Provides information about an api scope, e.g. public, system, test. type apiScope struct { // The name of the api scope, e.g. public, system, test @@ -137,6 +143,7 @@ type apiScope struct { droidstubsArgsForGeneratingApi []string // True if the stubs source and api can be created by the same metalava invocation. + // TODO(b/146727827) Now that metalava supports "API hierarchy", do we still need it? createStubsSourceAndApiTogether bool // Whether the api scope can be treated as unstable, and should skip compat checks. @@ -278,6 +285,7 @@ var ( sdkVersion: "module_current", droidstubsArgs: []string{ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)", + "--show-for-stub-purposes-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)", }, }) apiScopeSystemServer = initApiScope(&apiScope{ @@ -976,7 +984,8 @@ func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"} -func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { +// Add the dependencies on the child modules in the component deps mutator. +func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { for _, apiScope := range module.getGeneratedApiScopes(ctx) { // Add dependencies to the stubs library ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) @@ -1001,7 +1010,12 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { // Add dependency to the rule for generating the xml permissions file ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName()) } + } +} +// Add other dependencies as normal. +func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + if module.requiresRuntimeImplementationLibrary() { // Only add the deps for the library if it is actually going to be built. module.Library.deps(ctx) } @@ -1045,8 +1059,10 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { return nil } entriesList := module.Library.AndroidMkEntries() - entries := &entriesList[0] - entries.Required = append(entries.Required, module.xmlPermissionsModuleName()) + if module.sharedLibrary() { + entries := &entriesList[0] + entries.Required = append(entries.Required, module.xmlPermissionsModuleName()) + } return entriesList } @@ -1882,20 +1898,26 @@ func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.Defaulta props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) } -func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { +// Add the dependencies on the child module in the component deps mutator so that it +// creates references to the prebuilt and not the source modules. +func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { for apiScope, scopeProperties := range module.scopeProperties { if len(scopeProperties.Jars) == 0 { continue } // Add dependencies to the prebuilt stubs library - ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.stubsTag, "prebuilt_"+module.stubsLibraryModuleName(apiScope)) if len(scopeProperties.Stub_srcs) > 0 { // Add dependencies to the prebuilt stubs source library - ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, "prebuilt_"+module.stubsSourceModuleName(apiScope)) } } +} + +// Add other dependencies as normal. +func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { implName := module.implLibraryModuleName() if ctx.OtherModuleExists(implName) { @@ -1920,6 +1942,11 @@ func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, return false } +func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + // we don't check prebuilt modules for sdk_version + return nil +} + func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) { return module.commonOutputFiles(tag) } @@ -1993,11 +2020,11 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont } // to satisfy apex.javaDependency interface -func (module *SdkLibraryImport) DexJar() android.Path { +func (module *SdkLibraryImport) DexJarBuildPath() android.Path { if module.implLibraryModule == nil { return nil } else { - return module.implLibraryModule.DexJar() + return module.implLibraryModule.DexJarBuildPath() } } @@ -2086,6 +2113,11 @@ func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { // do nothing } +func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { + // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked + return nil +} + // File path to the runtime implementation library func (module *sdkLibraryXml) implPath() string { implName := proptools.String(module.properties.Lib_name) diff --git a/java/sdk_test.go b/java/sdk_test.go index 52d2df552..1f23b140c 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -49,27 +49,27 @@ func TestClasspath(t *testing.T) { }{ { name: "default", - bootclasspath: config.DefaultBootclasspathLibraries, - system: config.DefaultSystemModules, - java8classpath: config.DefaultLibraries, - java9classpath: config.DefaultLibraries, + bootclasspath: config.LegacyCorePlatformBootclasspathLibraries, + system: config.LegacyCorePlatformSystemModules, + java8classpath: config.FrameworkLibraries, + java9classpath: config.FrameworkLibraries, aidl: "-Iframework/aidl", }, { name: `sdk_version:"core_platform"`, properties: `sdk_version:"core_platform"`, - bootclasspath: config.DefaultBootclasspathLibraries, - system: config.DefaultSystemModules, + bootclasspath: config.LegacyCorePlatformBootclasspathLibraries, + system: config.LegacyCorePlatformSystemModules, java8classpath: []string{}, aidl: "", }, { name: "blank sdk version", properties: `sdk_version: "",`, - bootclasspath: config.DefaultBootclasspathLibraries, - system: config.DefaultSystemModules, - java8classpath: config.DefaultLibraries, - java9classpath: config.DefaultLibraries, + bootclasspath: config.LegacyCorePlatformBootclasspathLibraries, + system: config.LegacyCorePlatformSystemModules, + java8classpath: config.FrameworkLibraries, + java9classpath: config.FrameworkLibraries, aidl: "-Iframework/aidl", }, { @@ -139,11 +139,10 @@ func TestClasspath(t *testing.T) { }, { - name: "core_current", - properties: `sdk_version: "core_current",`, - bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"}, - system: "core-current-stubs-system-modules", - java9classpath: []string{"core.current.stubs"}, + name: "core_current", + properties: `sdk_version: "core_current",`, + bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"}, + system: "core-current-stubs-system-modules", }, { @@ -156,9 +155,9 @@ func TestClasspath(t *testing.T) { { name: "nostdlib system_modules", - properties: `sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules"`, - system: "core-platform-api-stubs-system-modules", - bootclasspath: []string{"core-platform-api-stubs-system-modules-lib"}, + properties: `sdk_version: "none", system_modules: "legacy-core-platform-api-stubs-system-modules"`, + system: "legacy-core-platform-api-stubs-system-modules", + bootclasspath: []string{"legacy-core-platform-api-stubs-system-modules-lib"}, java8classpath: []string{}, }, { diff --git a/java/testing.go b/java/testing.go index 48e449f34..4f3f9f160 100644 --- a/java/testing.go +++ b/java/testing.go @@ -16,9 +16,13 @@ package java import ( "fmt" + "reflect" + "sort" + "testing" "android/soong/android" "android/soong/cc" + "github.com/google/blueprint" ) func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config { @@ -82,11 +86,10 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), // For java_sdk_library - "api/module-lib-current.txt": nil, - "api/module-lib-removed.txt": nil, - "api/system-server-current.txt": nil, - "api/system-server-removed.txt": nil, - "build/soong/scripts/gen-java-current-api-files.sh": nil, + "api/module-lib-current.txt": nil, + "api/module-lib-removed.txt": nil, + "api/system-server-current.txt": nil, + "api/system-server-removed.txt": nil, } cc.GatherRequiredFilesForTest(mockFS) @@ -118,7 +121,8 @@ func GatherRequiredDepsForTest() string { "android_module_lib_stubs_current", "android_system_server_stubs_current", "core.current.stubs", - "core.platform.api.stubs", + "legacy.core.platform.api.stubs", + "stable.core.platform.api.stubs", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", @@ -131,7 +135,7 @@ func GatherRequiredDepsForTest() string { name: "%s", srcs: ["a.java"], sdk_version: "none", - system_modules: "core-platform-api-stubs-system-modules", + system_modules: "legacy-core-platform-api-stubs-system-modules", } `, extra) } @@ -141,7 +145,7 @@ func GatherRequiredDepsForTest() string { name: "framework", srcs: ["a.java"], sdk_version: "none", - system_modules: "core-platform-api-stubs-system-modules", + system_modules: "legacy-core-platform-api-stubs-system-modules", aidl: { export_include_dirs: ["framework/aidl"], }, @@ -156,7 +160,7 @@ func GatherRequiredDepsForTest() string { name: "android.hidl.base-V1.0-java", srcs: ["a.java"], sdk_version: "none", - system_modules: "core-platform-api-stubs-system-modules", + system_modules: "legacy-core-platform-api-stubs-system-modules", installable: true, } @@ -164,7 +168,7 @@ func GatherRequiredDepsForTest() string { name: "android.hidl.manager-V1.0-java", srcs: ["a.java"], sdk_version: "none", - system_modules: "core-platform-api-stubs-system-modules", + system_modules: "legacy-core-platform-api-stubs-system-modules", installable: true, } @@ -172,14 +176,31 @@ func GatherRequiredDepsForTest() string { name: "org.apache.http.legacy", srcs: ["a.java"], sdk_version: "none", - system_modules: "core-platform-api-stubs-system-modules", + system_modules: "legacy-core-platform-api-stubs-system-modules", + installable: true, + } + + java_library { + name: "android.test.base", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "legacy-core-platform-api-stubs-system-modules", + installable: true, + } + + java_library { + name: "android.test.mock", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "legacy-core-platform-api-stubs-system-modules", installable: true, } ` systemModules := []string{ "core-current-stubs-system-modules", - "core-platform-api-stubs-system-modules", + "legacy-core-platform-api-stubs-system-modules", + "stable-core-platform-api-stubs-system-modules", } for _, extra := range systemModules { @@ -198,3 +219,17 @@ func GatherRequiredDepsForTest() string { return bp } + +func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { + t.Helper() + module := ctx.ModuleForTests(name, variant).Module() + deps := []string{} + ctx.VisitDirectDeps(module, func(m blueprint.Module) { + deps = append(deps, m.Name()) + }) + sort.Strings(deps) + + if actual := deps; !reflect.DeepEqual(expected, actual) { + t.Errorf("expected %#q, found %#q", expected, actual) + } +} |