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