1// Copyright 2019 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 "fmt" 19 "path/filepath" 20 "strings" 21 22 "android/soong/android" 23 "android/soong/dexpreopt" 24) 25 26// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed 27// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same 28// ctx.Config(). 29func systemServerClasspath(ctx android.MakeVarsContext) []string { 30 return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string { 31 global := dexpreopt.GetGlobalConfig(ctx) 32 var systemServerClasspathLocations []string 33 nonUpdatable := dexpreopt.NonUpdatableSystemServerJars(ctx, global) 34 // 1) Non-updatable jars. 35 for _, m := range nonUpdatable { 36 systemServerClasspathLocations = append(systemServerClasspathLocations, 37 filepath.Join("/system/framework", m+".jar")) 38 } 39 // 2) The jars that are from an updatable apex. 40 for _, m := range global.UpdatableSystemServerJars { 41 systemServerClasspathLocations = append(systemServerClasspathLocations, 42 dexpreopt.GetJarLocationFromApexJarPair(ctx, m)) 43 } 44 if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) { 45 panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d", 46 len(systemServerClasspathLocations), 47 len(global.SystemServerJars)+len(global.UpdatableSystemServerJars))) 48 } 49 return systemServerClasspathLocations 50 }) 51} 52 53var systemServerClasspathKey = android.NewOnceKey("systemServerClasspath") 54 55// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures 56// supported through native bridge. 57func dexpreoptTargets(ctx android.PathContext) []android.Target { 58 var targets []android.Target 59 for _, target := range ctx.Config().Targets[android.Android] { 60 if target.NativeBridge == android.NativeBridgeDisabled { 61 targets = append(targets, target) 62 } 63 } 64 // We may also need the images on host in order to run host-based tests. 65 for _, target := range ctx.Config().Targets[android.BuildOs] { 66 targets = append(targets, target) 67 } 68 69 return targets 70} 71 72func stemOf(moduleName string) string { 73 // b/139391334: the stem of framework-minus-apex is framework 74 // This is hard coded here until we find a good way to query the stem 75 // of a module before any other mutators are run 76 if moduleName == "framework-minus-apex" { 77 return "framework" 78 } 79 return moduleName 80} 81 82func getDexLocation(ctx android.PathContext, target android.Target, module string) string { 83 apex, jar := android.SplitApexJarPair(ctx, module) 84 85 name := stemOf(jar) + ".jar" 86 87 var subdir string 88 if apex == "platform" { 89 // Special apex name "platform" denotes jars do not come from an apex, but are part 90 // of the platform. Such jars are installed on the /system partition on device. 91 subdir = "system/framework" 92 } else if apex == "system_ext" { 93 subdir = "system_ext/framework" 94 } else { 95 subdir = filepath.Join("apex", apex, "javalib") 96 } 97 98 if target.Os.Class == android.Host { 99 return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name) 100 } else { 101 return filepath.Join("/", subdir, name) 102 } 103} 104 105var ( 106 bootImageConfigKey = android.NewOnceKey("bootImageConfig") 107 artBootImageName = "art" 108 frameworkBootImageName = "boot" 109) 110 111// Construct the global boot image configs. 112func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { 113 return ctx.Config().Once(bootImageConfigKey, func() interface{} { 114 115 global := dexpreopt.GetGlobalConfig(ctx) 116 targets := dexpreoptTargets(ctx) 117 deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName()) 118 119 artModules := global.ArtApexJars 120 // With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco. 121 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { 122 artModules = append(artModules, "com.android.art:jacocoagent") 123 } 124 frameworkModules := android.RemoveListFromList(global.BootJars, artModules) 125 126 artSubdir := "apex/com.android.art/javalib" 127 frameworkSubdir := "system/framework" 128 129 // ART config for the primary boot image in the ART apex. 130 // It includes the Core Libraries. 131 artCfg := bootImageConfig{ 132 name: artBootImageName, 133 stem: "boot", 134 installSubdir: artSubdir, 135 modules: artModules, 136 } 137 138 // Framework config for the boot image extension. 139 // It includes framework libraries and depends on the ART config. 140 frameworkCfg := bootImageConfig{ 141 extends: &artCfg, 142 name: frameworkBootImageName, 143 stem: "boot", 144 installSubdir: frameworkSubdir, 145 modules: frameworkModules, 146 } 147 148 configs := map[string]*bootImageConfig{ 149 artBootImageName: &artCfg, 150 frameworkBootImageName: &frameworkCfg, 151 } 152 153 // common to all configs 154 for _, c := range configs { 155 c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars") 156 c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped") 157 158 // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension 159 imageName := c.firstModuleNameOrStem(ctx) + ".art" 160 161 // The path to bootclasspath dex files needs to be known at module 162 // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. 163 // Set up known paths for them, the singleton rules will copy them there. 164 // TODO(b/143682396): use module dependencies instead 165 inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") 166 for _, m := range c.modules { 167 _, jar := android.SplitApexJarPair(ctx, m) 168 c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(jar)+".jar")) 169 } 170 c.dexPathsDeps = c.dexPaths 171 172 // Create target-specific variants. 173 for _, target := range targets { 174 arch := target.Arch.ArchType 175 imageDir := c.dir.Join(ctx, target.Os.String(), c.installSubdir, arch.String()) 176 variant := &bootImageVariant{ 177 bootImageConfig: c, 178 target: target, 179 images: imageDir.Join(ctx, imageName), 180 imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), 181 } 182 for _, m := range c.modules { 183 variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, m)) 184 } 185 variant.dexLocationsDeps = variant.dexLocations 186 c.variants = append(c.variants, variant) 187 } 188 189 c.zip = c.dir.Join(ctx, c.name+".zip") 190 } 191 192 // specific to the framework config 193 frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) 194 for i := range targets { 195 frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images 196 frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) 197 } 198 199 return configs 200 }).(map[string]*bootImageConfig) 201} 202 203func artBootImageConfig(ctx android.PathContext) *bootImageConfig { 204 return genBootImageConfigs(ctx)[artBootImageName] 205} 206 207func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { 208 return genBootImageConfigs(ctx)[frameworkBootImageName] 209} 210 211func defaultBootclasspath(ctx android.PathContext) []string { 212 return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string { 213 global := dexpreopt.GetGlobalConfig(ctx) 214 image := defaultBootImageConfig(ctx) 215 216 updatableBootclasspath := make([]string, len(global.UpdatableBootJars)) 217 for i, p := range global.UpdatableBootJars { 218 updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(ctx, p) 219 } 220 221 bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...) 222 return bootclasspath 223 }) 224} 225 226var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") 227 228var copyOf = android.CopyOf 229 230func init() { 231 android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) 232} 233 234func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { 235 ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) 236 ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":")) 237 ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) 238 239 ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":")) 240} 241