diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/aar.go | 4 | ||||
-rw-r--r-- | java/android_manifest.go | 6 | ||||
-rw-r--r-- | java/base.go | 9 | ||||
-rw-r--r-- | java/bootclasspath_fragment.go | 16 | ||||
-rw-r--r-- | java/dexpreopt.go_v1 | 404 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 18 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go_v1 | 952 | ||||
-rw-r--r-- | java/dexpreopt_config.go_v1 | 215 | ||||
-rw-r--r-- | java/droiddoc.go | 4 | ||||
-rw-r--r-- | java/java.go | 25 | ||||
-rw-r--r-- | java/kotlin.go | 5 | ||||
-rw-r--r-- | java/rro.go | 4 | ||||
-rw-r--r-- | java/systemserver_classpath_fragment.go | 21 |
13 files changed, 86 insertions, 1597 deletions
diff --git a/java/aar.go b/java/aar.go index 00ff7e774..cf84309f4 100644 --- a/java/aar.go +++ b/java/aar.go @@ -678,6 +678,10 @@ func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpe return a.SdkVersion(ctx) } +func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpecFrom(ctx, "") +} + func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return a.SdkVersion(ctx) } diff --git a/java/android_manifest.go b/java/android_manifest.go index a297b2c10..c61823d06 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -136,6 +136,11 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, ctx.ModuleErrorf("invalid minSdkVersion: %s", err) } + replaceMaxSdkVersionPlaceholder, err := params.SdkContext.ReplaceMaxSdkVersionPlaceholder(ctx).EffectiveVersion(ctx) + if err != nil { + ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err) + } + if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) deps = append(deps, ApiFingerprintPath(ctx)) @@ -145,6 +150,7 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, ctx.ModuleErrorf("invalid minSdkVersion: %s", err) } args = append(args, "--minSdkVersion ", minSdkVersion) + args = append(args, "--replaceMaxSdkVersionPlaceholder ", strconv.Itoa(replaceMaxSdkVersionPlaceholder.FinalOrFutureInt())) args = append(args, "--raise-min-sdk-version") } diff --git a/java/base.go b/java/base.go index c399c4063..94daf37fc 100644 --- a/java/base.go +++ b/java/base.go @@ -204,6 +204,10 @@ type DeviceProperties struct { // Defaults to empty string "". See sdk_version for possible values. Max_sdk_version *string + // if not blank, set the maxSdkVersion properties of permission and uses-permission tags. + // Defaults to empty string "". See sdk_version for possible values. + Replace_max_sdk_version_placeholder *string + // if not blank, set the targetSdkVersion in the AndroidManifest.xml. // Defaults to sdk_version if not set. See sdk_version for possible values. Target_sdk_version *string @@ -649,6 +653,11 @@ func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return android.SdkSpecFrom(ctx, maxSdkVersion) } +func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + replaceMaxSdkVersionPlaceholder := proptools.StringDefault(j.deviceProperties.Replace_max_sdk_version_placeholder, "") + return android.SdkSpecFrom(ctx, replaceMaxSdkVersionPlaceholder) +} + func (j *Module) MinSdkVersionString() string { return j.minSdkVersion.Raw } diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 0591012fd..f08b64b23 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -32,12 +32,7 @@ import ( func init() { registerBootclasspathFragmentBuildComponents(android.InitRegistrationContext) - android.RegisterSdkMemberType(&bootclasspathFragmentMemberType{ - SdkMemberTypeBase: android.SdkMemberTypeBase{ - PropertyName: "bootclasspath_fragments", - SupportsSdk: true, - }, - }) + android.RegisterSdkMemberType(BootclasspathFragmentSdkMemberType) } func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContext) { @@ -46,6 +41,15 @@ func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContex ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory) } +// BootclasspathFragmentSdkMemberType is the member type used to add bootclasspath_fragments to +// the SDK snapshot. It is exported for use by apex. +var BootclasspathFragmentSdkMemberType = &bootclasspathFragmentMemberType{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ + PropertyName: "bootclasspath_fragments", + SupportsSdk: true, + }, +} + type bootclasspathFragmentContentDependencyTag struct { blueprint.BaseDependencyTag } diff --git a/java/dexpreopt.go_v1 b/java/dexpreopt.go_v1 deleted file mode 100644 index 0adaf9917..000000000 --- a/java/dexpreopt.go_v1 +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package java - -import ( - "path/filepath" - "strings" - - "android/soong/android" - "android/soong/dexpreopt" -) - -type DexpreopterInterface interface { - IsInstallable() bool // Structs that embed dexpreopter must implement this. - dexpreoptDisabled(ctx android.BaseModuleContext) bool - DexpreoptBuiltInstalledForApex() []dexpreopterInstall - AndroidMkEntriesForApex() []android.AndroidMkEntries -} - -type dexpreopterInstall struct { - // A unique name to distinguish an output from others for the same java library module. Usually in - // the form of `<arch>-<encoded-path>.odex/vdex/art`. - name string - - // The name of the input java module. - moduleName string - - // The path to the dexpreopt output on host. - outputPathOnHost android.Path - - // The directory on the device for the output to install to. - installDirOnDevice android.InstallPath - - // The basename (the last segment of the path) for the output to install as. - installFileOnDevice string -} - -// The full module name of the output in the makefile. -func (install *dexpreopterInstall) FullModuleName() string { - return install.moduleName + install.SubModuleName() -} - -// The sub-module name of the output in the makefile (the name excluding the java module name). -func (install *dexpreopterInstall) SubModuleName() string { - return "-dexpreopt-" + install.name -} - -// Returns Make entries for installing the file. -// -// This function uses a value receiver rather than a pointer receiver to ensure that the object is -// safe to use in `android.AndroidMkExtraEntriesFunc`. -func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { - return android.AndroidMkEntries{ - Class: "ETC", - SubName: install.SubModuleName(), - OutputFile: android.OptionalPathForPath(install.outputPathOnHost), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String()) - entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice) - entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false") - }, - }, - } -} - -type dexpreopter struct { - dexpreoptProperties DexpreoptProperties - - installPath android.InstallPath - uncompressedDex bool - isSDKLibrary bool - isApp bool - isTest bool - isPresignedPrebuilt bool - preventInstall bool - - manifestFile android.Path - statusFile android.WritablePath - enforceUsesLibs bool - classLoaderContexts dexpreopt.ClassLoaderContextMap - - // See the `dexpreopt` function for details. - builtInstalled string - builtInstalledForApex []dexpreopterInstall - - // The config is used for two purposes: - // - Passing dexpreopt information about libraries from Soong to Make. This is needed when - // a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py). - // Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself. - // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally - // dexpreopt another partition). - configPath android.WritablePath -} - -type DexpreoptProperties struct { - Dex_preopt struct { - // If false, prevent dexpreopting. Defaults to true. - Enabled *bool - - // If true, generate an app image (.art file) for this module. - App_image *bool - - // If true, use a checked-in profile to guide optimization. Defaults to false unless - // a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR - // that matches the name of this module, in which case it is defaulted to true. - Profile_guided *bool - - // If set, provides the path to profile relative to the Android.bp file. If not set, - // defaults to searching for a file that matches the name of this module in the default - // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found. - Profile *string `android:"path"` - } -} - -func init() { - dexpreopt.DexpreoptRunningInSoong = true -} - -func isApexVariant(ctx android.BaseModuleContext) bool { - apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) - return !apexInfo.IsForPlatform() -} - -func forPrebuiltApex(ctx android.BaseModuleContext) bool { - apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) - return apexInfo.ForPrebuiltApex -} - -func moduleName(ctx android.BaseModuleContext) string { - // Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not - // expected by dexpreopter. - return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()) -} - -func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { - if !ctx.Device() { - return true - } - - if d.isTest { - return true - } - - if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) { - return true - } - - // If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be - // dexpreopted. - if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) { - return true - } - - if !android.IsModulePreferred(ctx.Module()) { - return true - } - - global := dexpreopt.GetGlobalConfig(ctx) - - if global.DisablePreopt { - return true - } - - if inList(moduleName(ctx), global.DisablePreoptModules) { - return true - } - - isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) - if isApexVariant(ctx) { - // Don't preopt APEX variant module unless the module is an APEX system server jar and we are - // building the entire system image. - if !isApexSystemServerJar || ctx.Config().UnbundledBuild() { - return true - } - } else { - // Don't preopt the platform variant of an APEX system server jar to avoid conflicts. - if isApexSystemServerJar { - return true - } - } - - // TODO: contains no java code - - return false -} - -func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) { - if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) { - return - } - dexpreopt.RegisterToolDeps(ctx) -} - -func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool { - return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx)) -} - -// Returns the install path of the dex jar of a module. -// -// Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather -// than the `name` in the path `/apex/<name>` as suggested in its comment. -// -// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a -// system server jar, which is fine because we currently only preopt system server jars for APEXes. -func (d *dexpreopter) getInstallPath( - ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath { - global := dexpreopt.GetGlobalConfig(ctx) - if global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) { - dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, moduleName(ctx)) - return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/")) - } - if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) && - filepath.Base(defaultInstallPath.PartitionDir()) != "apex" { - ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt") - } - return defaultInstallPath -} - -func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) { - global := dexpreopt.GetGlobalConfig(ctx) - - // TODO(b/148690468): The check on d.installPath is to bail out in cases where - // the dexpreopter struct hasn't been fully initialized before we're called, - // e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively - // disabled, even if installable is true. - if d.installPath.Base() == "." { - return - } - - dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath) - - providesUsesLib := moduleName(ctx) - if ulib, ok := ctx.Module().(ProvidesUsesLib); ok { - name := ulib.ProvidesUsesLib() - if name != nil { - providesUsesLib = *name - } - } - - // If it is test, make config files regardless of its dexpreopt setting. - // The config files are required for apps defined in make which depend on the lib. - if d.isTest && d.dexpreoptDisabled(ctx) { - return - } - - isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx)) - - bootImage := defaultBootImageConfig(ctx) - dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp) - - targets := ctx.MultiTargets() - if len(targets) == 0 { - // assume this is a java library, dexpreopt for all arches for now - for _, target := range ctx.Config().Targets[android.Android] { - if target.NativeBridge == android.NativeBridgeDisabled { - targets = append(targets, target) - } - } - if isSystemServerJar && !d.isSDKLibrary { - // If the module is not an SDK library and it's a system server jar, only preopt the primary arch. - targets = targets[:1] - } - } - - var archs []android.ArchType - var images android.Paths - var imagesDeps []android.OutputPaths - for _, target := range targets { - archs = append(archs, target.Arch.ArchType) - variant := bootImage.getVariant(target) - images = append(images, variant.imagePathOnHost) - imagesDeps = append(imagesDeps, variant.imagesDeps) - } - // The image locations for all Android variants are identical. - hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations() - - var profileClassListing android.OptionalPath - var profileBootListing android.OptionalPath - profileIsTextListing := false - if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) { - // If dex_preopt.profile_guided is not set, default it based on the existence of the - // dexprepot.profile option or the profile class listing. - if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { - profileClassListing = android.OptionalPathForPath( - android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile))) - profileBootListing = android.ExistentPathForSource(ctx, - ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot") - profileIsTextListing = true - } else if global.ProfileDir != "" { - profileClassListing = android.ExistentPathForSource(ctx, - global.ProfileDir, moduleName(ctx)+".prof") - } - } - - // Full dexpreopt config, used to create dexpreopt build rules. - dexpreoptConfig := &dexpreopt.ModuleConfig{ - Name: moduleName(ctx), - DexLocation: dexLocation, - BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath, - DexPath: dexJarFile, - ManifestPath: android.OptionalPathForPath(d.manifestFile), - UncompressedDex: d.uncompressedDex, - HasApkLibraries: false, - PreoptFlags: nil, - - ProfileClassListing: profileClassListing, - ProfileIsTextListing: profileIsTextListing, - ProfileBootListing: profileBootListing, - - EnforceUsesLibrariesStatusFile: dexpreopt.UsesLibrariesStatusFile(ctx), - EnforceUsesLibraries: d.enforceUsesLibs, - ProvidesUsesLibrary: providesUsesLib, - ClassLoaderContexts: d.classLoaderContexts, - - Archs: archs, - DexPreoptImagesDeps: imagesDeps, - DexPreoptImageLocationsOnHost: hostImageLocations, - DexPreoptImageLocationsOnDevice: deviceImageLocations, - - PreoptBootClassPathDexFiles: dexFiles.Paths(), - PreoptBootClassPathDexLocations: dexLocations, - - PreoptExtractedApk: false, - - NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true), - ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false), - - PresignedPrebuilt: d.isPresignedPrebuilt, - } - - d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config") - dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath) - - if d.dexpreoptDisabled(ctx) { - return - } - - globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) - - dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig) - if err != nil { - ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) - return - } - - dexpreoptRule.Build("dexpreopt", "dexpreopt") - - isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) - - for _, install := range dexpreoptRule.Installs() { - // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT. - installDir := strings.TrimPrefix(filepath.Dir(install.To), "/") - installBase := filepath.Base(install.To) - arch := filepath.Base(installDir) - installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir) - - if isApexSystemServerJar { - // APEX variants of java libraries are hidden from Make, so their dexpreopt - // outputs need special handling. Currently, for APEX variants of java - // libraries, only those in the system server classpath are handled here. - // Preopting of boot classpath jars in the ART APEX are handled in - // java/dexpreopt_bootjars.go, and other APEX jars are not preopted. - // The installs will be handled by Make as sub-modules of the java library. - d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{ - name: arch + "-" + installBase, - moduleName: moduleName(ctx), - outputPathOnHost: install.From, - installDirOnDevice: installPath, - installFileOnDevice: installBase, - }) - } else if !d.preventInstall { - ctx.InstallFile(installPath, installBase, install.From) - } - } - - if !isApexSystemServerJar { - d.builtInstalled = dexpreoptRule.Installs().String() - } -} - -func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall { - return d.builtInstalledForApex -} - -func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { - var entries []android.AndroidMkEntries - for _, install := range d.builtInstalledForApex { - entries = append(entries, install.ToMakeEntries()) - } - return entries -} diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 7c4da3ef6..b4cd07a78 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -785,24 +785,26 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and } defaultProfile := "frameworks/base/config/boot-image-profile.txt" + extraProfile := "frameworks/base/config/boot-image-profile-extra.txt" rule := android.NewRuleBuilder(pctx, ctx) - var bootImageProfile android.Path - if len(global.BootImageProfiles) > 1 { - combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt") - rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile) - bootImageProfile = combinedBootImageProfile - } else if len(global.BootImageProfiles) == 1 { - bootImageProfile = global.BootImageProfiles[0] + var profiles android.Paths + if len(global.BootImageProfiles) > 0 { + profiles = append(profiles, global.BootImageProfiles...) } else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() { - bootImageProfile = path.Path() + profiles = append(profiles, path.Path()) } else { // No profile (not even a default one, which is the case on some branches // like master-art-host that don't have frameworks/base). // Return nil and continue without profile. return nil } + if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() { + profiles = append(profiles, path.Path()) + } + bootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt") + rule.Command().Text("cat").Inputs(profiles).Text(">").Output(bootImageProfile) profile := image.dir.Join(ctx, "boot.prof") diff --git a/java/dexpreopt_bootjars.go_v1 b/java/dexpreopt_bootjars.go_v1 deleted file mode 100644 index 07a357bb5..000000000 --- a/java/dexpreopt_bootjars.go_v1 +++ /dev/null @@ -1,952 +0,0 @@ -// Copyright 2019 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package java - -import ( - "path/filepath" - "strings" - - "android/soong/android" - "android/soong/dexpreopt" - - "github.com/google/blueprint/proptools" -) - -// ================================================================================================= -// WIP - see http://b/177892522 for details -// -// The build support for boot images is currently being migrated away from singleton to modules so -// the documentation may not be strictly accurate. Rather than update the documentation at every -// step which will create a lot of churn the changes that have been made will be listed here and the -// documentation will be updated once it is closer to the final result. -// -// Changes: -// 1) dex_bootjars is now a singleton module and not a plain singleton. -// 2) Boot images are now represented by the boot_image module type. -// 3) The art boot image is called "art-boot-image", the framework boot image is called -// "framework-boot-image". -// 4) They are defined in art/build/boot/Android.bp and frameworks/base/boot/Android.bp -// respectively. -// 5) Each boot_image retrieves the appropriate boot image configuration from the map returned by -// genBootImageConfigs() using the image_name specified in the boot_image module. -// ================================================================================================= - -// This comment describes: -// 1. ART boot images in general (their types, structure, file layout, etc.) -// 2. build system support for boot images -// -// 1. ART boot images -// ------------------ -// -// A boot image in ART is a set of files that contain AOT-compiled native code and a heap snapshot -// of AOT-initialized classes for the bootclasspath Java libraries. A boot image is compiled from a -// set of DEX jars by the dex2oat compiler. A boot image is used for two purposes: 1) it is -// installed on device and loaded at runtime, and 2) other Java libraries and apps are compiled -// against it (compilation may take place either on host, known as "dexpreopt", or on device, known -// as "dexopt"). -// -// A boot image is not a single file, but a collection of interrelated files. Each boot image has a -// number of components that correspond to the Java libraries that constitute it. For each component -// there are multiple files: -// - *.oat or *.odex file with native code (architecture-specific, one per instruction set) -// - *.art file with pre-initialized Java classes (architecture-specific, one per instruction set) -// - *.vdex file with verification metadata for the DEX bytecode (architecture independent) -// -// *.vdex files for the boot images do not contain the DEX bytecode itself, because the -// bootclasspath DEX files are stored on disk in uncompressed and aligned form. Consequently a boot -// image is not self-contained and cannot be used without its DEX files. To simplify the management -// of boot image files, ART uses a certain naming scheme and associates the following metadata with -// each boot image: -// - A stem, which is a symbolic name that is prepended to boot image file names. -// - A location (on-device path to the boot image files). -// - A list of boot image locations (on-device paths to dependency boot images). -// - A set of DEX locations (on-device paths to the DEX files, one location for one DEX file used -// to compile the boot image). -// -// There are two kinds of boot images: -// - primary boot images -// - boot image extensions -// -// 1.1. Primary boot images -// ------------------------ -// -// A primary boot image is compiled for a core subset of bootclasspath Java libraries. It does not -// depend on any other images, and other boot images may depend on it. -// -// For example, assuming that the stem is "boot", the location is /apex/com.android.art/javalib/, -// the set of core bootclasspath libraries is A B C, and the boot image is compiled for ARM targets -// (32 and 64 bits), it will have three components with the following files: -// - /apex/com.android.art/javalib/{arm,arm64}/boot.{art,oat,vdex} -// - /apex/com.android.art/javalib/{arm,arm64}/boot-B.{art,oat,vdex} -// - /apex/com.android.art/javalib/{arm,arm64}/boot-C.{art,oat,vdex} -// -// The files of the first component are special: they do not have the component name appended after -// the stem. This naming convention dates back to the times when the boot image was not split into -// components, and there were just boot.oat and boot.art. The decision to split was motivated by -// licensing reasons for one of the bootclasspath libraries. -// -// As of November 2020 the only primary boot image in Android is the image in the ART APEX -// com.android.art. The primary ART boot image contains the Core libraries that are part of the ART -// module. When the ART module gets updated, the primary boot image will be updated with it, and all -// dependent images will get invalidated (the checksum of the primary image stored in dependent -// images will not match), unless they are updated in sync with the ART module. -// -// 1.2. Boot image extensions -// -------------------------- -// -// A boot image extension is compiled for a subset of bootclasspath Java libraries (in particular, -// this subset does not include the Core bootclasspath libraries that go into the primary boot -// image). A boot image extension depends on the primary boot image and optionally some other boot -// image extensions. Other images may depend on it. In other words, boot image extensions can form -// acyclic dependency graphs. -// -// The motivation for boot image extensions comes from the Mainline project. Consider a situation -// when the list of bootclasspath libraries is A B C, and both A and B are parts of the Android -// platform, but C is part of an updatable APEX com.android.C. When the APEX is updated, the Java -// code for C might have changed compared to the code that was used to compile the boot image. -// Consequently, the whole boot image is obsolete and invalidated (even though the code for A and B -// that does not depend on C is up to date). To avoid this, the original monolithic boot image is -// split in two parts: the primary boot image that contains A B, and the boot image extension that -// contains C and depends on the primary boot image (extends it). -// -// For example, assuming that the stem is "boot", the location is /system/framework, the set of -// bootclasspath libraries is D E (where D is part of the platform and is located in -// /system/framework, and E is part of a non-updatable APEX com.android.E and is located in -// /apex/com.android.E/javalib), and the boot image is compiled for ARM targets (32 and 64 bits), -// it will have two components with the following files: -// - /system/framework/{arm,arm64}/boot-D.{art,oat,vdex} -// - /system/framework/{arm,arm64}/boot-E.{art,oat,vdex} -// -// As of November 2020 the only boot image extension in Android is the Framework boot image -// extension. It extends the primary ART boot image and contains Framework libraries and other -// bootclasspath libraries from the platform and non-updatable APEXes that are not included in the -// ART image. The Framework boot image extension is updated together with the platform. In the -// future other boot image extensions may be added for some updatable modules. -// -// -// 2. Build system support for boot images -// --------------------------------------- -// -// The primary ART boot image needs to be compiled with one dex2oat invocation that depends on DEX -// jars for the core libraries. Framework boot image extension needs to be compiled with one dex2oat -// invocation that depends on the primary ART boot image and all bootclasspath DEX jars except the -// core libraries as they are already part of the primary ART boot image. -// -// 2.1. Libraries that go in the boot images -// ----------------------------------------- -// -// The contents of each boot image are determined by the PRODUCT variables. The primary ART APEX -// boot image contains libraries listed in the ART_APEX_JARS variable in the AOSP makefiles. The -// Framework boot image extension contains libraries specified in the PRODUCT_BOOT_JARS and -// PRODUCT_BOOT_JARS_EXTRA variables. The AOSP makefiles specify some common Framework libraries, -// but more product-specific libraries can be added in the product makefiles. -// -// Each component of the PRODUCT_BOOT_JARS and PRODUCT_BOOT_JARS_EXTRA variables is a -// colon-separated pair <apex>:<library>, where <apex> is the variant name of a non-updatable APEX, -// "platform" if the library is a part of the platform in the system partition, or "system_ext" if -// it's in the system_ext partition. -// -// In these variables APEXes are identified by their "variant names", i.e. the names they get -// mounted as in /apex on device. In Soong modules that is the name set in the "apex_name" -// properties, which default to the "name" values. For example, many APEXes have both -// com.android.xxx and com.google.android.xxx modules in Soong, but take the same place -// /apex/com.android.xxx at runtime. In these cases the variant name is always com.android.xxx, -// regardless which APEX goes into the product. See also android.ApexInfo.ApexVariationName and -// apex.apexBundleProperties.Apex_name. -// -// A related variable PRODUCT_APEX_BOOT_JARS contains bootclasspath libraries that are in APEXes. -// They are not included in the boot image. The only exception here are ART jars and core-icu4j.jar -// that have been historically part of the boot image and are now in apexes; they are in boot images -// and core-icu4j.jar is generally treated as being part of PRODUCT_BOOT_JARS. -// -// One exception to the above rules are "coverage" builds (a special build flavor which requires -// setting environment variable EMMA_INSTRUMENT_FRAMEWORK=true). In coverage builds the Java code in -// boot image libraries is instrumented, which means that the instrumentation library (jacocoagent) -// needs to be added to the list of bootclasspath DEX jars. -// -// In general, there is a requirement that the source code for a boot image library must be -// available at build time (e.g. it cannot be a stub that has a separate implementation library). -// -// 2.2. Static configs -// ------------------- -// -// Because boot images are used to dexpreopt other Java modules, the paths to boot image files must -// be known by the time dexpreopt build rules for the dependent modules are generated. Boot image -// configs are constructed very early during the build, before build rule generation. The configs -// provide predefined paths to boot image files (these paths depend only on static build -// configuration, such as PRODUCT variables, and use hard-coded directory names). -// -// 2.3. Singleton -// -------------- -// -// Build rules for the boot images are generated with a Soong singleton. Because a singleton has no -// dependencies on other modules, it has to find the modules for the DEX jars using VisitAllModules. -// Soong loops through all modules and compares each module against a list of bootclasspath library -// names. Then it generates build rules that copy DEX jars from their intermediate module-specific -// locations to the hard-coded locations predefined in the boot image configs. -// -// It would be possible to use a module with proper dependencies instead, but that would require -// changes in the way Soong generates variables for Make: a singleton can use one MakeVars() method -// that writes variables to out/soong/make_vars-*.mk, which is included early by the main makefile, -// but module(s) would have to use out/soong/Android-*.mk which has a group of LOCAL_* variables -// for each module, and is included later. -// -// 2.4. Install rules -// ------------------ -// -// The primary boot image and the Framework extension are installed in different ways. The primary -// boot image is part of the ART APEX: it is copied into the APEX intermediate files, packaged -// together with other APEX contents, extracted and mounted on device. The Framework boot image -// extension is installed by the rules defined in makefiles (make/core/dex_preopt_libart.mk). Soong -// writes out a few DEXPREOPT_IMAGE_* variables for Make; these variables contain boot image names, -// paths and so on. -// - -var artApexNames = []string{ - "com.android.art", - "com.android.art.debug", - "com.android.art.testing", - "com.google.android.art", - "com.google.android.art.debug", - "com.google.android.art.testing", -} - -func init() { - RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext) -} - -// Target-independent description of a boot image. -type bootImageConfig struct { - // 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 - - // Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}. - stem string - - // Output directory for the image files. - dir android.OutputPath - - // Output directory for the image files with debug symbols. - symbolsDir android.OutputPath - - // Subdirectory where the image files are installed. - installDirOnHost string - - // Subdirectory where the image files on device are installed. - installDirOnDevice string - - // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not - // needed. - profileInstallPathInApex string - - // A list of (location, jar) pairs for the Java modules in this image. - modules android.ConfiguredJarList - - // File paths to jars. - dexPaths android.WritablePaths // for this image - dexPathsDeps android.WritablePaths // for the dependency images and in this image - - // Map from module name (without prebuilt_ prefix) to the predefined build path. - dexPathsByModule map[string]android.WritablePath - - // File path to a zip archive with all image files (or nil, if not needed). - zip android.WritablePath - - // Rules which should be used in make to install the outputs. - profileInstalls android.RuleBuilderInstalls - - // Path to the license metadata file for the module that built the profile. - profileLicenseMetadataFile android.OptionalPath - - // Path to the image profile file on host (or empty, if profile is not generated). - profilePathOnHost android.Path - - // Target-dependent fields. - variants []*bootImageVariant - - // Path of the preloaded classes file. - preloadedClassesFile string -} - -// Target-dependent description of a boot image. -type bootImageVariant struct { - *bootImageConfig - - // 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. - imagePathOnHost android.OutputPath // first image file path on host - imagePathOnDevice string // first image file path on device - - // All the files that constitute this image variant, i.e. .art, .oat and .vdex files. - imagesDeps android.OutputPaths - - // The path to the primary image variant's imagePathOnHost field, where primary image variant - // means the image variant that this extends. - // - // This is only set for a variant of an image that extends another image. - primaryImages android.OutputPath - - // The paths to the primary image variant's imagesDeps field, where primary image variant - // means the image variant that this extends. - // - // This is only set for a variant of an image that extends another image. - primaryImagesDeps android.Paths - - // Rules which should be used in make to install the outputs on host. - installs android.RuleBuilderInstalls - vdexInstalls android.RuleBuilderInstalls - unstrippedInstalls android.RuleBuilderInstalls - - // Rules which should be used in make to install the outputs on device. - deviceInstalls android.RuleBuilderInstalls - - // Path to the license metadata file for the module that built the image. - licenseMetadataFile android.OptionalPath -} - -// Get target-specific boot image variant for the given boot image config and target. -func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant { - for _, variant := range image.variants { - if variant.target.Os == target.Os && variant.target.Arch.ArchType == target.Arch.ArchType { - return variant - } - } - return nil -} - -// Return any (the first) variant which is for the device (as opposed to for the host). -func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant { - for _, variant := range image.variants { - if variant.target.Os == android.Android { - return variant - } - } - return nil -} - -// Return the name of a boot image module given a boot image config and a component (module) index. -// A module name is a combination of the Java library name, and the boot image stem (that is stored -// in the config). -func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string { - // The first module of the primary boot image is special: its module name has only the stem, but - // not the library name. All other module names are of the form <stem>-<library name> - m := image.modules.Jar(idx) - name := image.stem - if idx != 0 || image.extends != nil { - name += "-" + android.ModuleStem(m) - } - return name -} - -// Return the name of the first boot image module, or stem if the list of modules is empty. -func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string { - if image.modules.Len() > 0 { - return image.moduleName(ctx, 0) - } else { - return image.stem - } -} - -// Return filenames for the given boot image component, given the output directory and a list of -// extensions. -func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths { - ret := make(android.OutputPaths, 0, image.modules.Len()*len(exts)) - for i := 0; i < image.modules.Len(); i++ { - name := image.moduleName(ctx, i) - for _, ext := range exts { - ret = append(ret, dir.Join(ctx, name+ext)) - } - } - return ret -} - -// apexVariants returns a list of all *bootImageVariant that could be included in an apex. -func (image *bootImageConfig) apexVariants() []*bootImageVariant { - variants := []*bootImageVariant{} - for _, variant := range image.variants { - // We also generate boot images for host (for testing), but we don't need those in the apex. - // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device - if variant.target.Os == android.Android { - variants = append(variants, variant) - } - } - return variants -} - -// Returns true if the boot image should be installed in the APEX. -func (image *bootImageConfig) shouldInstallInApex() bool { - return strings.HasPrefix(image.installDirOnDevice, "apex/") -} - -// Return boot image locations (as a list of symbolic paths). -// -// 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). -// -// For a primary boot image the list of locations has a single element. -// -// For a boot image extension the list of locations contains a location for all dependency images -// (including the primary image) and the location of the extension itself. For example, for the -// Framework boot image extension that depends on the primary ART boot image the list contains two -// elements. -// -// 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() (imageLocationsOnHost []string, imageLocationsOnDevice []string) { - if image.extends != nil { - imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations() - } - return append(imageLocationsOnHost, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)), - append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType)) -} - -func dexpreoptBootJarsFactory() android.SingletonModule { - m := &dexpreoptBootJars{} - android.InitAndroidModule(m) - return m -} - -func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory) -} - -func SkipDexpreoptBootJars(ctx android.PathContext) bool { - return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages -} - -// Singleton module for generating boot image build rules. -type dexpreoptBootJars struct { - android.SingletonModuleBase - - // Default boot image config (currently always the Framework boot image extension). It should be - // noted that JIT-Zygote builds use ART APEX image instead of the Framework boot image extension, - // but the switch is handled not here, but in the makefiles (triggered with - // DEXPREOPT_USE_ART_IMAGE=true). - defaultBootImage *bootImageConfig - - // Build path to a config file that Soong writes for Make (to be used in makefiles that install - // the default boot image). - dexpreoptConfigForMake android.WritablePath -} - -// Provide paths to boot images for use by modules that depend upon them. -// -// The build rules are created in GenerateSingletonBuildActions(). -func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Placeholder for now. -} - -// Generate build rules for boot images. -func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) { - if SkipDexpreoptBootJars(ctx) { - return - } - if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil { - // No module has enabled dexpreopting, so we assume there will be no boot image to make. - return - } - - d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config") - writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) - - global := dexpreopt.GetGlobalConfig(ctx) - if !shouldBuildBootImages(ctx.Config(), global) { - return - } - - defaultImageConfig := defaultBootImageConfig(ctx) - d.defaultBootImage = defaultImageConfig -} - -// shouldBuildBootImages determines whether boot images should be built. -func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool { - // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths - // and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds. - // Note: this is technically incorrect. Compiled code contains stack checks which may depend - // on ASAN settings. - if len(config.SanitizeDevice()) == 1 && config.SanitizeDevice()[0] == "address" && global.SanitizeLite { - return false - } - return true -} - -// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined -// paths in the global config. -func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) { - // Create the super set of module names. - names := []string{} - names = append(names, android.SortedStringKeys(srcBootDexJarsByModule)...) - names = append(names, android.SortedStringKeys(dstBootJarsByModule)...) - names = android.SortedUniqueStrings(names) - for _, name := range names { - src := srcBootDexJarsByModule[name] - dst := dstBootJarsByModule[name] - - if src == nil { - // A dex boot jar should be provided by the source java module. It needs to be installable or - // have compile_dex=true - cf. assignments to java.Module.dexJarFile. - // - // However, the source java module may be either replaced or overridden (using prefer:true) by - // a prebuilt java module with the same name. In that case the dex boot jar needs to be - // provided by the corresponding prebuilt APEX module. That APEX is the one that refers - // through a exported_(boot|systemserver)classpath_fragments property to a - // prebuilt_(boot|systemserver)classpath_fragment module, which in turn lists the prebuilt - // java module in the contents property. If that chain is broken then this dependency will - // fail. - if !ctx.Config().AllowMissingDependencies() { - ctx.ModuleErrorf("module %s does not provide a dex boot jar (see comment next to this message in Soong for details)", name) - } else { - ctx.AddMissingDependencies([]string{name}) - } - } else if dst == nil { - ctx.ModuleErrorf("module %s is not part of the boot configuration", name) - } else { - ctx.Build(pctx, android.BuildParams{ - Rule: android.Cp, - Input: src, - Output: dst, - }) - } - } -} - -// buildBootImageVariantsForAndroidOs generates rules to build the boot image variants for the -// android.Android OsType and returns a map from the architectures to the paths of the generated -// boot image files. -// -// The paths are returned because they are needed elsewhere in Soong, e.g. for populating an APEX. -func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch { - return buildBootImageForOsType(ctx, image, profile, android.Android) -} - -// buildBootImageVariantsForBuildOs generates rules to build the boot image variants for the -// config.BuildOS OsType, i.e. the type of OS on which the build is being running. -// -// The files need to be generated into their predefined location because they are used from there -// both within Soong and outside, e.g. for ART based host side testing and also for use by some -// cloud based tools. However, they are not needed by callers of this function and so the paths do -// not need to be returned from this func, unlike the buildBootImageVariantsForAndroidOs func. -func buildBootImageVariantsForBuildOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) { - buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS) -} - -// buildBootImageForOsType takes a bootImageConfig, a profile file and an android.OsType -// boot image files are required for and it creates rules to build the boot image -// files for all the required architectures for them. -// -// It returns a map from android.ArchType to the predefined paths of the boot image files. -func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageFilesByArch { - filesByArch := bootImageFilesByArch{} - for _, variant := range image.variants { - if variant.target.Os == requiredOsType { - buildBootImageVariant(ctx, variant, profile) - filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths() - } - } - - return filesByArch -} - -// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files. -// -// The supplied filesByArch is nil when the boot image files have not been generated. Otherwise, it -// is a map from android.ArchType to the predefined locations. -func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *bootImageConfig, filesByArch bootImageFilesByArch) { - if filesByArch == nil { - return - } - - // Compute the list of files from all the architectures. - zipFiles := android.Paths{} - for _, archType := range android.ArchTypeList() { - zipFiles = append(zipFiles, filesByArch[archType]...) - } - - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - BuiltTool("soong_zip"). - FlagWithOutput("-o ", image.zip). - FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()). - FlagWithInputList("-f ", zipFiles, " -f ") - - rule.Build("zip_"+image.name, "zip "+image.name+" image") -} - -// Generate boot image build rules for a specific target. -func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) { - - globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) - global := dexpreopt.GetGlobalConfig(ctx) - - arch := image.target.Arch.ArchType - os := image.target.Os.String() // We need to distinguish host-x86 and device-x86. - symbolsDir := image.symbolsDir.Join(ctx, os, image.installDirOnHost, arch.String()) - symbolsFile := symbolsDir.Join(ctx, image.stem+".oat") - outputDir := image.dir.Join(ctx, os, image.installDirOnHost, arch.String()) - outputPath := outputDir.Join(ctx, image.stem+".oat") - oatLocation := dexpreopt.PathToLocation(outputPath, arch) - imagePath := outputPath.ReplaceExtension(ctx, "art") - - rule := android.NewRuleBuilder(pctx, ctx) - - rule.Command().Text("mkdir").Flag("-p").Flag(symbolsDir.String()) - rule.Command().Text("rm").Flag("-f"). - Flag(symbolsDir.Join(ctx, "*.art").String()). - Flag(symbolsDir.Join(ctx, "*.oat").String()). - Flag(symbolsDir.Join(ctx, "*.invocation").String()) - rule.Command().Text("rm").Flag("-f"). - Flag(outputDir.Join(ctx, "*.art").String()). - Flag(outputDir.Join(ctx, "*.oat").String()). - Flag(outputDir.Join(ctx, "*.invocation").String()) - - cmd := rule.Command() - - extraFlags := ctx.Config().Getenv("ART_BOOT_IMAGE_EXTRA_ARGS") - if extraFlags == "" { - // Use ANDROID_LOG_TAGS to suppress most logging by default... - cmd.Text(`ANDROID_LOG_TAGS="*:e"`) - } else { - // ...unless the boot image is generated specifically for testing, then allow all logging. - cmd.Text(`ANDROID_LOG_TAGS="*:v"`) - } - - invocationPath := outputPath.ReplaceExtension(ctx, "invocation") - - cmd.Tool(globalSoong.Dex2oat). - Flag("--avoid-storing-invocation"). - FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath). - Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms). - Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx) - - if profile != nil { - cmd.FlagWithInput("--profile-file=", profile) - } - - dirtyImageFile := "frameworks/base/config/dirty-image-objects" - dirtyImagePath := android.ExistentPathForSource(ctx, dirtyImageFile) - if dirtyImagePath.Valid() { - cmd.FlagWithInput("--dirty-image-objects=", dirtyImagePath.Path()) - } - - if image.extends != nil { - // It is a boot image extension, so it needs the boot image it depends on (in this case the - // primary ART APEX image). - artImage := image.primaryImages - cmd. - Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). - Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - // Add the path to the first file in the boot image with the arch specific directory removed, - // dex2oat will reconstruct the path to the actual file when it needs it. As the actual path - // to the file cannot be passed to the command make sure to add the actual path as an Implicit - // dependency to ensure that it is built before the command runs. - FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage). - // Similarly, the dex2oat tool will automatically find the paths to other files in the base - // boot image so make sure to add them as implicit dependencies to ensure that they are built - // before this command is run. - Implicits(image.primaryImagesDeps) - } else { - // It is a primary image, so it needs a base address. - cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress()) - } - - // We always expect a preloaded classes file to be available. However, if we cannot find it, it's - // OK to not pass the flag to dex2oat. - preloadedClassesPath := android.ExistentPathForSource(ctx, image.preloadedClassesFile) - if preloadedClassesPath.Valid() { - cmd.FlagWithInput("--preloaded-classes=", preloadedClassesPath.Path()) - } - - cmd. - FlagForEachInput("--dex-file=", image.dexPaths.Paths()). - FlagForEachArg("--dex-location=", image.dexLocations). - Flag("--generate-debug-info"). - Flag("--generate-build-id"). - Flag("--image-format=lz4hc"). - FlagWithArg("--oat-symbols=", symbolsFile.String()). - Flag("--strip"). - FlagWithArg("--oat-file=", outputPath.String()). - FlagWithArg("--oat-location=", oatLocation). - FlagWithArg("--image=", imagePath.String()). - FlagWithArg("--instruction-set=", arch.String()). - 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) - } - - if extraFlags != "" { - cmd.Flag(extraFlags) - } - - cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage)) - - installDir := filepath.Join("/", image.installDirOnHost, arch.String()) - - var vdexInstalls android.RuleBuilderInstalls - var unstrippedInstalls android.RuleBuilderInstalls - var deviceInstalls android.RuleBuilderInstalls - - for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") { - cmd.ImplicitOutput(artOrOat) - - // Install the .oat and .art files - rule.Install(artOrOat, filepath.Join(installDir, artOrOat.Base())) - } - - for _, vdex := range image.moduleFiles(ctx, outputDir, ".vdex") { - cmd.ImplicitOutput(vdex) - - // 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(installDir, vdex.Base())}) - } - - for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") { - cmd.ImplicitOutput(unstrippedOat) - - // Install the unstripped oat files. The Make rules will put these in $(TARGET_OUT_UNSTRIPPED) - unstrippedInstalls = append(unstrippedInstalls, - android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())}) - } - - if image.installDirOnHost != image.installDirOnDevice && !image.shouldInstallInApex() && !ctx.Config().UnbundledBuild() { - installDirOnDevice := filepath.Join("/", image.installDirOnDevice, arch.String()) - for _, file := range image.moduleFiles(ctx, outputDir, ".art", ".oat", ".vdex") { - deviceInstalls = append(deviceInstalls, - android.RuleBuilderInstall{file, filepath.Join(installDirOnDevice, file.Base())}) - } - } - - rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String()) - - // save output and installed files for makevars - image.installs = rule.Installs() - image.vdexInstalls = vdexInstalls - image.unstrippedInstalls = unstrippedInstalls - image.deviceInstalls = deviceInstalls - image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) -} - -const failureMessage = `ERROR: Dex2oat failed to compile a boot image. -It is likely that the boot classpath is inconsistent. -Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.` - -func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath { - globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) - global := dexpreopt.GetGlobalConfig(ctx) - - if global.DisableGenerateProfile { - return nil - } - - defaultProfile := "frameworks/base/config/boot-image-profile.txt" - - rule := android.NewRuleBuilder(pctx, ctx) - - var bootImageProfile android.Path - if len(global.BootImageProfiles) > 1 { - combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt") - rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile) - bootImageProfile = combinedBootImageProfile - } else if len(global.BootImageProfiles) == 1 { - bootImageProfile = global.BootImageProfiles[0] - } else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() { - bootImageProfile = path.Path() - } else { - // No profile (not even a default one, which is the case on some branches - // like master-art-host that don't have frameworks/base). - // Return nil and continue without profile. - return nil - } - - profile := image.dir.Join(ctx, "boot.prof") - - rule.Command(). - Text(`ANDROID_LOG_TAGS="*:e"`). - Tool(globalSoong.Profman). - Flag("--output-profile-type=boot"). - FlagWithInput("--create-profile-from=", bootImageProfile). - FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). - FlagWithOutput("--reference-profile-file=", profile) - - if image == defaultBootImageConfig(ctx) { - rule.Install(profile, "/system/etc/boot-image.prof") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) - image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) - } - - rule.Build("bootJarsProfile", "profile boot jars") - - image.profilePathOnHost = profile - - return profile -} - -// bootFrameworkProfileRule generates the rule to create the boot framework profile and -// returns a path to the generated file. -func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath { - globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) - global := dexpreopt.GetGlobalConfig(ctx) - - if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() { - return nil - } - - defaultProfile := "frameworks/base/config/boot-profile.txt" - bootFrameworkProfile := android.PathForSource(ctx, defaultProfile) - - profile := image.dir.Join(ctx, "boot.bprof") - - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - Text(`ANDROID_LOG_TAGS="*:e"`). - Tool(globalSoong.Profman). - Flag("--output-profile-type=bprof"). - FlagWithInput("--create-profile-from=", bootFrameworkProfile). - FlagForEachInput("--apk=", image.dexPathsDeps.Paths()). - FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). - FlagWithOutput("--reference-profile-file=", profile) - - rule.Install(profile, "/system/etc/boot-image.bprof") - rule.Build("bootFrameworkProfile", "profile boot framework jars") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) - image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) - - return profile -} - -func dumpOatRules(ctx android.ModuleContext, 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."+suffix+".oatdump.txt") - rule := android.NewRuleBuilder(pctx, ctx) - imageLocationsOnHost, _ := image.imageLocations() - rule.Command(). - BuiltTool("oatdump"). - FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). - FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()). - FlagWithOutput("--output=", output). - FlagWithArg("--instruction-set=", arch.String()) - rule.Build("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-"+suffix) - rule = android.NewRuleBuilder(pctx, ctx) - rule.Command(). - Implicit(output). - ImplicitOutput(phony). - Text("echo").FlagWithArg("Output in ", output.String()) - rule.Build("phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) - - allPhonies = append(allPhonies, phony) - } - - phony := android.PathForPhony(ctx, "dump-oat-boot") - ctx.Build(pctx, android.BuildParams{ - Rule: android.Phony, - Output: phony, - Inputs: allPhonies, - Description: "dump-oat-boot", - }) -} - -func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) { - data := dexpreopt.GetGlobalConfigRawData(ctx) - - android.WriteFileRule(ctx, path, string(data)) -} - -// Define Make variables for boot image names, paths, etc. These variables are used in makefiles -// (make/core/dex_preopt_libart.mk) to generate install rules that copy boot image files to the -// correct output directories. -func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { - if d.dexpreoptConfigForMake != nil { - ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String()) - ctx.Strict("DEX_PREOPT_SOONG_CONFIG_FOR_MAKE", android.PathForOutput(ctx, "dexpreopt_soong.config").String()) - } - - image := d.defaultBootImage - if image == nil { - return - } - - ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) - if image.profileLicenseMetadataFile.Valid() { - ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", image.profileLicenseMetadataFile.String()) - } - - global := dexpreopt.GetGlobalConfig(ctx) - dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp) - ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " ")) - ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " ")) - - for _, variant := range image.variants { - suffix := "" - if variant.target.Os.Class == android.Host { - suffix = "_host" - } - sfx := suffix + "_" + variant.target.Arch.ArchType.String() - ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, variant.vdexInstalls.String()) - ctx.Strict("DEXPREOPT_IMAGE_"+sfx, variant.imagePathOnHost.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()) - if variant.licenseMetadataFile.Valid() { - ctx.Strict("DEXPREOPT_IMAGE_LICENSE_METADATA_"+sfx, variant.licenseMetadataFile.String()) - } - } - imageLocationsOnHost, imageLocationsOnDevice := image.getAnyAndroidVariant().imageLocations() - ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_HOST", strings.Join(imageLocationsOnHost, ":")) - ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE", strings.Join(imageLocationsOnDevice, ":")) - ctx.Strict("DEXPREOPT_IMAGE_ZIP", image.zip.String()) - - // There used to be multiple images for JIT-Zygote mode, not there's only one. - ctx.Strict("DEXPREOPT_IMAGE_NAMES", image.name) -} diff --git a/java/dexpreopt_config.go_v1 b/java/dexpreopt_config.go_v1 deleted file mode 100644 index d71e2bbfd..000000000 --- a/java/dexpreopt_config.go_v1 +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2019 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package java - -import ( - "path/filepath" - "strings" - - "android/soong/android" - "android/soong/dexpreopt" -) - -// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures -// supported through native bridge. -func dexpreoptTargets(ctx android.PathContext) []android.Target { - var targets []android.Target - for _, target := range ctx.Config().Targets[android.Android] { - if target.NativeBridge == android.NativeBridgeDisabled { - 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[ctx.Config().BuildOS] { - targets = append(targets, target) - } - - return targets -} - -var ( - bootImageConfigKey = android.NewOnceKey("bootImageConfig") - bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw") - artBootImageName = "art" - frameworkBootImageName = "boot" -) - -func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig { - return ctx.Config().Once(bootImageConfigRawKey, func() interface{} { - global := dexpreopt.GetGlobalConfig(ctx) - - artModules := global.ArtApexJars - frameworkModules := global.BootJars.RemoveList(artModules) - - // ART config for the primary boot image in the ART apex. - // It includes the Core Libraries. - artCfg := bootImageConfig{ - name: artBootImageName, - stem: "boot", - installDirOnHost: "apex/art_boot_images/javalib", - installDirOnDevice: "system/framework", - profileInstallPathInApex: "etc/boot-image.prof", - modules: artModules, - preloadedClassesFile: "art/build/boot/preloaded-classes", - } - - // Framework config for the boot image extension. - // It includes framework libraries and depends on the ART config. - frameworkSubdir := "system/framework" - frameworkCfg := bootImageConfig{ - extends: &artCfg, - name: frameworkBootImageName, - stem: "boot", - installDirOnHost: frameworkSubdir, - installDirOnDevice: frameworkSubdir, - modules: frameworkModules, - preloadedClassesFile: "frameworks/base/config/preloaded-classes", - } - - return map[string]*bootImageConfig{ - artBootImageName: &artCfg, - frameworkBootImageName: &frameworkCfg, - } - }).(map[string]*bootImageConfig) -} - -// Construct the global boot image configs. -func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { - return ctx.Config().Once(bootImageConfigKey, func() interface{} { - targets := dexpreoptTargets(ctx) - deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName()) - - configs := genBootImageConfigRaw(ctx) - artCfg := configs[artBootImageName] - frameworkCfg := configs[frameworkBootImageName] - - // common to all configs - for _, c := range configs { - c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars") - 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(ctx) + ".art" - - // The path to bootclasspath dex files needs to be known at module - // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. - // Set up known paths for them, the singleton rules will copy them there. - // TODO(b/143682396): use module dependencies instead - inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") - c.dexPaths = c.modules.BuildPaths(ctx, inputDir) - c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir) - c.dexPathsDeps = c.dexPaths - - // Create target-specific variants. - for _, target := range targets { - arch := target.Arch.ArchType - imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String()) - variant := &bootImageVariant{ - bootImageConfig: c, - target: target, - imagePathOnHost: imageDir.Join(ctx, imageName), - imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName), - imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), - dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os), - } - variant.dexLocationsDeps = variant.dexLocations - c.variants = append(c.variants, variant) - } - - c.zip = c.dir.Join(ctx, c.name+".zip") - } - - // specific to the framework config - frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) - for i := range targets { - frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost - frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths() - frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) - } - - return configs - }).(map[string]*bootImageConfig) -} - -func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { - return genBootImageConfigs(ctx)[frameworkBootImageName] -} - -// Apex boot config allows to access build/install paths of apex boot jars without going -// through the usual trouble of registering dependencies on those modules and extracting build paths -// from those dependencies. -type apexBootConfig struct { - // A list of apex boot jars. - modules android.ConfiguredJarList - - // A list of predefined build paths to apex boot jars. They are configured very early, - // before the modules for these jars are processed and the actual paths are generated, and - // later on a singleton adds commands to copy actual jars to the predefined paths. - dexPaths android.WritablePaths - - // Map from module name (without prebuilt_ prefix) to the predefined build path. - dexPathsByModule map[string]android.WritablePath - - // A list of dex locations (a.k.a. on-device paths) to the boot jars. - dexLocations []string -} - -var updatableBootConfigKey = android.NewOnceKey("apexBootConfig") - -// Returns apex boot config. -func GetApexBootConfig(ctx android.PathContext) apexBootConfig { - return ctx.Config().Once(updatableBootConfigKey, func() interface{} { - apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars - - dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "apex_bootjars") - dexPaths := apexBootJars.BuildPaths(ctx, dir) - dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir) - - dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android) - - return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations} - }).(apexBootConfig) -} - -// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be -// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat). -func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) { - // Non-updatable boot jars (they are used both in the boot image and in dexpreopt). - bootImage := defaultBootImageConfig(ctx) - dexPaths := bootImage.dexPathsDeps - // The dex locations for all Android variants are identical. - dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps - - if withUpdatable { - // Apex boot jars (they are used only in dexpreopt, but not in the boot image). - apexBootConfig := GetApexBootConfig(ctx) - dexPaths = append(dexPaths, apexBootConfig.dexPaths...) - dexLocations = append(dexLocations, apexBootConfig.dexLocations...) - } - - return dexPaths, dexLocations -} - -var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") - -var copyOf = android.CopyOf - -func init() { - android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) -} - -func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { - ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":")) -} diff --git a/java/droiddoc.go b/java/droiddoc.go index 023d61912..96639220a 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -256,6 +256,10 @@ func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec return j.SdkVersion(ctx) } +func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return j.SdkVersion(ctx) +} + func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } diff --git a/java/java.go b/java/java.go index cbdc2bd28..eaf82ad7a 100644 --- a/java/java.go +++ b/java/java.go @@ -513,6 +513,20 @@ func (v javaVersion) String() string { } } +func (v javaVersion) StringForKotlinc() string { + // $ ./external/kotlinc/bin/kotlinc -jvm-target foo + // error: unknown JVM target version: foo + // Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17 + switch v { + case JAVA_VERSION_7: + return "1.6" + case JAVA_VERSION_9: + return "9" + default: + return v.String() + } +} + // Returns true if javac targeting this version uses system modules instead of a bootclasspath. func (v javaVersion) usesJavaModules() bool { return v >= 9 @@ -1445,6 +1459,10 @@ type ImportProperties struct { // specified. Min_sdk_version *string + // The max sdk version placeholder used to replace maxSdkVersion attributes on permission + // and uses-permission tags in manifest_fixer. + Replace_max_sdk_version_placeholder *string + Installable *bool // If not empty, classes are restricted to the specified packages and their sub-packages. @@ -1524,6 +1542,13 @@ func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } +func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + if j.properties.Replace_max_sdk_version_placeholder != nil { + return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder) + } + return android.SdkSpecFrom(ctx, "") +} + func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } diff --git a/java/kotlin.go b/java/kotlin.go index 903c6249b..9bff5ea01 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -119,9 +119,8 @@ func kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile andro "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, + "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(), + "name": kotlinName, }, }) } diff --git a/java/rro.go b/java/rro.go index be84afffc..7952c2cc4 100644 --- a/java/rro.go +++ b/java/rro.go @@ -173,6 +173,10 @@ func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) a return r.SdkVersion(ctx) } +func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpecFrom(ctx, "") +} + func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return r.SdkVersion(ctx) } diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index 79d2ee9f7..a2cd2619a 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -24,15 +24,7 @@ import ( func init() { registerSystemserverClasspathBuildComponents(android.InitRegistrationContext) - android.RegisterSdkMemberType(&systemServerClasspathFragmentMemberType{ - SdkMemberTypeBase: android.SdkMemberTypeBase{ - PropertyName: "systemserverclasspath_fragments", - SupportsSdk: true, - - // This was only added in Tiramisu. - SupportedBuildReleaseSpecification: "Tiramisu+", - }, - }) + android.RegisterSdkMemberType(SystemServerClasspathFragmentSdkMemberType) } func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContext) { @@ -41,6 +33,17 @@ func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContex ctx.RegisterModuleType("prebuilt_systemserverclasspath_fragment", prebuiltSystemServerClasspathModuleFactory) } +var SystemServerClasspathFragmentSdkMemberType = &systemServerClasspathFragmentMemberType{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ + PropertyName: "systemserverclasspath_fragments", + SupportsSdk: true, + + // Support for adding systemserverclasspath_fragments to the sdk snapshot was only added in + // Tiramisu. + SupportedBuildReleaseSpecification: "Tiramisu+", + }, +} + type platformSystemServerClasspathModule struct { android.ModuleBase |