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 Worker// The dexpreopt package converts a global dexpreopt config and a module dexpreopt config into rules to perform 16*333d2b36SAndroid Build Coastguard Worker// dexpreopting. 17*333d2b36SAndroid Build Coastguard Worker// 18*333d2b36SAndroid Build Coastguard Worker// It is used in two places; in the dexpeopt_gen binary for modules defined in Make, and directly linked into Soong. 19*333d2b36SAndroid Build Coastguard Worker// 20*333d2b36SAndroid Build Coastguard Worker// For Make modules it is built into the dexpreopt_gen binary, which is executed as a Make rule using global config and 21*333d2b36SAndroid Build Coastguard Worker// module config specified in JSON files. The binary writes out two shell scripts, only updating them if they have 22*333d2b36SAndroid Build Coastguard Worker// changed. One script takes an APK or JAR as an input and produces a zip file containing any outputs of preopting, 23*333d2b36SAndroid Build Coastguard Worker// in the location they should be on the device. The Make build rules will unzip the zip file into $(PRODUCT_OUT) when 24*333d2b36SAndroid Build Coastguard Worker// installing the APK, which will install the preopt outputs into $(PRODUCT_OUT)/system or $(PRODUCT_OUT)/system_other 25*333d2b36SAndroid Build Coastguard Worker// as necessary. The zip file may be empty if preopting was disabled for any reason. 26*333d2b36SAndroid Build Coastguard Worker// 27*333d2b36SAndroid Build Coastguard Worker// The intermediate shell scripts allow changes to this package or to the global config to regenerate the shell scripts 28*333d2b36SAndroid Build Coastguard Worker// but only require re-executing preopting if the script has changed. 29*333d2b36SAndroid Build Coastguard Worker// 30*333d2b36SAndroid Build Coastguard Worker// For Soong modules this package is linked directly into Soong and run from the java package. It generates the same 31*333d2b36SAndroid Build Coastguard Worker// commands as for make, using athe same global config JSON file used by make, but using a module config structure 32*333d2b36SAndroid Build Coastguard Worker// provided by Soong. The generated commands are then converted into Soong rule and written directly to the ninja file, 33*333d2b36SAndroid Build Coastguard Worker// with no extra shell scripts involved. 34*333d2b36SAndroid Build Coastguard Workerpackage dexpreopt 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workerimport ( 37*333d2b36SAndroid Build Coastguard Worker "fmt" 38*333d2b36SAndroid Build Coastguard Worker "path/filepath" 39*333d2b36SAndroid Build Coastguard Worker "runtime" 40*333d2b36SAndroid Build Coastguard Worker "strings" 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 43*333d2b36SAndroid Build Coastguard Worker 44*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/pathtools" 45*333d2b36SAndroid Build Coastguard Worker) 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Workerconst SystemPartition = "/system/" 48*333d2b36SAndroid Build Coastguard Workerconst SystemOtherPartition = "/system_other/" 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Workervar DexpreoptRunningInSoong = false 51*333d2b36SAndroid Build Coastguard Worker 52*333d2b36SAndroid Build Coastguard Worker// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a 53*333d2b36SAndroid Build Coastguard Worker// ModuleConfig. The produced files and their install locations will be available through rule.Installs(). 54*333d2b36SAndroid Build Coastguard Workerfunc GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongConfig, 55*333d2b36SAndroid Build Coastguard Worker global *GlobalConfig, module *ModuleConfig, productPackages android.Path, copyApexSystemServerJarDex bool) ( 56*333d2b36SAndroid Build Coastguard Worker rule *android.RuleBuilder, err error) { 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Worker defer func() { 59*333d2b36SAndroid Build Coastguard Worker if r := recover(); r != nil { 60*333d2b36SAndroid Build Coastguard Worker if _, ok := r.(runtime.Error); ok { 61*333d2b36SAndroid Build Coastguard Worker panic(r) 62*333d2b36SAndroid Build Coastguard Worker } else if e, ok := r.(error); ok { 63*333d2b36SAndroid Build Coastguard Worker err = e 64*333d2b36SAndroid Build Coastguard Worker rule = nil 65*333d2b36SAndroid Build Coastguard Worker } else { 66*333d2b36SAndroid Build Coastguard Worker panic(r) 67*333d2b36SAndroid Build Coastguard Worker } 68*333d2b36SAndroid Build Coastguard Worker } 69*333d2b36SAndroid Build Coastguard Worker }() 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker rule = android.NewRuleBuilder(pctx, ctx) 72*333d2b36SAndroid Build Coastguard Worker 73*333d2b36SAndroid Build Coastguard Worker generateProfile := module.ProfileClassListing.Valid() && !global.DisableGenerateProfile 74*333d2b36SAndroid Build Coastguard Worker generateBootProfile := module.ProfileBootListing.Valid() && !global.DisableGenerateProfile 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Worker var profile android.WritablePath 77*333d2b36SAndroid Build Coastguard Worker if generateProfile { 78*333d2b36SAndroid Build Coastguard Worker profile = profileCommand(ctx, globalSoong, global, module, rule) 79*333d2b36SAndroid Build Coastguard Worker } 80*333d2b36SAndroid Build Coastguard Worker if generateBootProfile { 81*333d2b36SAndroid Build Coastguard Worker bootProfileCommand(ctx, globalSoong, global, module, rule) 82*333d2b36SAndroid Build Coastguard Worker } 83*333d2b36SAndroid Build Coastguard Worker 84*333d2b36SAndroid Build Coastguard Worker if !dexpreoptDisabled(ctx, global, module) { 85*333d2b36SAndroid Build Coastguard Worker if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil { 86*333d2b36SAndroid Build Coastguard Worker android.ReportPathErrorf(ctx, err.Error()) 87*333d2b36SAndroid Build Coastguard Worker } else if valid { 88*333d2b36SAndroid Build Coastguard Worker fixClassLoaderContext(module.ClassLoaderContexts) 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Worker appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) && 91*333d2b36SAndroid Build Coastguard Worker !module.NoCreateAppImage 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Worker generateDM := shouldGenerateDM(module, global) 94*333d2b36SAndroid Build Coastguard Worker 95*333d2b36SAndroid Build Coastguard Worker for archIdx, _ := range module.Archs { 96*333d2b36SAndroid Build Coastguard Worker dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, 97*333d2b36SAndroid Build Coastguard Worker generateDM, productPackages, copyApexSystemServerJarDex) 98*333d2b36SAndroid Build Coastguard Worker } 99*333d2b36SAndroid Build Coastguard Worker } 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Worker return rule, nil 103*333d2b36SAndroid Build Coastguard Worker} 104*333d2b36SAndroid Build Coastguard Worker 105*333d2b36SAndroid Build Coastguard Worker// If dexpreopt is applicable to the module, returns whether dexpreopt is disabled. Otherwise, the 106*333d2b36SAndroid Build Coastguard Worker// behavior is undefined. 107*333d2b36SAndroid Build Coastguard Worker// When it returns true, dexpreopt artifacts will not be generated, but profile will still be 108*333d2b36SAndroid Build Coastguard Worker// generated if profile-guided compilation is requested. 109*333d2b36SAndroid Build Coastguard Workerfunc dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) bool { 110*333d2b36SAndroid Build Coastguard Worker if ctx.Config().UnbundledBuild() { 111*333d2b36SAndroid Build Coastguard Worker return true 112*333d2b36SAndroid Build Coastguard Worker } 113*333d2b36SAndroid Build Coastguard Worker 114*333d2b36SAndroid Build Coastguard Worker if global.DisablePreopt { 115*333d2b36SAndroid Build Coastguard Worker return true 116*333d2b36SAndroid Build Coastguard Worker } 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Worker if contains(global.DisablePreoptModules, module.Name) { 119*333d2b36SAndroid Build Coastguard Worker return true 120*333d2b36SAndroid Build Coastguard Worker } 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker // Don't preopt individual boot jars, they will be preopted together. 123*333d2b36SAndroid Build Coastguard Worker if global.BootJars.ContainsJar(module.Name) { 124*333d2b36SAndroid Build Coastguard Worker return true 125*333d2b36SAndroid Build Coastguard Worker } 126*333d2b36SAndroid Build Coastguard Worker 127*333d2b36SAndroid Build Coastguard Worker if global.OnlyPreoptArtBootImage { 128*333d2b36SAndroid Build Coastguard Worker return true 129*333d2b36SAndroid Build Coastguard Worker } 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Worker return false 132*333d2b36SAndroid Build Coastguard Worker} 133*333d2b36SAndroid Build Coastguard Worker 134*333d2b36SAndroid Build Coastguard Workerfunc profileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig, 135*333d2b36SAndroid Build Coastguard Worker module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath { 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Worker profilePath := module.BuildPath.InSameDir(ctx, "profile.prof") 138*333d2b36SAndroid Build Coastguard Worker profileInstalledPath := module.DexLocation + ".prof" 139*333d2b36SAndroid Build Coastguard Worker 140*333d2b36SAndroid Build Coastguard Worker if !module.ProfileIsTextListing { 141*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -f").Output(profilePath) 142*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("touch").Output(profilePath) 143*333d2b36SAndroid Build Coastguard Worker } 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Worker cmd := rule.Command(). 146*333d2b36SAndroid Build Coastguard Worker Text(`ANDROID_LOG_TAGS="*:e"`). 147*333d2b36SAndroid Build Coastguard Worker Tool(globalSoong.Profman) 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Worker if module.ProfileIsTextListing { 150*333d2b36SAndroid Build Coastguard Worker // The profile is a test listing of classes (used for framework jars). 151*333d2b36SAndroid Build Coastguard Worker // We need to generate the actual binary profile before being able to compile. 152*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing.Path()) 153*333d2b36SAndroid Build Coastguard Worker } else { 154*333d2b36SAndroid Build Coastguard Worker // The profile is binary profile (used for apps). Run it through profman to 155*333d2b36SAndroid Build Coastguard Worker // ensure the profile keys match the apk. 156*333d2b36SAndroid Build Coastguard Worker cmd. 157*333d2b36SAndroid Build Coastguard Worker Flag("--copy-and-update-profile-key"). 158*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--profile-file=", module.ProfileClassListing.Path()) 159*333d2b36SAndroid Build Coastguard Worker } 160*333d2b36SAndroid Build Coastguard Worker 161*333d2b36SAndroid Build Coastguard Worker cmd. 162*333d2b36SAndroid Build Coastguard Worker Flag("--output-profile-type=app"). 163*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--apk=", module.DexPath). 164*333d2b36SAndroid Build Coastguard Worker Flag("--dex-location="+module.DexLocation). 165*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--reference-profile-file=", profilePath) 166*333d2b36SAndroid Build Coastguard Worker 167*333d2b36SAndroid Build Coastguard Worker if !module.ProfileIsTextListing { 168*333d2b36SAndroid Build Coastguard Worker cmd.Text(fmt.Sprintf(`|| echo "Profile out of date for %s"`, module.DexPath)) 169*333d2b36SAndroid Build Coastguard Worker } 170*333d2b36SAndroid Build Coastguard Worker rule.Install(profilePath, profileInstalledPath) 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Worker return profilePath 173*333d2b36SAndroid Build Coastguard Worker} 174*333d2b36SAndroid Build Coastguard Worker 175*333d2b36SAndroid Build Coastguard Workerfunc bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig, 176*333d2b36SAndroid Build Coastguard Worker module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath { 177*333d2b36SAndroid Build Coastguard Worker 178*333d2b36SAndroid Build Coastguard Worker profilePath := module.BuildPath.InSameDir(ctx, "profile.bprof") 179*333d2b36SAndroid Build Coastguard Worker profileInstalledPath := module.DexLocation + ".bprof" 180*333d2b36SAndroid Build Coastguard Worker 181*333d2b36SAndroid Build Coastguard Worker if !module.ProfileIsTextListing { 182*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -f").Output(profilePath) 183*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("touch").Output(profilePath) 184*333d2b36SAndroid Build Coastguard Worker } 185*333d2b36SAndroid Build Coastguard Worker 186*333d2b36SAndroid Build Coastguard Worker cmd := rule.Command(). 187*333d2b36SAndroid Build Coastguard Worker Text(`ANDROID_LOG_TAGS="*:e"`). 188*333d2b36SAndroid Build Coastguard Worker Tool(globalSoong.Profman) 189*333d2b36SAndroid Build Coastguard Worker 190*333d2b36SAndroid Build Coastguard Worker // The profile is a test listing of methods. 191*333d2b36SAndroid Build Coastguard Worker // We need to generate the actual binary profile. 192*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--create-profile-from=", module.ProfileBootListing.Path()) 193*333d2b36SAndroid Build Coastguard Worker 194*333d2b36SAndroid Build Coastguard Worker cmd. 195*333d2b36SAndroid Build Coastguard Worker Flag("--output-profile-type=bprof"). 196*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--apk=", module.DexPath). 197*333d2b36SAndroid Build Coastguard Worker Flag("--dex-location="+module.DexLocation). 198*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--reference-profile-file=", profilePath) 199*333d2b36SAndroid Build Coastguard Worker 200*333d2b36SAndroid Build Coastguard Worker if !module.ProfileIsTextListing { 201*333d2b36SAndroid Build Coastguard Worker cmd.Text(fmt.Sprintf(`|| echo "Profile out of date for %s"`, module.DexPath)) 202*333d2b36SAndroid Build Coastguard Worker } 203*333d2b36SAndroid Build Coastguard Worker rule.Install(profilePath, profileInstalledPath) 204*333d2b36SAndroid Build Coastguard Worker 205*333d2b36SAndroid Build Coastguard Worker return profilePath 206*333d2b36SAndroid Build Coastguard Worker} 207*333d2b36SAndroid Build Coastguard Worker 208*333d2b36SAndroid Build Coastguard Worker// Returns the dex location of a system server java library. 209*333d2b36SAndroid Build Coastguard Workerfunc GetSystemServerDexLocation(ctx android.PathContext, global *GlobalConfig, lib string) string { 210*333d2b36SAndroid Build Coastguard Worker if apex := global.AllApexSystemServerJars(ctx).ApexOfJar(lib); apex != "" { 211*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("/apex/%s/javalib/%s.jar", apex, lib) 212*333d2b36SAndroid Build Coastguard Worker } 213*333d2b36SAndroid Build Coastguard Worker 214*333d2b36SAndroid Build Coastguard Worker if apex := global.AllPlatformSystemServerJars(ctx).ApexOfJar(lib); apex == "system_ext" { 215*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("/system_ext/framework/%s.jar", lib) 216*333d2b36SAndroid Build Coastguard Worker } 217*333d2b36SAndroid Build Coastguard Worker 218*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("/system/framework/%s.jar", lib) 219*333d2b36SAndroid Build Coastguard Worker} 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker// Returns the location to the odex file for the dex file at `path`. 222*333d2b36SAndroid Build Coastguard Workerfunc ToOdexPath(path string, arch android.ArchType, partition string) string { 223*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(path, "/apex/") { 224*333d2b36SAndroid Build Coastguard Worker return filepath.Join(partition, "framework/oat", arch.String(), 225*333d2b36SAndroid Build Coastguard Worker strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex") 226*333d2b36SAndroid Build Coastguard Worker } 227*333d2b36SAndroid Build Coastguard Worker 228*333d2b36SAndroid Build Coastguard Worker return filepath.Join(filepath.Dir(path), "oat", arch.String(), 229*333d2b36SAndroid Build Coastguard Worker pathtools.ReplaceExtension(filepath.Base(path), "odex")) 230*333d2b36SAndroid Build Coastguard Worker} 231*333d2b36SAndroid Build Coastguard Worker 232*333d2b36SAndroid Build Coastguard Workerfunc dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig, 233*333d2b36SAndroid Build Coastguard Worker global *GlobalConfig, module *ModuleConfig, rule *android.RuleBuilder, archIdx int, 234*333d2b36SAndroid Build Coastguard Worker profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path, copyApexSystemServerJarDex bool) { 235*333d2b36SAndroid Build Coastguard Worker 236*333d2b36SAndroid Build Coastguard Worker arch := module.Archs[archIdx] 237*333d2b36SAndroid Build Coastguard Worker 238*333d2b36SAndroid Build Coastguard Worker // HACK: make soname in Soong-generated .odex files match Make. 239*333d2b36SAndroid Build Coastguard Worker base := filepath.Base(module.DexLocation) 240*333d2b36SAndroid Build Coastguard Worker if filepath.Ext(base) == ".jar" { 241*333d2b36SAndroid Build Coastguard Worker base = "javalib.jar" 242*333d2b36SAndroid Build Coastguard Worker } else if filepath.Ext(base) == ".apk" { 243*333d2b36SAndroid Build Coastguard Worker base = "package.apk" 244*333d2b36SAndroid Build Coastguard Worker } 245*333d2b36SAndroid Build Coastguard Worker 246*333d2b36SAndroid Build Coastguard Worker odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex")) 247*333d2b36SAndroid Build Coastguard Worker odexSymbolsPath := odexPath.ReplaceExtension(ctx, "symbols.odex") 248*333d2b36SAndroid Build Coastguard Worker odexInstallPath := ToOdexPath(module.DexLocation, arch, module.ApexPartition) 249*333d2b36SAndroid Build Coastguard Worker if odexOnSystemOther(module, global) { 250*333d2b36SAndroid Build Coastguard Worker odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath) 251*333d2b36SAndroid Build Coastguard Worker } 252*333d2b36SAndroid Build Coastguard Worker 253*333d2b36SAndroid Build Coastguard Worker vdexPath := odexPath.ReplaceExtension(ctx, "vdex") 254*333d2b36SAndroid Build Coastguard Worker vdexInstallPath := pathtools.ReplaceExtension(odexInstallPath, "vdex") 255*333d2b36SAndroid Build Coastguard Worker 256*333d2b36SAndroid Build Coastguard Worker invocationPath := odexPath.ReplaceExtension(ctx, "invocation") 257*333d2b36SAndroid Build Coastguard Worker 258*333d2b36SAndroid Build Coastguard Worker systemServerJars := global.AllSystemServerJars(ctx) 259*333d2b36SAndroid Build Coastguard Worker systemServerClasspathJars := global.AllSystemServerClasspathJars(ctx) 260*333d2b36SAndroid Build Coastguard Worker 261*333d2b36SAndroid Build Coastguard Worker rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String())) 262*333d2b36SAndroid Build Coastguard Worker rule.Command().FlagWithOutput("rm -f ", odexPath). 263*333d2b36SAndroid Build Coastguard Worker FlagWithArg("rm -f ", odexSymbolsPath.String()) 264*333d2b36SAndroid Build Coastguard Worker 265*333d2b36SAndroid Build Coastguard Worker if jarIndex := systemServerJars.IndexOfJar(module.Name); jarIndex >= 0 { 266*333d2b36SAndroid Build Coastguard Worker // System server jars should be dexpreopted together: class loader context of each jar 267*333d2b36SAndroid Build Coastguard Worker // should include all preceding jars on the system server classpath. 268*333d2b36SAndroid Build Coastguard Worker 269*333d2b36SAndroid Build Coastguard Worker var clcHost android.Paths 270*333d2b36SAndroid Build Coastguard Worker var clcTarget []string 271*333d2b36SAndroid Build Coastguard Worker endIndex := systemServerClasspathJars.IndexOfJar(module.Name) 272*333d2b36SAndroid Build Coastguard Worker if endIndex < 0 { 273*333d2b36SAndroid Build Coastguard Worker // The jar is a standalone one. Use the full classpath as the class loader context. 274*333d2b36SAndroid Build Coastguard Worker endIndex = systemServerClasspathJars.Len() 275*333d2b36SAndroid Build Coastguard Worker } 276*333d2b36SAndroid Build Coastguard Worker for i := 0; i < endIndex; i++ { 277*333d2b36SAndroid Build Coastguard Worker lib := systemServerClasspathJars.Jar(i) 278*333d2b36SAndroid Build Coastguard Worker clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib)) 279*333d2b36SAndroid Build Coastguard Worker clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib)) 280*333d2b36SAndroid Build Coastguard Worker } 281*333d2b36SAndroid Build Coastguard Worker 282*333d2b36SAndroid Build Coastguard Worker if DexpreoptRunningInSoong && copyApexSystemServerJarDex { 283*333d2b36SAndroid Build Coastguard Worker // Copy the system server jar to a predefined location where dex2oat will find it. 284*333d2b36SAndroid Build Coastguard Worker dexPathHost := SystemServerDexJarHostPath(ctx, module.Name) 285*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String())) 286*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost) 287*333d2b36SAndroid Build Coastguard Worker } else { 288*333d2b36SAndroid Build Coastguard Worker // For Make modules the copy rule is generated in the makefiles, not in dexpreopt.sh. 289*333d2b36SAndroid Build Coastguard Worker // This is necessary to expose the rule to Ninja, otherwise it has rules that depend on 290*333d2b36SAndroid Build Coastguard Worker // the jar (namely, dexpreopt commands for all subsequent system server jars that have 291*333d2b36SAndroid Build Coastguard Worker // this one in their class loader context), but no rule that creates it (because Ninja 292*333d2b36SAndroid Build Coastguard Worker // cannot see the rule in the generated dexpreopt.sh script). 293*333d2b36SAndroid Build Coastguard Worker } 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Worker clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]" 296*333d2b36SAndroid Build Coastguard Worker clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]" 297*333d2b36SAndroid Build Coastguard Worker 298*333d2b36SAndroid Build Coastguard Worker if systemServerClasspathJars.ContainsJar(module.Name) { 299*333d2b36SAndroid Build Coastguard Worker checkSystemServerOrder(ctx, jarIndex) 300*333d2b36SAndroid Build Coastguard Worker } else { 301*333d2b36SAndroid Build Coastguard Worker // Standalone jars are loaded by separate class loaders with SYSTEMSERVERCLASSPATH as the 302*333d2b36SAndroid Build Coastguard Worker // parent. 303*333d2b36SAndroid Build Coastguard Worker clcHostString = "PCL[];" + clcHostString 304*333d2b36SAndroid Build Coastguard Worker clcTargetString = "PCL[];" + clcTargetString 305*333d2b36SAndroid Build Coastguard Worker } 306*333d2b36SAndroid Build Coastguard Worker 307*333d2b36SAndroid Build Coastguard Worker rule.Command(). 308*333d2b36SAndroid Build Coastguard Worker Text(`class_loader_context_arg=--class-loader-context="` + clcHostString + `"`). 309*333d2b36SAndroid Build Coastguard Worker Implicits(clcHost). 310*333d2b36SAndroid Build Coastguard Worker Text(`stored_class_loader_context_arg=--stored-class-loader-context="` + clcTargetString + `"`) 311*333d2b36SAndroid Build Coastguard Worker 312*333d2b36SAndroid Build Coastguard Worker } else { 313*333d2b36SAndroid Build Coastguard Worker // There are three categories of Java modules handled here: 314*333d2b36SAndroid Build Coastguard Worker // 315*333d2b36SAndroid Build Coastguard Worker // - Modules that have passed verify_uses_libraries check. They are AOT-compiled and 316*333d2b36SAndroid Build Coastguard Worker // expected to be loaded on device without CLC mismatch errors. 317*333d2b36SAndroid Build Coastguard Worker // 318*333d2b36SAndroid Build Coastguard Worker // - Modules that have failed the check in relaxed mode, so it didn't cause a build error. 319*333d2b36SAndroid Build Coastguard Worker // They are dexpreopted with "verify" filter and not AOT-compiled. 320*333d2b36SAndroid Build Coastguard Worker // TODO(b/132357300): ensure that CLC mismatch errors are ignored with "verify" filter. 321*333d2b36SAndroid Build Coastguard Worker // 322*333d2b36SAndroid Build Coastguard Worker // - Modules that didn't run the check. They are AOT-compiled, but it's unknown if they 323*333d2b36SAndroid Build Coastguard Worker // will have CLC mismatch errors on device (the check is disabled by default). 324*333d2b36SAndroid Build Coastguard Worker // 325*333d2b36SAndroid Build Coastguard Worker // TODO(b/132357300): enable the check by default and eliminate the last category, so that 326*333d2b36SAndroid Build Coastguard Worker // no time/space is wasted on AOT-compiling modules that will fail CLC check on device. 327*333d2b36SAndroid Build Coastguard Worker 328*333d2b36SAndroid Build Coastguard Worker var manifestOrApk android.Path 329*333d2b36SAndroid Build Coastguard Worker if module.ManifestPath.Valid() { 330*333d2b36SAndroid Build Coastguard Worker // Ok, there is an XML manifest. 331*333d2b36SAndroid Build Coastguard Worker manifestOrApk = module.ManifestPath.Path() 332*333d2b36SAndroid Build Coastguard Worker } else if filepath.Ext(base) == ".apk" { 333*333d2b36SAndroid Build Coastguard Worker // Ok, there is is an APK with the manifest inside. 334*333d2b36SAndroid Build Coastguard Worker manifestOrApk = module.DexPath 335*333d2b36SAndroid Build Coastguard Worker } 336*333d2b36SAndroid Build Coastguard Worker 337*333d2b36SAndroid Build Coastguard Worker // Generate command that saves target SDK version in a shell variable. 338*333d2b36SAndroid Build Coastguard Worker if manifestOrApk == nil { 339*333d2b36SAndroid Build Coastguard Worker // There is neither an XML manifest nor APK => nowhere to extract targetSdkVersion from. 340*333d2b36SAndroid Build Coastguard Worker // Set the latest ("any") version: then construct_context will not add any compatibility 341*333d2b36SAndroid Build Coastguard Worker // libraries (if this is incorrect, there will be a CLC mismatch and dexopt on device). 342*333d2b36SAndroid Build Coastguard Worker rule.Command().Textf(`target_sdk_version=%d`, AnySdkVersion) 343*333d2b36SAndroid Build Coastguard Worker } else { 344*333d2b36SAndroid Build Coastguard Worker rule.Command().Text(`target_sdk_version="$(`). 345*333d2b36SAndroid Build Coastguard Worker Tool(globalSoong.ManifestCheck). 346*333d2b36SAndroid Build Coastguard Worker Flag("--extract-target-sdk-version"). 347*333d2b36SAndroid Build Coastguard Worker Input(manifestOrApk). 348*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--aapt ", globalSoong.Aapt). 349*333d2b36SAndroid Build Coastguard Worker Text(`)"`) 350*333d2b36SAndroid Build Coastguard Worker } 351*333d2b36SAndroid Build Coastguard Worker 352*333d2b36SAndroid Build Coastguard Worker // Generate command that saves host and target class loader context in shell variables. 353*333d2b36SAndroid Build Coastguard Worker _, paths := ComputeClassLoaderContextDependencies(module.ClassLoaderContexts) 354*333d2b36SAndroid Build Coastguard Worker rule.Command(). 355*333d2b36SAndroid Build Coastguard Worker Text(`eval "$(`).Tool(globalSoong.ConstructContext). 356*333d2b36SAndroid Build Coastguard Worker Text(` --target-sdk-version ${target_sdk_version}`). 357*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--context-json=", module.ClassLoaderContexts.DumpForFlag()). 358*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--product-packages=", productPackages). 359*333d2b36SAndroid Build Coastguard Worker Implicits(paths). 360*333d2b36SAndroid Build Coastguard Worker Text(`)"`) 361*333d2b36SAndroid Build Coastguard Worker } 362*333d2b36SAndroid Build Coastguard Worker 363*333d2b36SAndroid Build Coastguard Worker // Devices that do not have a product partition use a symlink from /product to /system/product. 364*333d2b36SAndroid Build Coastguard Worker // Because on-device dexopt will see dex locations starting with /product, we change the paths 365*333d2b36SAndroid Build Coastguard Worker // to mimic this behavior. 366*333d2b36SAndroid Build Coastguard Worker dexLocationArg := module.DexLocation 367*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(dexLocationArg, "/system/product/") { 368*333d2b36SAndroid Build Coastguard Worker dexLocationArg = strings.TrimPrefix(dexLocationArg, "/system") 369*333d2b36SAndroid Build Coastguard Worker } 370*333d2b36SAndroid Build Coastguard Worker 371*333d2b36SAndroid Build Coastguard Worker cmd := rule.Command(). 372*333d2b36SAndroid Build Coastguard Worker Text(`ANDROID_LOG_TAGS="*:e"`). 373*333d2b36SAndroid Build Coastguard Worker Tool(globalSoong.Dex2oat). 374*333d2b36SAndroid Build Coastguard Worker Flag("--avoid-storing-invocation"). 375*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath). 376*333d2b36SAndroid Build Coastguard Worker Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms). 377*333d2b36SAndroid Build Coastguard Worker Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatXmx). 378*333d2b36SAndroid Build Coastguard Worker Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":"). 379*333d2b36SAndroid Build Coastguard Worker Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":"). 380*333d2b36SAndroid Build Coastguard Worker Flag("${class_loader_context_arg}"). 381*333d2b36SAndroid Build Coastguard Worker Flag("${stored_class_loader_context_arg}"). 382*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocationsOnHost, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()). 383*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--dex-file=", module.DexPath). 384*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--dex-location=", dexLocationArg). 385*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath). 386*333d2b36SAndroid Build Coastguard Worker // Pass an empty directory, dex2oat shouldn't be reading arbitrary files 387*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--android-root=", global.EmptyDirectory). 388*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--instruction-set=", arch.String()). 389*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]). 390*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]). 391*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--oat-symbols=", odexSymbolsPath). 392*333d2b36SAndroid Build Coastguard Worker Flag("--generate-debug-info"). 393*333d2b36SAndroid Build Coastguard Worker Flag("--strip"). 394*333d2b36SAndroid Build Coastguard Worker Flag("--generate-build-id"). 395*333d2b36SAndroid Build Coastguard Worker Flag("--abort-on-hard-verifier-error"). 396*333d2b36SAndroid Build Coastguard Worker Flag("--force-determinism"). 397*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--no-inline-from=", "core-oj.jar"). 398*333d2b36SAndroid Build Coastguard Worker Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")") 399*333d2b36SAndroid Build Coastguard Worker 400*333d2b36SAndroid Build Coastguard Worker var preoptFlags []string 401*333d2b36SAndroid Build Coastguard Worker if len(module.PreoptFlags) > 0 { 402*333d2b36SAndroid Build Coastguard Worker preoptFlags = module.PreoptFlags 403*333d2b36SAndroid Build Coastguard Worker } else if len(global.PreoptFlags) > 0 { 404*333d2b36SAndroid Build Coastguard Worker preoptFlags = global.PreoptFlags 405*333d2b36SAndroid Build Coastguard Worker } 406*333d2b36SAndroid Build Coastguard Worker 407*333d2b36SAndroid Build Coastguard Worker if len(preoptFlags) > 0 { 408*333d2b36SAndroid Build Coastguard Worker cmd.Text(strings.Join(preoptFlags, " ")) 409*333d2b36SAndroid Build Coastguard Worker } 410*333d2b36SAndroid Build Coastguard Worker 411*333d2b36SAndroid Build Coastguard Worker if module.UncompressedDex { 412*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--copy-dex-files=", "false") 413*333d2b36SAndroid Build Coastguard Worker } 414*333d2b36SAndroid Build Coastguard Worker 415*333d2b36SAndroid Build Coastguard Worker if !android.PrefixInList(preoptFlags, "--compiler-filter=") { 416*333d2b36SAndroid Build Coastguard Worker var compilerFilter string 417*333d2b36SAndroid Build Coastguard Worker if systemServerJars.ContainsJar(module.Name) { 418*333d2b36SAndroid Build Coastguard Worker if global.SystemServerCompilerFilter != "" { 419*333d2b36SAndroid Build Coastguard Worker // Use the product option if it is set. 420*333d2b36SAndroid Build Coastguard Worker compilerFilter = global.SystemServerCompilerFilter 421*333d2b36SAndroid Build Coastguard Worker } else if profile != nil { 422*333d2b36SAndroid Build Coastguard Worker // Use "speed-profile" for system server jars that have a profile. 423*333d2b36SAndroid Build Coastguard Worker compilerFilter = "speed-profile" 424*333d2b36SAndroid Build Coastguard Worker } else { 425*333d2b36SAndroid Build Coastguard Worker // Use "speed" for system server jars that do not have a profile. 426*333d2b36SAndroid Build Coastguard Worker compilerFilter = "speed" 427*333d2b36SAndroid Build Coastguard Worker } 428*333d2b36SAndroid Build Coastguard Worker } else if contains(global.SpeedApps, module.Name) || contains(global.SystemServerApps, module.Name) { 429*333d2b36SAndroid Build Coastguard Worker // Apps loaded into system server, and apps the product default to being compiled with the 430*333d2b36SAndroid Build Coastguard Worker // 'speed' compiler filter. 431*333d2b36SAndroid Build Coastguard Worker compilerFilter = "speed" 432*333d2b36SAndroid Build Coastguard Worker } else if profile != nil { 433*333d2b36SAndroid Build Coastguard Worker // For non system server jars, use speed-profile when we have a profile. 434*333d2b36SAndroid Build Coastguard Worker compilerFilter = "speed-profile" 435*333d2b36SAndroid Build Coastguard Worker } else if global.DefaultCompilerFilter != "" { 436*333d2b36SAndroid Build Coastguard Worker compilerFilter = global.DefaultCompilerFilter 437*333d2b36SAndroid Build Coastguard Worker } else { 438*333d2b36SAndroid Build Coastguard Worker compilerFilter = "quicken" 439*333d2b36SAndroid Build Coastguard Worker } 440*333d2b36SAndroid Build Coastguard Worker if module.EnforceUsesLibraries { 441*333d2b36SAndroid Build Coastguard Worker // If the verify_uses_libraries check failed (in this case status file contains a 442*333d2b36SAndroid Build Coastguard Worker // non-empty error message), then use "verify" compiler filter to avoid compiling any 443*333d2b36SAndroid Build Coastguard Worker // code (it would be rejected on device because of a class loader context mismatch). 444*333d2b36SAndroid Build Coastguard Worker cmd.Text("--compiler-filter=$(if test -s "). 445*333d2b36SAndroid Build Coastguard Worker Input(module.EnforceUsesLibrariesStatusFile). 446*333d2b36SAndroid Build Coastguard Worker Text(" ; then echo verify ; else echo " + compilerFilter + " ; fi)") 447*333d2b36SAndroid Build Coastguard Worker } else { 448*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--compiler-filter=", compilerFilter) 449*333d2b36SAndroid Build Coastguard Worker } 450*333d2b36SAndroid Build Coastguard Worker } 451*333d2b36SAndroid Build Coastguard Worker 452*333d2b36SAndroid Build Coastguard Worker if generateDM { 453*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--copy-dex-files=", "false") 454*333d2b36SAndroid Build Coastguard Worker dmPath := module.BuildPath.InSameDir(ctx, "generated.dm") 455*333d2b36SAndroid Build Coastguard Worker dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm") 456*333d2b36SAndroid Build Coastguard Worker tmpPath := module.BuildPath.InSameDir(ctx, "primary.vdex") 457*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath) 458*333d2b36SAndroid Build Coastguard Worker rule.Command().Tool(globalSoong.SoongZip). 459*333d2b36SAndroid Build Coastguard Worker FlagWithArg("-L", "9"). 460*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o", dmPath). 461*333d2b36SAndroid Build Coastguard Worker Flag("-j"). 462*333d2b36SAndroid Build Coastguard Worker Input(tmpPath) 463*333d2b36SAndroid Build Coastguard Worker rule.Install(dmPath, dmInstalledPath) 464*333d2b36SAndroid Build Coastguard Worker } 465*333d2b36SAndroid Build Coastguard Worker 466*333d2b36SAndroid Build Coastguard Worker // By default, emit debug info. 467*333d2b36SAndroid Build Coastguard Worker debugInfo := true 468*333d2b36SAndroid Build Coastguard Worker if global.NoDebugInfo { 469*333d2b36SAndroid Build Coastguard Worker // If the global setting suppresses mini-debug-info, disable it. 470*333d2b36SAndroid Build Coastguard Worker debugInfo = false 471*333d2b36SAndroid Build Coastguard Worker } 472*333d2b36SAndroid Build Coastguard Worker 473*333d2b36SAndroid Build Coastguard Worker // PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO. 474*333d2b36SAndroid Build Coastguard Worker // PRODUCT_OTHER_JAVA_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO. 475*333d2b36SAndroid Build Coastguard Worker if systemServerJars.ContainsJar(module.Name) { 476*333d2b36SAndroid Build Coastguard Worker if global.AlwaysSystemServerDebugInfo { 477*333d2b36SAndroid Build Coastguard Worker debugInfo = true 478*333d2b36SAndroid Build Coastguard Worker } else if global.NeverSystemServerDebugInfo { 479*333d2b36SAndroid Build Coastguard Worker debugInfo = false 480*333d2b36SAndroid Build Coastguard Worker } 481*333d2b36SAndroid Build Coastguard Worker } else { 482*333d2b36SAndroid Build Coastguard Worker if global.AlwaysOtherDebugInfo { 483*333d2b36SAndroid Build Coastguard Worker debugInfo = true 484*333d2b36SAndroid Build Coastguard Worker } else if global.NeverOtherDebugInfo { 485*333d2b36SAndroid Build Coastguard Worker debugInfo = false 486*333d2b36SAndroid Build Coastguard Worker } 487*333d2b36SAndroid Build Coastguard Worker } 488*333d2b36SAndroid Build Coastguard Worker 489*333d2b36SAndroid Build Coastguard Worker if debugInfo { 490*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--generate-mini-debug-info") 491*333d2b36SAndroid Build Coastguard Worker } else { 492*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--no-generate-mini-debug-info") 493*333d2b36SAndroid Build Coastguard Worker } 494*333d2b36SAndroid Build Coastguard Worker 495*333d2b36SAndroid Build Coastguard Worker // Set the compiler reason to 'prebuilt' to identify the oat files produced 496*333d2b36SAndroid Build Coastguard Worker // during the build, as opposed to compiled on the device. 497*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--compilation-reason=", "prebuilt") 498*333d2b36SAndroid Build Coastguard Worker 499*333d2b36SAndroid Build Coastguard Worker if appImage { 500*333d2b36SAndroid Build Coastguard Worker appImagePath := odexPath.ReplaceExtension(ctx, "art") 501*333d2b36SAndroid Build Coastguard Worker appImageInstallPath := pathtools.ReplaceExtension(odexInstallPath, "art") 502*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithOutput("--app-image-file=", appImagePath). 503*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--image-format=", "lz4") 504*333d2b36SAndroid Build Coastguard Worker if !global.DontResolveStartupStrings { 505*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--resolve-startup-const-strings=", "true") 506*333d2b36SAndroid Build Coastguard Worker } 507*333d2b36SAndroid Build Coastguard Worker rule.Install(appImagePath, appImageInstallPath) 508*333d2b36SAndroid Build Coastguard Worker } 509*333d2b36SAndroid Build Coastguard Worker 510*333d2b36SAndroid Build Coastguard Worker if profile != nil { 511*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--profile-file=", profile) 512*333d2b36SAndroid Build Coastguard Worker } 513*333d2b36SAndroid Build Coastguard Worker 514*333d2b36SAndroid Build Coastguard Worker rule.Install(odexPath, odexInstallPath) 515*333d2b36SAndroid Build Coastguard Worker rule.Install(vdexPath, vdexInstallPath) 516*333d2b36SAndroid Build Coastguard Worker} 517*333d2b36SAndroid Build Coastguard Worker 518*333d2b36SAndroid Build Coastguard Workerfunc shouldGenerateDM(module *ModuleConfig, global *GlobalConfig) bool { 519*333d2b36SAndroid Build Coastguard Worker // Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs. 520*333d2b36SAndroid Build Coastguard Worker // No reason to use a dm file if the dex is already uncompressed. 521*333d2b36SAndroid Build Coastguard Worker return global.GenerateDMFiles && !module.UncompressedDex && 522*333d2b36SAndroid Build Coastguard Worker contains(module.PreoptFlags, "--compiler-filter=verify") 523*333d2b36SAndroid Build Coastguard Worker} 524*333d2b36SAndroid Build Coastguard Worker 525*333d2b36SAndroid Build Coastguard Workerfunc OdexOnSystemOtherByName(name string, dexLocation string, global *GlobalConfig) bool { 526*333d2b36SAndroid Build Coastguard Worker if !global.HasSystemOther { 527*333d2b36SAndroid Build Coastguard Worker return false 528*333d2b36SAndroid Build Coastguard Worker } 529*333d2b36SAndroid Build Coastguard Worker 530*333d2b36SAndroid Build Coastguard Worker if global.SanitizeLite { 531*333d2b36SAndroid Build Coastguard Worker return false 532*333d2b36SAndroid Build Coastguard Worker } 533*333d2b36SAndroid Build Coastguard Worker 534*333d2b36SAndroid Build Coastguard Worker if contains(global.SystemServerApps, name) { 535*333d2b36SAndroid Build Coastguard Worker return false 536*333d2b36SAndroid Build Coastguard Worker } 537*333d2b36SAndroid Build Coastguard Worker 538*333d2b36SAndroid Build Coastguard Worker for _, f := range global.PatternsOnSystemOther { 539*333d2b36SAndroid Build Coastguard Worker if makefileMatch("/"+f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) { 540*333d2b36SAndroid Build Coastguard Worker return true 541*333d2b36SAndroid Build Coastguard Worker } 542*333d2b36SAndroid Build Coastguard Worker } 543*333d2b36SAndroid Build Coastguard Worker 544*333d2b36SAndroid Build Coastguard Worker return false 545*333d2b36SAndroid Build Coastguard Worker} 546*333d2b36SAndroid Build Coastguard Worker 547*333d2b36SAndroid Build Coastguard Workerfunc odexOnSystemOther(module *ModuleConfig, global *GlobalConfig) bool { 548*333d2b36SAndroid Build Coastguard Worker return OdexOnSystemOtherByName(module.Name, module.DexLocation, global) 549*333d2b36SAndroid Build Coastguard Worker} 550*333d2b36SAndroid Build Coastguard Worker 551*333d2b36SAndroid Build Coastguard Worker// PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art 552*333d2b36SAndroid Build Coastguard Workerfunc PathToLocation(path android.Path, arch android.ArchType) string { 553*333d2b36SAndroid Build Coastguard Worker return PathStringToLocation(path.String(), arch) 554*333d2b36SAndroid Build Coastguard Worker} 555*333d2b36SAndroid Build Coastguard Worker 556*333d2b36SAndroid Build Coastguard Worker// PathStringToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art 557*333d2b36SAndroid Build Coastguard Workerfunc PathStringToLocation(path string, arch android.ArchType) string { 558*333d2b36SAndroid Build Coastguard Worker pathArch := filepath.Base(filepath.Dir(path)) 559*333d2b36SAndroid Build Coastguard Worker if pathArch != arch.String() { 560*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("last directory in %q must be %q", path, arch.String())) 561*333d2b36SAndroid Build Coastguard Worker } 562*333d2b36SAndroid Build Coastguard Worker return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path)) 563*333d2b36SAndroid Build Coastguard Worker} 564*333d2b36SAndroid Build Coastguard Worker 565*333d2b36SAndroid Build Coastguard Workerfunc makefileMatch(pattern, s string) bool { 566*333d2b36SAndroid Build Coastguard Worker percent := strings.IndexByte(pattern, '%') 567*333d2b36SAndroid Build Coastguard Worker switch percent { 568*333d2b36SAndroid Build Coastguard Worker case -1: 569*333d2b36SAndroid Build Coastguard Worker return pattern == s 570*333d2b36SAndroid Build Coastguard Worker case len(pattern) - 1: 571*333d2b36SAndroid Build Coastguard Worker return strings.HasPrefix(s, pattern[:len(pattern)-1]) 572*333d2b36SAndroid Build Coastguard Worker default: 573*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("unsupported makefile pattern %q", pattern)) 574*333d2b36SAndroid Build Coastguard Worker } 575*333d2b36SAndroid Build Coastguard Worker} 576*333d2b36SAndroid Build Coastguard Worker 577*333d2b36SAndroid Build Coastguard Worker// A predefined location for the system server dex jars. This is needed in order to generate 578*333d2b36SAndroid Build Coastguard Worker// class loader context for dex2oat, as the path to the jar in the Soong module may be unknown 579*333d2b36SAndroid Build Coastguard Worker// at that time (Soong processes the jars in dependency order, which may be different from the 580*333d2b36SAndroid Build Coastguard Worker// the system server classpath order). 581*333d2b36SAndroid Build Coastguard Workerfunc SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath { 582*333d2b36SAndroid Build Coastguard Worker if DexpreoptRunningInSoong { 583*333d2b36SAndroid Build Coastguard Worker // Soong module, just use the default output directory $OUT/soong. 584*333d2b36SAndroid Build Coastguard Worker return android.PathForOutput(ctx, "system_server_dexjars", jar+".jar") 585*333d2b36SAndroid Build Coastguard Worker } else { 586*333d2b36SAndroid Build Coastguard Worker // Make module, default output directory is $OUT (passed via the "null config" created 587*333d2b36SAndroid Build Coastguard Worker // by dexpreopt_gen). Append Soong subdirectory to match Soong module paths. 588*333d2b36SAndroid Build Coastguard Worker return android.PathForOutput(ctx, "soong", "system_server_dexjars", jar+".jar") 589*333d2b36SAndroid Build Coastguard Worker } 590*333d2b36SAndroid Build Coastguard Worker} 591*333d2b36SAndroid Build Coastguard Worker 592*333d2b36SAndroid Build Coastguard Worker// Check the order of jars on the system server classpath and give a warning/error if a jar precedes 593*333d2b36SAndroid Build Coastguard Worker// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't 594*333d2b36SAndroid Build Coastguard Worker// have the dependency jar in the class loader context, and it won't be able to resolve any 595*333d2b36SAndroid Build Coastguard Worker// references to its classes and methods. 596*333d2b36SAndroid Build Coastguard Workerfunc checkSystemServerOrder(ctx android.PathContext, jarIndex int) { 597*333d2b36SAndroid Build Coastguard Worker mctx, isModule := ctx.(android.ModuleContext) 598*333d2b36SAndroid Build Coastguard Worker if isModule { 599*333d2b36SAndroid Build Coastguard Worker config := GetGlobalConfig(ctx) 600*333d2b36SAndroid Build Coastguard Worker jars := config.AllSystemServerClasspathJars(ctx) 601*333d2b36SAndroid Build Coastguard Worker mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { 602*333d2b36SAndroid Build Coastguard Worker depIndex := jars.IndexOfJar(dep.Name()) 603*333d2b36SAndroid Build Coastguard Worker if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { 604*333d2b36SAndroid Build Coastguard Worker jar := jars.Jar(jarIndex) 605*333d2b36SAndroid Build Coastguard Worker dep := jars.Jar(depIndex) 606*333d2b36SAndroid Build Coastguard Worker mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+ 607*333d2b36SAndroid Build Coastguard Worker " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+ 608*333d2b36SAndroid Build Coastguard Worker " references from '%s' to '%s'.\n", jar, dep, jar, dep) 609*333d2b36SAndroid Build Coastguard Worker } 610*333d2b36SAndroid Build Coastguard Worker return true 611*333d2b36SAndroid Build Coastguard Worker }) 612*333d2b36SAndroid Build Coastguard Worker } 613*333d2b36SAndroid Build Coastguard Worker} 614*333d2b36SAndroid Build Coastguard Worker 615*333d2b36SAndroid Build Coastguard Worker// Returns path to a file containing the reult of verify_uses_libraries check (empty if the check 616*333d2b36SAndroid Build Coastguard Worker// has succeeded, or an error message if it failed). 617*333d2b36SAndroid Build Coastguard Workerfunc UsesLibrariesStatusFile(ctx android.ModuleContext) android.WritablePath { 618*333d2b36SAndroid Build Coastguard Worker return android.PathForModuleOut(ctx, "enforce_uses_libraries.status") 619*333d2b36SAndroid Build Coastguard Worker} 620*333d2b36SAndroid Build Coastguard Worker 621*333d2b36SAndroid Build Coastguard Workerfunc contains(l []string, s string) bool { 622*333d2b36SAndroid Build Coastguard Worker for _, e := range l { 623*333d2b36SAndroid Build Coastguard Worker if e == s { 624*333d2b36SAndroid Build Coastguard Worker return true 625*333d2b36SAndroid Build Coastguard Worker } 626*333d2b36SAndroid Build Coastguard Worker } 627*333d2b36SAndroid Build Coastguard Worker return false 628*333d2b36SAndroid Build Coastguard Worker} 629