• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"android/soong/android"
19	"android/soong/dexpreopt"
20)
21
22type dexpreopter struct {
23	dexpreoptProperties DexpreoptProperties
24
25	installPath     android.OutputPath
26	uncompressedDex bool
27	isSDKLibrary    bool
28	isTest          bool
29	isInstallable   bool
30
31	builtInstalled string
32}
33
34type DexpreoptProperties struct {
35	Dex_preopt struct {
36		// If false, prevent dexpreopting and stripping the dex file from the final jar.  Defaults to
37		// true.
38		Enabled *bool
39
40		// If true, never strip the dex files from the final jar when dexpreopting.  Defaults to false.
41		No_stripping *bool
42
43		// If true, generate an app image (.art file) for this module.
44		App_image *bool
45
46		// If true, use a checked-in profile to guide optimization.  Defaults to false unless
47		// a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
48		// that matches the name of this module, in which case it is defaulted to true.
49		Profile_guided *bool
50
51		// If set, provides the path to profile relative to the Android.bp file.  If not set,
52		// defaults to searching for a file that matches the name of this module in the default
53		// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
54		Profile *string
55	}
56}
57
58func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
59	global := dexpreoptGlobalConfig(ctx)
60
61	if global.DisablePreopt {
62		return true
63	}
64
65	if inList(ctx.ModuleName(), global.DisablePreoptModules) {
66		return true
67	}
68
69	if ctx.Config().UnbundledBuild() {
70		return true
71	}
72
73	if d.isTest {
74		return true
75	}
76
77	if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) {
78		return true
79	}
80
81	if !d.isInstallable {
82		return true
83	}
84
85	// TODO: contains no java code
86
87	return false
88}
89
90func odexOnSystemOther(ctx android.ModuleContext, installPath android.OutputPath) bool {
91	return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreoptGlobalConfig(ctx))
92}
93
94func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath {
95	if d.dexpreoptDisabled(ctx) {
96		return dexJarFile
97	}
98
99	global := dexpreoptGlobalConfig(ctx)
100	bootImage := defaultBootImageConfig(ctx)
101	defaultBootImage := bootImage
102	if global.UseApexImage {
103		bootImage = apexBootImageConfig(ctx)
104	}
105
106	var archs []android.ArchType
107	for _, a := range ctx.MultiTargets() {
108		archs = append(archs, a.Arch.ArchType)
109	}
110	if len(archs) == 0 {
111		// assume this is a java library, dexpreopt for all arches for now
112		for _, target := range ctx.Config().Targets[android.Android] {
113			archs = append(archs, target.Arch.ArchType)
114		}
115		if inList(ctx.ModuleName(), global.SystemServerJars) && !d.isSDKLibrary {
116			// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
117			archs = archs[:1]
118		}
119	}
120	if ctx.Config().SecondArchIsTranslated() {
121		// Only preopt primary arch for translated arch since there is only an image there.
122		archs = archs[:1]
123	}
124
125	var images android.Paths
126	for _, arch := range archs {
127		images = append(images, bootImage.images[arch])
128	}
129
130	dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
131
132	strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base())
133
134	var profileClassListing android.OptionalPath
135	profileIsTextListing := false
136	if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) {
137		// If dex_preopt.profile_guided is not set, default it based on the existence of the
138		// dexprepot.profile option or the profile class listing.
139		if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
140			profileClassListing = android.OptionalPathForPath(
141				android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile)))
142			profileIsTextListing = true
143		} else {
144			profileClassListing = android.ExistentPathForSource(ctx,
145				global.ProfileDir, ctx.ModuleName()+".prof")
146		}
147	}
148
149	dexpreoptConfig := dexpreopt.ModuleConfig{
150		Name:            ctx.ModuleName(),
151		DexLocation:     dexLocation,
152		BuildPath:       android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
153		DexPath:         dexJarFile,
154		UncompressedDex: d.uncompressedDex,
155		HasApkLibraries: false,
156		PreoptFlags:     nil,
157
158		ProfileClassListing:  profileClassListing,
159		ProfileIsTextListing: profileIsTextListing,
160
161		EnforceUsesLibraries:  false,
162		OptionalUsesLibraries: nil,
163		UsesLibraries:         nil,
164		LibraryPaths:          nil,
165
166		Archs:           archs,
167		DexPreoptImages: images,
168
169		// We use the dex paths and dex locations of the default boot image, as it
170		// contains the full dexpreopt boot classpath. Other images may just contain a subset of
171		// the dexpreopt boot classpath.
172		PreoptBootClassPathDexFiles:     defaultBootImage.dexPaths.Paths(),
173		PreoptBootClassPathDexLocations: defaultBootImage.dexLocations,
174
175		PreoptExtractedApk: false,
176
177		NoCreateAppImage:    !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
178		ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
179
180		NoStripping:     Bool(d.dexpreoptProperties.Dex_preopt.No_stripping),
181		StripInputPath:  dexJarFile,
182		StripOutputPath: strippedDexJarFile.OutputPath,
183	}
184
185	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, dexpreoptConfig)
186	if err != nil {
187		ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
188		return dexJarFile
189	}
190
191	dexpreoptRule.Build(pctx, ctx, "dexpreopt", "dexpreopt")
192
193	d.builtInstalled = dexpreoptRule.Installs().String()
194
195	stripRule, err := dexpreopt.GenerateStripRule(global, dexpreoptConfig)
196	if err != nil {
197		ctx.ModuleErrorf("error generating dexpreopt strip rule: %s", err.Error())
198		return dexJarFile
199	}
200
201	stripRule.Build(pctx, ctx, "dexpreopt_strip", "dexpreopt strip")
202
203	return strippedDexJarFile
204}
205