xref: /aosp_15_r20/build/soong/java/dexpreopt.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2018 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage java
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
19*333d2b36SAndroid Build Coastguard Worker	"sort"
20*333d2b36SAndroid Build Coastguard Worker	"strings"
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/dexpreopt"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Workertype DexpreopterInterface interface {
29*333d2b36SAndroid Build Coastguard Worker	// True if the java module is to be dexed and installed on devices.
30*333d2b36SAndroid Build Coastguard Worker	// Structs that embed dexpreopter must implement this.
31*333d2b36SAndroid Build Coastguard Worker	IsInstallable() bool
32*333d2b36SAndroid Build Coastguard Worker
33*333d2b36SAndroid Build Coastguard Worker	// True if dexpreopt is disabled for the java module.
34*333d2b36SAndroid Build Coastguard Worker	dexpreoptDisabled(ctx android.BaseModuleContext, libraryName string) bool
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Worker	// If the java module is to be installed into an APEX, this list contains information about the
37*333d2b36SAndroid Build Coastguard Worker	// dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed
38*333d2b36SAndroid Build Coastguard Worker	// outside of the APEX.
39*333d2b36SAndroid Build Coastguard Worker	DexpreoptBuiltInstalledForApex() []dexpreopterInstall
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Worker	// The Make entries to install the dexpreopt outputs. Derived from
42*333d2b36SAndroid Build Coastguard Worker	// `DexpreoptBuiltInstalledForApex`.
43*333d2b36SAndroid Build Coastguard Worker	AndroidMkEntriesForApex() []android.AndroidMkEntries
44*333d2b36SAndroid Build Coastguard Worker
45*333d2b36SAndroid Build Coastguard Worker	// See `dexpreopter.outputProfilePathOnHost`.
46*333d2b36SAndroid Build Coastguard Worker	OutputProfilePathOnHost() android.Path
47*333d2b36SAndroid Build Coastguard Worker}
48*333d2b36SAndroid Build Coastguard Worker
49*333d2b36SAndroid Build Coastguard Workertype dexpreopterInstall struct {
50*333d2b36SAndroid Build Coastguard Worker	// A unique name to distinguish an output from others for the same java library module. Usually in
51*333d2b36SAndroid Build Coastguard Worker	// the form of `<arch>-<encoded-path>.odex/vdex/art`.
52*333d2b36SAndroid Build Coastguard Worker	name string
53*333d2b36SAndroid Build Coastguard Worker
54*333d2b36SAndroid Build Coastguard Worker	// The name of the input java module.
55*333d2b36SAndroid Build Coastguard Worker	moduleName string
56*333d2b36SAndroid Build Coastguard Worker
57*333d2b36SAndroid Build Coastguard Worker	// The path to the dexpreopt output on host.
58*333d2b36SAndroid Build Coastguard Worker	outputPathOnHost android.Path
59*333d2b36SAndroid Build Coastguard Worker
60*333d2b36SAndroid Build Coastguard Worker	// The directory on the device for the output to install to.
61*333d2b36SAndroid Build Coastguard Worker	installDirOnDevice android.InstallPath
62*333d2b36SAndroid Build Coastguard Worker
63*333d2b36SAndroid Build Coastguard Worker	// The basename (the last segment of the path) for the output to install as.
64*333d2b36SAndroid Build Coastguard Worker	installFileOnDevice string
65*333d2b36SAndroid Build Coastguard Worker}
66*333d2b36SAndroid Build Coastguard Worker
67*333d2b36SAndroid Build Coastguard Worker// The full module name of the output in the makefile.
68*333d2b36SAndroid Build Coastguard Workerfunc (install *dexpreopterInstall) FullModuleName() string {
69*333d2b36SAndroid Build Coastguard Worker	return install.moduleName + install.SubModuleName()
70*333d2b36SAndroid Build Coastguard Worker}
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker// The sub-module name of the output in the makefile (the name excluding the java module name).
73*333d2b36SAndroid Build Coastguard Workerfunc (install *dexpreopterInstall) SubModuleName() string {
74*333d2b36SAndroid Build Coastguard Worker	return "-dexpreopt-" + install.name
75*333d2b36SAndroid Build Coastguard Worker}
76*333d2b36SAndroid Build Coastguard Worker
77*333d2b36SAndroid Build Coastguard Worker// Returns Make entries for installing the file.
78*333d2b36SAndroid Build Coastguard Worker//
79*333d2b36SAndroid Build Coastguard Worker// This function uses a value receiver rather than a pointer receiver to ensure that the object is
80*333d2b36SAndroid Build Coastguard Worker// safe to use in `android.AndroidMkExtraEntriesFunc`.
81*333d2b36SAndroid Build Coastguard Workerfunc (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
82*333d2b36SAndroid Build Coastguard Worker	return android.AndroidMkEntries{
83*333d2b36SAndroid Build Coastguard Worker		Class:      "ETC",
84*333d2b36SAndroid Build Coastguard Worker		OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
85*333d2b36SAndroid Build Coastguard Worker		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
86*333d2b36SAndroid Build Coastguard Worker			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
87*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_MODULE", install.FullModuleName())
88*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
89*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
90*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
91*333d2b36SAndroid Build Coastguard Worker			},
92*333d2b36SAndroid Build Coastguard Worker		},
93*333d2b36SAndroid Build Coastguard Worker	}
94*333d2b36SAndroid Build Coastguard Worker}
95*333d2b36SAndroid Build Coastguard Worker
96*333d2b36SAndroid Build Coastguard Workertype Dexpreopter struct {
97*333d2b36SAndroid Build Coastguard Worker	dexpreopter
98*333d2b36SAndroid Build Coastguard Worker}
99*333d2b36SAndroid Build Coastguard Worker
100*333d2b36SAndroid Build Coastguard Workertype dexpreopter struct {
101*333d2b36SAndroid Build Coastguard Worker	dexpreoptProperties       DexpreoptProperties
102*333d2b36SAndroid Build Coastguard Worker	importDexpreoptProperties ImportDexpreoptProperties
103*333d2b36SAndroid Build Coastguard Worker
104*333d2b36SAndroid Build Coastguard Worker	// If true, the dexpreopt rules will not be generated
105*333d2b36SAndroid Build Coastguard Worker	// Unlike Dex_preopt.Enabled which is user-facing,
106*333d2b36SAndroid Build Coastguard Worker	// shouldDisableDexpreopt is a mutated propery.
107*333d2b36SAndroid Build Coastguard Worker	shouldDisableDexpreopt bool
108*333d2b36SAndroid Build Coastguard Worker
109*333d2b36SAndroid Build Coastguard Worker	installPath         android.InstallPath
110*333d2b36SAndroid Build Coastguard Worker	uncompressedDex     bool
111*333d2b36SAndroid Build Coastguard Worker	isSDKLibrary        bool
112*333d2b36SAndroid Build Coastguard Worker	isApp               bool
113*333d2b36SAndroid Build Coastguard Worker	isTest              bool
114*333d2b36SAndroid Build Coastguard Worker	isPresignedPrebuilt bool
115*333d2b36SAndroid Build Coastguard Worker	preventInstall      bool
116*333d2b36SAndroid Build Coastguard Worker
117*333d2b36SAndroid Build Coastguard Worker	manifestFile        android.Path
118*333d2b36SAndroid Build Coastguard Worker	statusFile          android.WritablePath
119*333d2b36SAndroid Build Coastguard Worker	enforceUsesLibs     bool
120*333d2b36SAndroid Build Coastguard Worker	classLoaderContexts dexpreopt.ClassLoaderContextMap
121*333d2b36SAndroid Build Coastguard Worker
122*333d2b36SAndroid Build Coastguard Worker	// See the `dexpreopt` function for details.
123*333d2b36SAndroid Build Coastguard Worker	builtInstalled        string
124*333d2b36SAndroid Build Coastguard Worker	builtInstalledForApex []dexpreopterInstall
125*333d2b36SAndroid Build Coastguard Worker
126*333d2b36SAndroid Build Coastguard Worker	// The config is used for two purposes:
127*333d2b36SAndroid Build Coastguard Worker	// - Passing dexpreopt information about libraries from Soong to Make. This is needed when
128*333d2b36SAndroid Build Coastguard Worker	//   a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py).
129*333d2b36SAndroid Build Coastguard Worker	//   Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself.
130*333d2b36SAndroid Build Coastguard Worker	// - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
131*333d2b36SAndroid Build Coastguard Worker	//   dexpreopt another partition).
132*333d2b36SAndroid Build Coastguard Worker	configPath android.WritablePath
133*333d2b36SAndroid Build Coastguard Worker
134*333d2b36SAndroid Build Coastguard Worker	// The path to the profile on host that dexpreopter generates. This is used as the input for
135*333d2b36SAndroid Build Coastguard Worker	// dex2oat.
136*333d2b36SAndroid Build Coastguard Worker	outputProfilePathOnHost android.Path
137*333d2b36SAndroid Build Coastguard Worker
138*333d2b36SAndroid Build Coastguard Worker	// The path to the profile that dexpreopter accepts. It must be in the binary format. If this is
139*333d2b36SAndroid Build Coastguard Worker	// set, it overrides the profile settings in `dexpreoptProperties`.
140*333d2b36SAndroid Build Coastguard Worker	inputProfilePathOnHost android.Path
141*333d2b36SAndroid Build Coastguard Worker
142*333d2b36SAndroid Build Coastguard Worker	// The path to the profile that matches the dex optimized by r8/d8. It is in text format. If this is
143*333d2b36SAndroid Build Coastguard Worker	// set, it will be converted to a binary profile which will be subsequently used for dexpreopt.
144*333d2b36SAndroid Build Coastguard Worker	rewrittenProfile android.Path
145*333d2b36SAndroid Build Coastguard Worker}
146*333d2b36SAndroid Build Coastguard Worker
147*333d2b36SAndroid Build Coastguard Workertype DexpreoptProperties struct {
148*333d2b36SAndroid Build Coastguard Worker	Dex_preopt struct {
149*333d2b36SAndroid Build Coastguard Worker		// If false, prevent dexpreopting.  Defaults to true.
150*333d2b36SAndroid Build Coastguard Worker		Enabled proptools.Configurable[bool] `android:"replace_instead_of_append"`
151*333d2b36SAndroid Build Coastguard Worker
152*333d2b36SAndroid Build Coastguard Worker		// If true, generate an app image (.art file) for this module.
153*333d2b36SAndroid Build Coastguard Worker		App_image proptools.Configurable[bool] `android:"replace_instead_of_append"`
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker		// If true, use a checked-in profile to guide optimization.  Defaults to false unless
156*333d2b36SAndroid Build Coastguard Worker		// a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
157*333d2b36SAndroid Build Coastguard Worker		// that matches the name of this module, in which case it is defaulted to true.
158*333d2b36SAndroid Build Coastguard Worker		Profile_guided proptools.Configurable[bool] `android:"replace_instead_of_append"`
159*333d2b36SAndroid Build Coastguard Worker
160*333d2b36SAndroid Build Coastguard Worker		// If set, provides the path to profile relative to the Android.bp file.  If not set,
161*333d2b36SAndroid Build Coastguard Worker		// defaults to searching for a file that matches the name of this module in the default
162*333d2b36SAndroid Build Coastguard Worker		// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
163*333d2b36SAndroid Build Coastguard Worker		Profile proptools.Configurable[string] `android:"path,replace_instead_of_append"`
164*333d2b36SAndroid Build Coastguard Worker
165*333d2b36SAndroid Build Coastguard Worker		// If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
166*333d2b36SAndroid Build Coastguard Worker		// the optimized dex.
167*333d2b36SAndroid Build Coastguard Worker		// The new profile will be subsequently used as the profile to dexpreopt the dex file.
168*333d2b36SAndroid Build Coastguard Worker		Enable_profile_rewriting proptools.Configurable[bool] `android:"replace_instead_of_append"`
169*333d2b36SAndroid Build Coastguard Worker	}
170*333d2b36SAndroid Build Coastguard Worker
171*333d2b36SAndroid Build Coastguard Worker	Dex_preopt_result struct {
172*333d2b36SAndroid Build Coastguard Worker		// True if profile-guided optimization is actually enabled.
173*333d2b36SAndroid Build Coastguard Worker		Profile_guided bool
174*333d2b36SAndroid Build Coastguard Worker	} `blueprint:"mutated"`
175*333d2b36SAndroid Build Coastguard Worker}
176*333d2b36SAndroid Build Coastguard Worker
177*333d2b36SAndroid Build Coastguard Workertype ImportDexpreoptProperties struct {
178*333d2b36SAndroid Build Coastguard Worker	Dex_preopt struct {
179*333d2b36SAndroid Build Coastguard Worker		// If true, use the profile in the prebuilt APEX to guide optimization. Defaults to false.
180*333d2b36SAndroid Build Coastguard Worker		Profile_guided *bool
181*333d2b36SAndroid Build Coastguard Worker	}
182*333d2b36SAndroid Build Coastguard Worker}
183*333d2b36SAndroid Build Coastguard Worker
184*333d2b36SAndroid Build Coastguard Workerfunc init() {
185*333d2b36SAndroid Build Coastguard Worker	dexpreopt.DexpreoptRunningInSoong = true
186*333d2b36SAndroid Build Coastguard Worker}
187*333d2b36SAndroid Build Coastguard Worker
188*333d2b36SAndroid Build Coastguard Workerfunc isApexVariant(ctx android.BaseModuleContext) bool {
189*333d2b36SAndroid Build Coastguard Worker	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
190*333d2b36SAndroid Build Coastguard Worker	return !apexInfo.IsForPlatform()
191*333d2b36SAndroid Build Coastguard Worker}
192*333d2b36SAndroid Build Coastguard Worker
193*333d2b36SAndroid Build Coastguard Workerfunc forPrebuiltApex(ctx android.BaseModuleContext) bool {
194*333d2b36SAndroid Build Coastguard Worker	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
195*333d2b36SAndroid Build Coastguard Worker	return apexInfo.ForPrebuiltApex
196*333d2b36SAndroid Build Coastguard Worker}
197*333d2b36SAndroid Build Coastguard Worker
198*333d2b36SAndroid Build Coastguard Worker// For apex variant of modules, this returns true on the source variant if the prebuilt apex
199*333d2b36SAndroid Build Coastguard Worker// has been selected using apex_contributions.
200*333d2b36SAndroid Build Coastguard Worker// The prebuilt apex will be responsible for generating the dexpreopt rules of the deapexed java lib.
201*333d2b36SAndroid Build Coastguard Workerfunc disableSourceApexVariant(ctx android.BaseModuleContext) bool {
202*333d2b36SAndroid Build Coastguard Worker	if !isApexVariant(ctx) {
203*333d2b36SAndroid Build Coastguard Worker		return false // platform variant
204*333d2b36SAndroid Build Coastguard Worker	}
205*333d2b36SAndroid Build Coastguard Worker	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
206*333d2b36SAndroid Build Coastguard Worker	psi := android.PrebuiltSelectionInfoMap{}
207*333d2b36SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(am android.Module) {
208*333d2b36SAndroid Build Coastguard Worker		if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok {
209*333d2b36SAndroid Build Coastguard Worker			psi = prebuiltSelectionInfo
210*333d2b36SAndroid Build Coastguard Worker		}
211*333d2b36SAndroid Build Coastguard Worker	})
212*333d2b36SAndroid Build Coastguard Worker
213*333d2b36SAndroid Build Coastguard Worker	// Find the apex variant for this module
214*333d2b36SAndroid Build Coastguard Worker	apexVariantsWithoutTestApexes := []string{}
215*333d2b36SAndroid Build Coastguard Worker	if apexInfo.BaseApexName != "" {
216*333d2b36SAndroid Build Coastguard Worker		// This is a transitive dependency of an override_apex
217*333d2b36SAndroid Build Coastguard Worker		apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.BaseApexName)
218*333d2b36SAndroid Build Coastguard Worker	} else {
219*333d2b36SAndroid Build Coastguard Worker		_, variants, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
220*333d2b36SAndroid Build Coastguard Worker		apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, variants...)
221*333d2b36SAndroid Build Coastguard Worker	}
222*333d2b36SAndroid Build Coastguard Worker	if apexInfo.ApexAvailableName != "" {
223*333d2b36SAndroid Build Coastguard Worker		apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.ApexAvailableName)
224*333d2b36SAndroid Build Coastguard Worker	}
225*333d2b36SAndroid Build Coastguard Worker	disableSource := false
226*333d2b36SAndroid Build Coastguard Worker	// find the selected apexes
227*333d2b36SAndroid Build Coastguard Worker	for _, apexVariant := range apexVariantsWithoutTestApexes {
228*333d2b36SAndroid Build Coastguard Worker		if len(psi.GetSelectedModulesForApiDomain(apexVariant)) > 0 {
229*333d2b36SAndroid Build Coastguard Worker			// If the apex_contribution for this api domain is non-empty, disable the source variant
230*333d2b36SAndroid Build Coastguard Worker			disableSource = true
231*333d2b36SAndroid Build Coastguard Worker		}
232*333d2b36SAndroid Build Coastguard Worker	}
233*333d2b36SAndroid Build Coastguard Worker	return disableSource
234*333d2b36SAndroid Build Coastguard Worker}
235*333d2b36SAndroid Build Coastguard Worker
236*333d2b36SAndroid Build Coastguard Worker// Returns whether dexpreopt is applicable to the module.
237*333d2b36SAndroid Build Coastguard Worker// When it returns true, neither profile nor dexpreopt artifacts will be generated.
238*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName string) bool {
239*333d2b36SAndroid Build Coastguard Worker	if !ctx.Device() {
240*333d2b36SAndroid Build Coastguard Worker		return true
241*333d2b36SAndroid Build Coastguard Worker	}
242*333d2b36SAndroid Build Coastguard Worker
243*333d2b36SAndroid Build Coastguard Worker	if d.isTest {
244*333d2b36SAndroid Build Coastguard Worker		return true
245*333d2b36SAndroid Build Coastguard Worker	}
246*333d2b36SAndroid Build Coastguard Worker
247*333d2b36SAndroid Build Coastguard Worker	if !d.dexpreoptProperties.Dex_preopt.Enabled.GetOrDefault(ctx, true) {
248*333d2b36SAndroid Build Coastguard Worker		return true
249*333d2b36SAndroid Build Coastguard Worker	}
250*333d2b36SAndroid Build Coastguard Worker
251*333d2b36SAndroid Build Coastguard Worker	if d.shouldDisableDexpreopt {
252*333d2b36SAndroid Build Coastguard Worker		return true
253*333d2b36SAndroid Build Coastguard Worker	}
254*333d2b36SAndroid Build Coastguard Worker
255*333d2b36SAndroid Build Coastguard Worker	// If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be
256*333d2b36SAndroid Build Coastguard Worker	// dexpreopted.
257*333d2b36SAndroid Build Coastguard Worker	if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) {
258*333d2b36SAndroid Build Coastguard Worker		return true
259*333d2b36SAndroid Build Coastguard Worker	}
260*333d2b36SAndroid Build Coastguard Worker
261*333d2b36SAndroid Build Coastguard Worker	if !android.IsModulePreferred(ctx.Module()) {
262*333d2b36SAndroid Build Coastguard Worker		return true
263*333d2b36SAndroid Build Coastguard Worker	}
264*333d2b36SAndroid Build Coastguard Worker
265*333d2b36SAndroid Build Coastguard Worker	if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex {
266*333d2b36SAndroid Build Coastguard Worker		// dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
267*333d2b36SAndroid Build Coastguard Worker		return false
268*333d2b36SAndroid Build Coastguard Worker	}
269*333d2b36SAndroid Build Coastguard Worker
270*333d2b36SAndroid Build Coastguard Worker	global := dexpreopt.GetGlobalConfig(ctx)
271*333d2b36SAndroid Build Coastguard Worker
272*333d2b36SAndroid Build Coastguard Worker	// Use the libName argument to determine if the library being dexpreopt'd is a system server jar
273*333d2b36SAndroid Build Coastguard Worker	// ctx.ModuleName() is not safe. In case of prebuilt apexes, the dexpreopt rules of system server jars
274*333d2b36SAndroid Build Coastguard Worker	// are created in the ctx object of the top-level prebuilt apex.
275*333d2b36SAndroid Build Coastguard Worker	isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(libName)
276*333d2b36SAndroid Build Coastguard Worker
277*333d2b36SAndroid Build Coastguard Worker	if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex || isApexVariant(ctx) {
278*333d2b36SAndroid Build Coastguard Worker		// dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
279*333d2b36SAndroid Build Coastguard Worker		if !isApexSystemServerJar {
280*333d2b36SAndroid Build Coastguard Worker			return true
281*333d2b36SAndroid Build Coastguard Worker		}
282*333d2b36SAndroid Build Coastguard Worker		ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
283*333d2b36SAndroid Build Coastguard Worker		allApexInfos := []android.ApexInfo{}
284*333d2b36SAndroid Build Coastguard Worker		if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok {
285*333d2b36SAndroid Build Coastguard Worker			allApexInfos = allApexInfosProvider.ApexInfos
286*333d2b36SAndroid Build Coastguard Worker		}
287*333d2b36SAndroid Build Coastguard Worker		if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) {
288*333d2b36SAndroid Build Coastguard Worker			// Apex system server jars are dexpreopted and installed on to the system image.
289*333d2b36SAndroid Build Coastguard Worker			// Since we can have BigAndroid and Go variants of system server jar providing apexes,
290*333d2b36SAndroid Build Coastguard Worker			// and these two variants can have different min_sdk_versions, hide one of the apex variants
291*333d2b36SAndroid Build Coastguard Worker			// from make to prevent collisions.
292*333d2b36SAndroid Build Coastguard Worker			//
293*333d2b36SAndroid Build Coastguard Worker			// Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries.
294*333d2b36SAndroid Build Coastguard Worker			ctx.Module().MakeUninstallable()
295*333d2b36SAndroid Build Coastguard Worker		}
296*333d2b36SAndroid Build Coastguard Worker	} else {
297*333d2b36SAndroid Build Coastguard Worker		// Don't preopt the platform variant of an APEX system server jar to avoid conflicts.
298*333d2b36SAndroid Build Coastguard Worker		if isApexSystemServerJar {
299*333d2b36SAndroid Build Coastguard Worker			return true
300*333d2b36SAndroid Build Coastguard Worker		}
301*333d2b36SAndroid Build Coastguard Worker	}
302*333d2b36SAndroid Build Coastguard Worker
303*333d2b36SAndroid Build Coastguard Worker	// TODO: contains no java code
304*333d2b36SAndroid Build Coastguard Worker
305*333d2b36SAndroid Build Coastguard Worker	return false
306*333d2b36SAndroid Build Coastguard Worker}
307*333d2b36SAndroid Build Coastguard Worker
308*333d2b36SAndroid Build Coastguard Workerfunc dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
309*333d2b36SAndroid Build Coastguard Worker	if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex && dexpreopt.IsDex2oatNeeded(ctx) {
310*333d2b36SAndroid Build Coastguard Worker		// prebuilt apexes can genererate rules to dexpreopt deapexed jars
311*333d2b36SAndroid Build Coastguard Worker		// Add a dex2oat dep aggressively on _every_ apex module
312*333d2b36SAndroid Build Coastguard Worker		dexpreopt.RegisterToolDeps(ctx)
313*333d2b36SAndroid Build Coastguard Worker		return
314*333d2b36SAndroid Build Coastguard Worker	}
315*333d2b36SAndroid Build Coastguard Worker	if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())) || !dexpreopt.IsDex2oatNeeded(ctx) {
316*333d2b36SAndroid Build Coastguard Worker		return
317*333d2b36SAndroid Build Coastguard Worker	}
318*333d2b36SAndroid Build Coastguard Worker	dexpreopt.RegisterToolDeps(ctx)
319*333d2b36SAndroid Build Coastguard Worker}
320*333d2b36SAndroid Build Coastguard Worker
321*333d2b36SAndroid Build Coastguard Worker// Returns the install path of the dex jar of a module.
322*333d2b36SAndroid Build Coastguard Worker//
323*333d2b36SAndroid Build Coastguard Worker// Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather
324*333d2b36SAndroid Build Coastguard Worker// than the `name` in the path `/apex/<name>` as suggested in its comment.
325*333d2b36SAndroid Build Coastguard Worker//
326*333d2b36SAndroid Build Coastguard Worker// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a
327*333d2b36SAndroid Build Coastguard Worker// system server jar, which is fine because we currently only preopt system server jars for APEXes.
328*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) getInstallPath(
329*333d2b36SAndroid Build Coastguard Worker	ctx android.ModuleContext, libName string, defaultInstallPath android.InstallPath) android.InstallPath {
330*333d2b36SAndroid Build Coastguard Worker	global := dexpreopt.GetGlobalConfig(ctx)
331*333d2b36SAndroid Build Coastguard Worker	if global.AllApexSystemServerJars(ctx).ContainsJar(libName) {
332*333d2b36SAndroid Build Coastguard Worker		dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, libName)
333*333d2b36SAndroid Build Coastguard Worker		return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/"))
334*333d2b36SAndroid Build Coastguard Worker	}
335*333d2b36SAndroid Build Coastguard Worker	if !d.dexpreoptDisabled(ctx, libName) && isApexVariant(ctx) &&
336*333d2b36SAndroid Build Coastguard Worker		filepath.Base(defaultInstallPath.PartitionDir()) != "apex" {
337*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt")
338*333d2b36SAndroid Build Coastguard Worker	}
339*333d2b36SAndroid Build Coastguard Worker	return defaultInstallPath
340*333d2b36SAndroid Build Coastguard Worker}
341*333d2b36SAndroid Build Coastguard Worker
342*333d2b36SAndroid Build Coastguard Worker// DexpreoptPrebuiltApexSystemServerJars generates the dexpreopt artifacts from a jar file that has been deapexed from a prebuilt apex
343*333d2b36SAndroid Build Coastguard Workerfunc (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleContext, libraryName string, di *android.DeapexerInfo) {
344*333d2b36SAndroid Build Coastguard Worker	// A single prebuilt apex can have multiple apex system jars
345*333d2b36SAndroid Build Coastguard Worker	// initialize the output path for this dex jar
346*333d2b36SAndroid Build Coastguard Worker	dc := dexpreopt.GetGlobalConfig(ctx)
347*333d2b36SAndroid Build Coastguard Worker	d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
348*333d2b36SAndroid Build Coastguard Worker	// generate the rules for creating the .odex and .vdex files for this system server jar
349*333d2b36SAndroid Build Coastguard Worker	dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
350*333d2b36SAndroid Build Coastguard Worker
351*333d2b36SAndroid Build Coastguard Worker	d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
352*333d2b36SAndroid Build Coastguard Worker	if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
353*333d2b36SAndroid Build Coastguard Worker		// Set the profile path to guide optimization
354*333d2b36SAndroid Build Coastguard Worker		prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof")
355*333d2b36SAndroid Build Coastguard Worker		if prof == nil {
356*333d2b36SAndroid Build Coastguard Worker			ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex")
357*333d2b36SAndroid Build Coastguard Worker		}
358*333d2b36SAndroid Build Coastguard Worker		d.inputProfilePathOnHost = prof
359*333d2b36SAndroid Build Coastguard Worker	}
360*333d2b36SAndroid Build Coastguard Worker
361*333d2b36SAndroid Build Coastguard Worker	d.dexpreopt(ctx, libraryName, dexJarFile)
362*333d2b36SAndroid Build Coastguard Worker}
363*333d2b36SAndroid Build Coastguard Worker
364*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.Path) {
365*333d2b36SAndroid Build Coastguard Worker	global := dexpreopt.GetGlobalConfig(ctx)
366*333d2b36SAndroid Build Coastguard Worker
367*333d2b36SAndroid Build Coastguard Worker	// TODO(b/148690468): The check on d.installPath is to bail out in cases where
368*333d2b36SAndroid Build Coastguard Worker	// the dexpreopter struct hasn't been fully initialized before we're called,
369*333d2b36SAndroid Build Coastguard Worker	// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
370*333d2b36SAndroid Build Coastguard Worker	// disabled, even if installable is true.
371*333d2b36SAndroid Build Coastguard Worker	if d.installPath.Base() == "." {
372*333d2b36SAndroid Build Coastguard Worker		return
373*333d2b36SAndroid Build Coastguard Worker	}
374*333d2b36SAndroid Build Coastguard Worker
375*333d2b36SAndroid Build Coastguard Worker	dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
376*333d2b36SAndroid Build Coastguard Worker
377*333d2b36SAndroid Build Coastguard Worker	providesUsesLib := libName
378*333d2b36SAndroid Build Coastguard Worker	if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
379*333d2b36SAndroid Build Coastguard Worker		name := ulib.ProvidesUsesLib()
380*333d2b36SAndroid Build Coastguard Worker		if name != nil {
381*333d2b36SAndroid Build Coastguard Worker			providesUsesLib = *name
382*333d2b36SAndroid Build Coastguard Worker		}
383*333d2b36SAndroid Build Coastguard Worker	}
384*333d2b36SAndroid Build Coastguard Worker
385*333d2b36SAndroid Build Coastguard Worker	// If it is test, make config files regardless of its dexpreopt setting.
386*333d2b36SAndroid Build Coastguard Worker	// The config files are required for apps defined in make which depend on the lib.
387*333d2b36SAndroid Build Coastguard Worker	if d.isTest && d.dexpreoptDisabled(ctx, libName) {
388*333d2b36SAndroid Build Coastguard Worker		return
389*333d2b36SAndroid Build Coastguard Worker	}
390*333d2b36SAndroid Build Coastguard Worker
391*333d2b36SAndroid Build Coastguard Worker	isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(libName)
392*333d2b36SAndroid Build Coastguard Worker
393*333d2b36SAndroid Build Coastguard Worker	bootImage := defaultBootImageConfig(ctx)
394*333d2b36SAndroid Build Coastguard Worker	// When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline
395*333d2b36SAndroid Build Coastguard Worker	// boot jars into bootclasspath, so we should include the mainline boot image as well because it's
396*333d2b36SAndroid Build Coastguard Worker	// generated from those jars.
397*333d2b36SAndroid Build Coastguard Worker	if global.PreoptWithUpdatableBcp {
398*333d2b36SAndroid Build Coastguard Worker		bootImage = mainlineBootImageConfig(ctx)
399*333d2b36SAndroid Build Coastguard Worker	}
400*333d2b36SAndroid Build Coastguard Worker	dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
401*333d2b36SAndroid Build Coastguard Worker
402*333d2b36SAndroid Build Coastguard Worker	targets := ctx.MultiTargets()
403*333d2b36SAndroid Build Coastguard Worker	if len(targets) == 0 {
404*333d2b36SAndroid Build Coastguard Worker		// assume this is a java library, dexpreopt for all arches for now
405*333d2b36SAndroid Build Coastguard Worker		for _, target := range ctx.Config().Targets[android.Android] {
406*333d2b36SAndroid Build Coastguard Worker			if target.NativeBridge == android.NativeBridgeDisabled {
407*333d2b36SAndroid Build Coastguard Worker				targets = append(targets, target)
408*333d2b36SAndroid Build Coastguard Worker			}
409*333d2b36SAndroid Build Coastguard Worker		}
410*333d2b36SAndroid Build Coastguard Worker		if isSystemServerJar && libName != "com.android.location.provider" {
411*333d2b36SAndroid Build Coastguard Worker			// If the module is a system server jar, only preopt for the primary arch because the jar can
412*333d2b36SAndroid Build Coastguard Worker			// only be loaded by system server. "com.android.location.provider" is a special case because
413*333d2b36SAndroid Build Coastguard Worker			// it's also used by apps as a shared library.
414*333d2b36SAndroid Build Coastguard Worker			targets = targets[:1]
415*333d2b36SAndroid Build Coastguard Worker		}
416*333d2b36SAndroid Build Coastguard Worker	}
417*333d2b36SAndroid Build Coastguard Worker
418*333d2b36SAndroid Build Coastguard Worker	var archs []android.ArchType
419*333d2b36SAndroid Build Coastguard Worker	var images android.Paths
420*333d2b36SAndroid Build Coastguard Worker	var imagesDeps []android.OutputPaths
421*333d2b36SAndroid Build Coastguard Worker	for _, target := range targets {
422*333d2b36SAndroid Build Coastguard Worker		archs = append(archs, target.Arch.ArchType)
423*333d2b36SAndroid Build Coastguard Worker		variant := bootImage.getVariant(target)
424*333d2b36SAndroid Build Coastguard Worker		images = append(images, variant.imagePathOnHost)
425*333d2b36SAndroid Build Coastguard Worker		imagesDeps = append(imagesDeps, variant.imagesDeps)
426*333d2b36SAndroid Build Coastguard Worker	}
427*333d2b36SAndroid Build Coastguard Worker	// The image locations for all Android variants are identical.
428*333d2b36SAndroid Build Coastguard Worker	hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
429*333d2b36SAndroid Build Coastguard Worker
430*333d2b36SAndroid Build Coastguard Worker	var profileClassListing android.OptionalPath
431*333d2b36SAndroid Build Coastguard Worker	var profileBootListing android.OptionalPath
432*333d2b36SAndroid Build Coastguard Worker	profileIsTextListing := false
433*333d2b36SAndroid Build Coastguard Worker
434*333d2b36SAndroid Build Coastguard Worker	if d.inputProfilePathOnHost != nil {
435*333d2b36SAndroid Build Coastguard Worker		profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
436*333d2b36SAndroid Build Coastguard Worker	} else if d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, true) && !forPrebuiltApex(ctx) {
437*333d2b36SAndroid Build Coastguard Worker		// If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
438*333d2b36SAndroid Build Coastguard Worker		if d.EnableProfileRewriting(ctx) {
439*333d2b36SAndroid Build Coastguard Worker			profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
440*333d2b36SAndroid Build Coastguard Worker			profileIsTextListing = true
441*333d2b36SAndroid Build Coastguard Worker		} else if profile := d.GetProfile(ctx); profile != "" {
442*333d2b36SAndroid Build Coastguard Worker			// If dex_preopt.profile_guided is not set, default it based on the existence of the
443*333d2b36SAndroid Build Coastguard Worker			// dexprepot.profile option or the profile class listing.
444*333d2b36SAndroid Build Coastguard Worker			profileClassListing = android.OptionalPathForPath(
445*333d2b36SAndroid Build Coastguard Worker				android.PathForModuleSrc(ctx, profile))
446*333d2b36SAndroid Build Coastguard Worker			profileBootListing = android.ExistentPathForSource(ctx,
447*333d2b36SAndroid Build Coastguard Worker				ctx.ModuleDir(), profile+"-boot")
448*333d2b36SAndroid Build Coastguard Worker			profileIsTextListing = true
449*333d2b36SAndroid Build Coastguard Worker		} else if global.ProfileDir != "" {
450*333d2b36SAndroid Build Coastguard Worker			profileClassListing = android.ExistentPathForSource(ctx,
451*333d2b36SAndroid Build Coastguard Worker				global.ProfileDir, libName+".prof")
452*333d2b36SAndroid Build Coastguard Worker		}
453*333d2b36SAndroid Build Coastguard Worker	}
454*333d2b36SAndroid Build Coastguard Worker
455*333d2b36SAndroid Build Coastguard Worker	d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid()
456*333d2b36SAndroid Build Coastguard Worker
457*333d2b36SAndroid Build Coastguard Worker	// A single apex can have multiple system server jars
458*333d2b36SAndroid Build Coastguard Worker	// Use the dexJar to create a unique scope for each
459*333d2b36SAndroid Build Coastguard Worker	dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
460*333d2b36SAndroid Build Coastguard Worker
461*333d2b36SAndroid Build Coastguard Worker	appImage := d.dexpreoptProperties.Dex_preopt.App_image.Get(ctx)
462*333d2b36SAndroid Build Coastguard Worker
463*333d2b36SAndroid Build Coastguard Worker	// Full dexpreopt config, used to create dexpreopt build rules.
464*333d2b36SAndroid Build Coastguard Worker	dexpreoptConfig := &dexpreopt.ModuleConfig{
465*333d2b36SAndroid Build Coastguard Worker		Name:            libName,
466*333d2b36SAndroid Build Coastguard Worker		DexLocation:     dexLocation,
467*333d2b36SAndroid Build Coastguard Worker		BuildPath:       android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, libName+".jar").OutputPath,
468*333d2b36SAndroid Build Coastguard Worker		DexPath:         dexJarFile,
469*333d2b36SAndroid Build Coastguard Worker		ManifestPath:    android.OptionalPathForPath(d.manifestFile),
470*333d2b36SAndroid Build Coastguard Worker		UncompressedDex: d.uncompressedDex,
471*333d2b36SAndroid Build Coastguard Worker		HasApkLibraries: false,
472*333d2b36SAndroid Build Coastguard Worker		PreoptFlags:     nil,
473*333d2b36SAndroid Build Coastguard Worker
474*333d2b36SAndroid Build Coastguard Worker		ProfileClassListing:  profileClassListing,
475*333d2b36SAndroid Build Coastguard Worker		ProfileIsTextListing: profileIsTextListing,
476*333d2b36SAndroid Build Coastguard Worker		ProfileBootListing:   profileBootListing,
477*333d2b36SAndroid Build Coastguard Worker
478*333d2b36SAndroid Build Coastguard Worker		EnforceUsesLibrariesStatusFile: dexpreopt.UsesLibrariesStatusFile(ctx),
479*333d2b36SAndroid Build Coastguard Worker		EnforceUsesLibraries:           d.enforceUsesLibs,
480*333d2b36SAndroid Build Coastguard Worker		ProvidesUsesLibrary:            providesUsesLib,
481*333d2b36SAndroid Build Coastguard Worker		ClassLoaderContexts:            d.classLoaderContexts,
482*333d2b36SAndroid Build Coastguard Worker
483*333d2b36SAndroid Build Coastguard Worker		Archs:                           archs,
484*333d2b36SAndroid Build Coastguard Worker		DexPreoptImagesDeps:             imagesDeps,
485*333d2b36SAndroid Build Coastguard Worker		DexPreoptImageLocationsOnHost:   hostImageLocations,
486*333d2b36SAndroid Build Coastguard Worker		DexPreoptImageLocationsOnDevice: deviceImageLocations,
487*333d2b36SAndroid Build Coastguard Worker
488*333d2b36SAndroid Build Coastguard Worker		PreoptBootClassPathDexFiles:     dexFiles.Paths(),
489*333d2b36SAndroid Build Coastguard Worker		PreoptBootClassPathDexLocations: dexLocations,
490*333d2b36SAndroid Build Coastguard Worker
491*333d2b36SAndroid Build Coastguard Worker		NoCreateAppImage:    !appImage.GetOrDefault(true),
492*333d2b36SAndroid Build Coastguard Worker		ForceCreateAppImage: appImage.GetOrDefault(false),
493*333d2b36SAndroid Build Coastguard Worker
494*333d2b36SAndroid Build Coastguard Worker		PresignedPrebuilt: d.isPresignedPrebuilt,
495*333d2b36SAndroid Build Coastguard Worker	}
496*333d2b36SAndroid Build Coastguard Worker
497*333d2b36SAndroid Build Coastguard Worker	if ctx.Config().InstallApexSystemServerDexpreoptSamePartition() {
498*333d2b36SAndroid Build Coastguard Worker		dexpreoptConfig.ApexPartition = android.PathForModuleInstall(ctx).Partition()
499*333d2b36SAndroid Build Coastguard Worker	} else {
500*333d2b36SAndroid Build Coastguard Worker		dexpreoptConfig.ApexPartition = "system"
501*333d2b36SAndroid Build Coastguard Worker	}
502*333d2b36SAndroid Build Coastguard Worker
503*333d2b36SAndroid Build Coastguard Worker	d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config")
504*333d2b36SAndroid Build Coastguard Worker	dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
505*333d2b36SAndroid Build Coastguard Worker	ctx.CheckbuildFile(d.configPath)
506*333d2b36SAndroid Build Coastguard Worker
507*333d2b36SAndroid Build Coastguard Worker	if d.dexpreoptDisabled(ctx, libName) {
508*333d2b36SAndroid Build Coastguard Worker		return
509*333d2b36SAndroid Build Coastguard Worker	}
510*333d2b36SAndroid Build Coastguard Worker
511*333d2b36SAndroid Build Coastguard Worker	globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
512*333d2b36SAndroid Build Coastguard Worker
513*333d2b36SAndroid Build Coastguard Worker	// The root "product_packages.txt" is generated by `build/make/core/Makefile`. It contains a list
514*333d2b36SAndroid Build Coastguard Worker	// of all packages that are installed on the device. We use `grep` to filter the list by the app's
515*333d2b36SAndroid Build Coastguard Worker	// dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
516*333d2b36SAndroid Build Coastguard Worker	// from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
517*333d2b36SAndroid Build Coastguard Worker	productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt")
518*333d2b36SAndroid Build Coastguard Worker	appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "product_packages.txt")
519*333d2b36SAndroid Build Coastguard Worker	appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp")
520*333d2b36SAndroid Build Coastguard Worker	clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts)
521*333d2b36SAndroid Build Coastguard Worker	sort.Strings(clcNames) // The order needs to be deterministic.
522*333d2b36SAndroid Build Coastguard Worker	productPackagesRule := android.NewRuleBuilder(pctx, ctx)
523*333d2b36SAndroid Build Coastguard Worker	if len(clcNames) > 0 {
524*333d2b36SAndroid Build Coastguard Worker		productPackagesRule.Command().
525*333d2b36SAndroid Build Coastguard Worker			Text("grep -F -x").
526*333d2b36SAndroid Build Coastguard Worker			FlagForEachArg("-e ", clcNames).
527*333d2b36SAndroid Build Coastguard Worker			Input(productPackages).
528*333d2b36SAndroid Build Coastguard Worker			FlagWithOutput("> ", appProductPackagesStaging).
529*333d2b36SAndroid Build Coastguard Worker			Text("|| true")
530*333d2b36SAndroid Build Coastguard Worker	} else {
531*333d2b36SAndroid Build Coastguard Worker		productPackagesRule.Command().
532*333d2b36SAndroid Build Coastguard Worker			Text("rm -f").Output(appProductPackagesStaging).
533*333d2b36SAndroid Build Coastguard Worker			Text("&&").
534*333d2b36SAndroid Build Coastguard Worker			Text("touch").Output(appProductPackagesStaging)
535*333d2b36SAndroid Build Coastguard Worker	}
536*333d2b36SAndroid Build Coastguard Worker	productPackagesRule.Command().
537*333d2b36SAndroid Build Coastguard Worker		Text("rsync --checksum").
538*333d2b36SAndroid Build Coastguard Worker		Input(appProductPackagesStaging).
539*333d2b36SAndroid Build Coastguard Worker		Output(appProductPackages)
540*333d2b36SAndroid Build Coastguard Worker	productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages")
541*333d2b36SAndroid Build Coastguard Worker
542*333d2b36SAndroid Build Coastguard Worker	// Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars
543*333d2b36SAndroid Build Coastguard Worker	// The javalib from the deapexed prebuilt will be copied to this location.
544*333d2b36SAndroid Build Coastguard Worker	// TODO (b/331665856): Implement a principled solution for this.
545*333d2b36SAndroid Build Coastguard Worker	copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake()
546*333d2b36SAndroid Build Coastguard Worker	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
547*333d2b36SAndroid Build Coastguard Worker		ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex)
548*333d2b36SAndroid Build Coastguard Worker	if err != nil {
549*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
550*333d2b36SAndroid Build Coastguard Worker		return
551*333d2b36SAndroid Build Coastguard Worker	}
552*333d2b36SAndroid Build Coastguard Worker
553*333d2b36SAndroid Build Coastguard Worker	dexpreoptRule.Build("dexpreopt"+"."+dexJarStem, "dexpreopt")
554*333d2b36SAndroid Build Coastguard Worker
555*333d2b36SAndroid Build Coastguard Worker	// The current ctx might be of a deapexer module created by a prebuilt apex
556*333d2b36SAndroid Build Coastguard Worker	// Use the path of the dex file to determine the library name
557*333d2b36SAndroid Build Coastguard Worker	isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(dexJarStem)
558*333d2b36SAndroid Build Coastguard Worker
559*333d2b36SAndroid Build Coastguard Worker	dexpreoptPartition := d.installPath.Partition()
560*333d2b36SAndroid Build Coastguard Worker	// dexpreoptPartition is set to empty for dexpreopts of system APEX and system_other.
561*333d2b36SAndroid Build Coastguard Worker	// In case of system APEX, however, we can set it to "system" manually.
562*333d2b36SAndroid Build Coastguard Worker	// TODO(b/346662300): Let dexpreopter generate the installPath for dexpreopt files instead of
563*333d2b36SAndroid Build Coastguard Worker	// using the dex location to generate the installPath.
564*333d2b36SAndroid Build Coastguard Worker	if isApexSystemServerJar {
565*333d2b36SAndroid Build Coastguard Worker		dexpreoptPartition = dexpreoptConfig.ApexPartition
566*333d2b36SAndroid Build Coastguard Worker	}
567*333d2b36SAndroid Build Coastguard Worker	for _, install := range dexpreoptRule.Installs() {
568*333d2b36SAndroid Build Coastguard Worker		// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
569*333d2b36SAndroid Build Coastguard Worker		installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
570*333d2b36SAndroid Build Coastguard Worker		partition := dexpreoptPartition
571*333d2b36SAndroid Build Coastguard Worker		if strings.HasPrefix(installDir, partition+"/") {
572*333d2b36SAndroid Build Coastguard Worker			installDir = strings.TrimPrefix(installDir, partition+"/")
573*333d2b36SAndroid Build Coastguard Worker		} else {
574*333d2b36SAndroid Build Coastguard Worker			// If the partition for the installDir is different from the install partition, set the
575*333d2b36SAndroid Build Coastguard Worker			// partition empty to install the dexpreopt files to the desired partition.
576*333d2b36SAndroid Build Coastguard Worker			// TODO(b/346439786): Define and use the dexpreopt module type to avoid this mismatch.
577*333d2b36SAndroid Build Coastguard Worker			partition = ""
578*333d2b36SAndroid Build Coastguard Worker		}
579*333d2b36SAndroid Build Coastguard Worker		installBase := filepath.Base(install.To)
580*333d2b36SAndroid Build Coastguard Worker		arch := filepath.Base(installDir)
581*333d2b36SAndroid Build Coastguard Worker		installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir)
582*333d2b36SAndroid Build Coastguard Worker		isProfile := strings.HasSuffix(installBase, ".prof")
583*333d2b36SAndroid Build Coastguard Worker
584*333d2b36SAndroid Build Coastguard Worker		if isProfile {
585*333d2b36SAndroid Build Coastguard Worker			d.outputProfilePathOnHost = install.From
586*333d2b36SAndroid Build Coastguard Worker		}
587*333d2b36SAndroid Build Coastguard Worker
588*333d2b36SAndroid Build Coastguard Worker		if isApexSystemServerJar {
589*333d2b36SAndroid Build Coastguard Worker			// Profiles are handled separately because they are installed into the APEX.
590*333d2b36SAndroid Build Coastguard Worker			if !isProfile {
591*333d2b36SAndroid Build Coastguard Worker				// APEX variants of java libraries are hidden from Make, so their dexpreopt
592*333d2b36SAndroid Build Coastguard Worker				// outputs need special handling. Currently, for APEX variants of java
593*333d2b36SAndroid Build Coastguard Worker				// libraries, only those in the system server classpath are handled here.
594*333d2b36SAndroid Build Coastguard Worker				// Preopting of boot classpath jars in the ART APEX are handled in
595*333d2b36SAndroid Build Coastguard Worker				// java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
596*333d2b36SAndroid Build Coastguard Worker				// The installs will be handled by Make as sub-modules of the java library.
597*333d2b36SAndroid Build Coastguard Worker				di := dexpreopterInstall{
598*333d2b36SAndroid Build Coastguard Worker					name:                arch + "-" + installBase,
599*333d2b36SAndroid Build Coastguard Worker					moduleName:          libName,
600*333d2b36SAndroid Build Coastguard Worker					outputPathOnHost:    install.From,
601*333d2b36SAndroid Build Coastguard Worker					installDirOnDevice:  installPath,
602*333d2b36SAndroid Build Coastguard Worker					installFileOnDevice: installBase,
603*333d2b36SAndroid Build Coastguard Worker				}
604*333d2b36SAndroid Build Coastguard Worker				ctx.InstallFile(di.installDirOnDevice, di.installFileOnDevice, di.outputPathOnHost)
605*333d2b36SAndroid Build Coastguard Worker				d.builtInstalledForApex = append(d.builtInstalledForApex, di)
606*333d2b36SAndroid Build Coastguard Worker
607*333d2b36SAndroid Build Coastguard Worker			}
608*333d2b36SAndroid Build Coastguard Worker		} else if !d.preventInstall {
609*333d2b36SAndroid Build Coastguard Worker			// Install without adding to checkbuild to match behavior of previous Make-based checkbuild rules
610*333d2b36SAndroid Build Coastguard Worker			ctx.InstallFileWithoutCheckbuild(installPath, installBase, install.From)
611*333d2b36SAndroid Build Coastguard Worker		}
612*333d2b36SAndroid Build Coastguard Worker	}
613*333d2b36SAndroid Build Coastguard Worker
614*333d2b36SAndroid Build Coastguard Worker	if !isApexSystemServerJar {
615*333d2b36SAndroid Build Coastguard Worker		d.builtInstalled = dexpreoptRule.Installs().String()
616*333d2b36SAndroid Build Coastguard Worker	}
617*333d2b36SAndroid Build Coastguard Worker}
618*333d2b36SAndroid Build Coastguard Worker
619*333d2b36SAndroid Build Coastguard Workerfunc getModuleInstallPathInfo(ctx android.ModuleContext, fullInstallPath string) (android.InstallPath, string, string) {
620*333d2b36SAndroid Build Coastguard Worker	installPath := android.PathForModuleInstall(ctx)
621*333d2b36SAndroid Build Coastguard Worker	installDir, installBase := filepath.Split(strings.TrimPrefix(fullInstallPath, "/"))
622*333d2b36SAndroid Build Coastguard Worker
623*333d2b36SAndroid Build Coastguard Worker	if !strings.HasPrefix(installDir, installPath.Partition()+"/") {
624*333d2b36SAndroid Build Coastguard Worker		// Return empty filename if the install partition is not for the target image.
625*333d2b36SAndroid Build Coastguard Worker		return installPath, "", ""
626*333d2b36SAndroid Build Coastguard Worker	}
627*333d2b36SAndroid Build Coastguard Worker	relDir, err := filepath.Rel(installPath.Partition(), installDir)
628*333d2b36SAndroid Build Coastguard Worker	if err != nil {
629*333d2b36SAndroid Build Coastguard Worker		panic(err)
630*333d2b36SAndroid Build Coastguard Worker	}
631*333d2b36SAndroid Build Coastguard Worker	return installPath, relDir, installBase
632*333d2b36SAndroid Build Coastguard Worker}
633*333d2b36SAndroid Build Coastguard Worker
634*333d2b36SAndroid Build Coastguard Worker// installFile will install the file if `install` path and the target install partition are the same.
635*333d2b36SAndroid Build Coastguard Workerfunc installFile(ctx android.ModuleContext, install android.RuleBuilderInstall) {
636*333d2b36SAndroid Build Coastguard Worker	installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
637*333d2b36SAndroid Build Coastguard Worker	// Empty name means the install partition is not for the target image.
638*333d2b36SAndroid Build Coastguard Worker	// For the system image, files for "apex" and "system_other" are skipped here.
639*333d2b36SAndroid Build Coastguard Worker	// The skipped "apex" files are for testing only, for example,
640*333d2b36SAndroid Build Coastguard Worker	// "/apex/art_boot_images/javalib/x86/boot.vdex".
641*333d2b36SAndroid Build Coastguard Worker	// TODO(b/320196894): Files for "system_other" are skipped because soong creates the system
642*333d2b36SAndroid Build Coastguard Worker	// image only for now.
643*333d2b36SAndroid Build Coastguard Worker	if name != "" {
644*333d2b36SAndroid Build Coastguard Worker		ctx.InstallFile(installPath.Join(ctx, relDir), name, install.From)
645*333d2b36SAndroid Build Coastguard Worker	}
646*333d2b36SAndroid Build Coastguard Worker}
647*333d2b36SAndroid Build Coastguard Worker
648*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall {
649*333d2b36SAndroid Build Coastguard Worker	return d.builtInstalledForApex
650*333d2b36SAndroid Build Coastguard Worker}
651*333d2b36SAndroid Build Coastguard Worker
652*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
653*333d2b36SAndroid Build Coastguard Worker	var entries []android.AndroidMkEntries
654*333d2b36SAndroid Build Coastguard Worker	for _, install := range d.builtInstalledForApex {
655*333d2b36SAndroid Build Coastguard Worker		entries = append(entries, install.ToMakeEntries())
656*333d2b36SAndroid Build Coastguard Worker	}
657*333d2b36SAndroid Build Coastguard Worker	return entries
658*333d2b36SAndroid Build Coastguard Worker}
659*333d2b36SAndroid Build Coastguard Worker
660*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) OutputProfilePathOnHost() android.Path {
661*333d2b36SAndroid Build Coastguard Worker	return d.outputProfilePathOnHost
662*333d2b36SAndroid Build Coastguard Worker}
663*333d2b36SAndroid Build Coastguard Worker
664*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) disableDexpreopt() {
665*333d2b36SAndroid Build Coastguard Worker	d.shouldDisableDexpreopt = true
666*333d2b36SAndroid Build Coastguard Worker}
667*333d2b36SAndroid Build Coastguard Worker
668*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) EnableProfileRewriting(ctx android.BaseModuleContext) bool {
669*333d2b36SAndroid Build Coastguard Worker	return d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting.GetOrDefault(ctx, false)
670*333d2b36SAndroid Build Coastguard Worker}
671*333d2b36SAndroid Build Coastguard Worker
672*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) GetProfile(ctx android.BaseModuleContext) string {
673*333d2b36SAndroid Build Coastguard Worker	return d.dexpreoptProperties.Dex_preopt.Profile.GetOrDefault(ctx, "")
674*333d2b36SAndroid Build Coastguard Worker}
675*333d2b36SAndroid Build Coastguard Worker
676*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) GetProfileGuided(ctx android.BaseModuleContext) bool {
677*333d2b36SAndroid Build Coastguard Worker	return d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, false)
678*333d2b36SAndroid Build Coastguard Worker}
679*333d2b36SAndroid Build Coastguard Worker
680*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) GetRewrittenProfile() android.Path {
681*333d2b36SAndroid Build Coastguard Worker	return d.rewrittenProfile
682*333d2b36SAndroid Build Coastguard Worker}
683*333d2b36SAndroid Build Coastguard Worker
684*333d2b36SAndroid Build Coastguard Workerfunc (d *dexpreopter) SetRewrittenProfile(p android.Path) {
685*333d2b36SAndroid Build Coastguard Worker	d.rewrittenProfile = p
686*333d2b36SAndroid Build Coastguard Worker}
687