Loading android/config.go +178 −28 Original line number Diff line number Diff line Loading @@ -913,34 +913,6 @@ func (c *config) ModulesLoadedByPrivilegedModules() []string { return c.productVariables.ModulesLoadedByPrivilegedModules } // Expected format for apexJarValue = <apex name>:<jar name> func SplitApexJarPair(ctx PathContext, str string) (string, string) { pair := strings.SplitN(str, ":", 2) if len(pair) == 2 { return pair[0], pair[1] } else { reportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str) return "error-apex", "error-jar" } } func GetJarsFromApexJarPairs(ctx PathContext, apexJarPairs []string) []string { modules := make([]string, len(apexJarPairs)) for i, p := range apexJarPairs { _, jar := SplitApexJarPair(ctx, p) modules[i] = jar } return modules } func (c *config) BootJars() []string { ctx := NullPathContext{Config{ config: c, }} return append(GetJarsFromApexJarPairs(ctx, c.productVariables.BootJars), GetJarsFromApexJarPairs(ctx, c.productVariables.UpdatableBootJars)...) } func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) { if c.productVariables.DexpreoptGlobalConfig == nil { return nil, nil Loading Loading @@ -1275,3 +1247,181 @@ func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool { func (c *deviceConfig) BoardKernelBinaries() []string { return c.config.productVariables.BoardKernelBinaries } // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs. // Such lists are used in the build system for things like bootclasspath jars or system server jars. // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a // module name. The pairs come from Make product variables as a list of colon-separated strings. // // Examples: // - "com.android.art:core-oj" // - "platform:framework" // - "system_ext:foo" // type ConfiguredJarList struct { apexes []string // A list of apex components. jars []string // A list of jar components. } // The length of the list. func (l *ConfiguredJarList) Len() int { return len(l.jars) } // Apex component of idx-th pair on the list. func (l *ConfiguredJarList) apex(idx int) string { return l.apexes[idx] } // Jar component of idx-th pair on the list. func (l *ConfiguredJarList) Jar(idx int) string { return l.jars[idx] } // If the list contains a pair with the given jar. func (l *ConfiguredJarList) ContainsJar(jar string) bool { return InList(jar, l.jars) } // If the list contains the given (apex, jar) pair. func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool { for i := 0; i < l.Len(); i++ { if apex == l.apex(i) && jar == l.Jar(i) { return true } } return false } // Index of the first pair with the given jar on the list, or -1 if none. func (l *ConfiguredJarList) IndexOfJar(jar string) int { return IndexList(jar, l.jars) } // Append an (apex, jar) pair to the list. func (l *ConfiguredJarList) Append(apex string, jar string) { l.apexes = append(l.apexes, apex) l.jars = append(l.jars, jar) } // Filter out sublist. func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) { apexes := make([]string, 0, l.Len()) jars := make([]string, 0, l.Len()) for i, jar := range l.jars { apex := l.apex(i) if !list.containsApexJarPair(apex, jar) { apexes = append(apexes, apex) jars = append(jars, jar) } } l.apexes = apexes l.jars = jars } // A copy of itself. func (l *ConfiguredJarList) CopyOf() ConfiguredJarList { return ConfiguredJarList{CopyOf(l.apexes), CopyOf(l.jars)} } // A copy of the list of strings containing jar components. func (l *ConfiguredJarList) CopyOfJars() []string { return CopyOf(l.jars) } // A copy of the list of strings with colon-separated (apex, jar) pairs. func (l *ConfiguredJarList) CopyOfApexJarPairs() []string { pairs := make([]string, 0, l.Len()) for i, jar := range l.jars { apex := l.apex(i) pairs = append(pairs, apex+":"+jar) } return pairs } // A list of build paths based on the given directory prefix. func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths { paths := make(WritablePaths, l.Len()) for i, jar := range l.jars { paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar") } return paths } func ModuleStem(module string) string { // b/139391334: the stem of framework-minus-apex is framework. This is hard coded here until we // find a good way to query the stem of a module before any other mutators are run. if module == "framework-minus-apex" { return "framework" } return module } // A list of on-device paths. func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string { paths := make([]string, l.Len()) for i, jar := range l.jars { apex := l.apexes[i] name := ModuleStem(jar) + ".jar" var subdir string if apex == "platform" { subdir = "system/framework" } else if apex == "system_ext" { subdir = "system_ext/framework" } else { subdir = filepath.Join("apex", apex, "javalib") } if ostype.Class == Host { paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name) } else { paths[i] = filepath.Join("/", subdir, name) } } return paths } // Expected format for apexJarValue = <apex name>:<jar name> func splitConfiguredJarPair(ctx PathContext, str string) (string, string) { pair := strings.SplitN(str, ":", 2) if len(pair) == 2 { return pair[0], pair[1] } else { reportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str) return "error-apex", "error-jar" } } func CreateConfiguredJarList(ctx PathContext, list []string) ConfiguredJarList { apexes := make([]string, 0, len(list)) jars := make([]string, 0, len(list)) l := ConfiguredJarList{apexes, jars} for _, apexjar := range list { apex, jar := splitConfiguredJarPair(ctx, apexjar) l.Append(apex, jar) } return l } func EmptyConfiguredJarList() ConfiguredJarList { return ConfiguredJarList{} } var earlyBootJarsKey = NewOnceKey("earlyBootJars") func (c *config) BootJars() []string { return c.Once(earlyBootJarsKey, func() interface{} { ctx := NullPathContext{Config{c}} list := CreateConfiguredJarList(ctx, append(CopyOf(c.productVariables.BootJars), c.productVariables.UpdatableBootJars...)) return list.CopyOfJars() }).([]string) } apex/apex_test.go +13 −11 Original line number Diff line number Diff line Loading @@ -5602,13 +5602,15 @@ func TestUpdatable_should_set_min_sdk_version(t *testing.T) { } func TestNoUpdatableJarsInBootImage(t *testing.T) { var err string var transform func(*dexpreopt.GlobalConfig) config := android.TestArchConfig(buildDir, nil, "", nil) ctx := android.PathContextForTesting(config) t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"com.android.art.something:some-art-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading @@ -5616,7 +5618,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) { err = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"com.android.art.something:some-art-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5624,7 +5626,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"some-updatable-apex:some-updatable-apex-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5632,7 +5634,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { err = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5640,14 +5642,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) { err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"some-updatable-apex:some-updatable-apex-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading @@ -5655,7 +5657,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) { err = "failed to find a dex jar path for module 'nonexistent'" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"platform:nonexistent"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5663,7 +5665,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) { err = "failed to find a dex jar path for module 'nonexistent'" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"platform:nonexistent"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5671,14 +5673,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("platform jar in the ART boot image => error", func(t *testing.T) { err = "module 'some-platform-lib' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"platform:some-platform-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) t.Run("platform jar in the framework boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"platform:some-platform-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading dexpreopt/config.go +21 −13 Original line number Diff line number Diff line Loading @@ -40,14 +40,14 @@ type GlobalConfig struct { DisableGenerateProfile bool // don't generate profiles ProfileDir string // directory to find profiles in BootJars []string // modules for jars that form the boot class path UpdatableBootJars []string // jars within apex that form the boot class path BootJars android.ConfiguredJarList // modules for jars that form the boot class path UpdatableBootJars android.ConfiguredJarList // jars within apex that form the boot class path ArtApexJars []string // modules for jars that are in the ART APEX ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX SystemServerJars []string // jars that form the system server SystemServerApps []string // apps that are loaded into system server UpdatableSystemServerJars []string // jars within apex that are loaded into system server UpdatableSystemServerJars android.ConfiguredJarList // jars within apex that are loaded into system server SpeedApps []string // apps that should be speed optimized BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error Loading Loading @@ -189,6 +189,10 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err // Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be // used to construct the real value manually below. BootJars []string UpdatableBootJars []string ArtApexJars []string UpdatableSystemServerJars []string DirtyImageObjects string BootImageProfiles []string } Loading @@ -200,6 +204,10 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err } // Construct paths that require a PathContext. config.GlobalConfig.BootJars = android.CreateConfiguredJarList(ctx, config.BootJars) config.GlobalConfig.UpdatableBootJars = android.CreateConfiguredJarList(ctx, config.UpdatableBootJars) config.GlobalConfig.ArtApexJars = android.CreateConfiguredJarList(ctx, config.ArtApexJars) config.GlobalConfig.UpdatableSystemServerJars = android.CreateConfiguredJarList(ctx, config.UpdatableSystemServerJars) config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects)) config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) Loading Loading @@ -530,12 +538,12 @@ func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { PatternsOnSystemOther: nil, DisableGenerateProfile: false, ProfileDir: "", BootJars: nil, UpdatableBootJars: nil, ArtApexJars: nil, BootJars: android.EmptyConfiguredJarList(), UpdatableBootJars: android.EmptyConfiguredJarList(), ArtApexJars: android.EmptyConfiguredJarList(), SystemServerJars: nil, SystemServerApps: nil, UpdatableSystemServerJars: nil, UpdatableSystemServerJars: android.EmptyConfiguredJarList(), SpeedApps: nil, PreoptFlags: nil, DefaultCompilerFilter: "", Loading dexpreopt/dexpreopt.go +5 −14 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConf if !dexpreoptDisabled(ctx, global, module) { // Don't preopt individual boot jars, they will be preopted together. if !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) { if !global.BootJars.ContainsJar(module.Name) { appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) && !module.NoCreateAppImage Loading @@ -104,17 +104,15 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo } // Don't preopt system server jars that are updatable. for _, p := range global.UpdatableSystemServerJars { if _, jar := android.SplitApexJarPair(ctx, p); jar == module.Name { if global.UpdatableSystemServerJars.ContainsJar(module.Name) { return true } } // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip // Also preopt system server jars since selinux prevents system server from loading anything from // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage // or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options. if global.OnlyPreoptBootImageAndSystemServer && !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) && if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) && !contains(global.SystemServerJars, module.Name) && !module.PreoptExtractedApk { return true } Loading Loading @@ -571,20 +569,13 @@ func makefileMatch(pattern, s string) bool { } } // Expected format for apexJarValue = <apex name>:<jar name> func GetJarLocationFromApexJarPair(ctx android.PathContext, apexJarValue string) string { apex, jar := android.SplitApexJarPair(ctx, apexJarValue) return filepath.Join("/apex", apex, "javalib", jar+".jar") } var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServerJars") // TODO: eliminate the superficial global config parameter by moving global config definition // from java subpackage to dexpreopt. func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string { return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} { return android.RemoveListFromList(global.SystemServerJars, android.GetJarsFromApexJarPairs(ctx, global.UpdatableSystemServerJars)) return android.RemoveListFromList(global.SystemServerJars, global.UpdatableSystemServerJars.CopyOfJars()) }).([]string) } Loading java/dexpreopt_bootjars.go +11 −11 Original line number Diff line number Diff line Loading @@ -49,8 +49,8 @@ type bootImageConfig struct { // Subdirectory where the image files are installed. installSubdir string // The names of jars that constitute this image. modules []string // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList // File paths to jars. dexPaths android.WritablePaths // for this image Loading Loading @@ -113,16 +113,16 @@ func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string // Dexpreopt on the boot class path produces multiple files. The first dex file // is converted into 'name'.art (to match the legacy assumption that 'name'.art // exists), and the rest are converted to 'name'-<jar>.art. _, m := android.SplitApexJarPair(ctx, image.modules[idx]) m := image.modules.Jar(idx) name := image.stem if idx != 0 || image.extends != nil { name += "-" + stemOf(m) name += "-" + android.ModuleStem(m) } return name } func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string { if len(image.modules) > 0 { if image.modules.Len() > 0 { return image.moduleName(ctx, 0) } else { return image.stem Loading @@ -130,8 +130,8 @@ func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) stri } func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths { ret := make(android.OutputPaths, 0, len(image.modules)*len(exts)) for i := range image.modules { ret := make(android.OutputPaths, 0, image.modules.Len()*len(exts)) for i := 0; i < image.modules.Len(); i++ { name := image.moduleName(ctx, i) for _, ext := range exts { ret = append(ret, dir.Join(ctx, name+ext)) Loading Loading @@ -253,7 +253,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul } name := ctx.ModuleName(module) index := android.IndexList(name, android.GetJarsFromApexJarPairs(ctx, image.modules)) index := image.modules.IndexOfJar(name) if index == -1 { return -1, nil } Loading Loading @@ -295,7 +295,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig { // Collect dex jar paths for the boot image modules. // This logic is tested in the apex package to avoid import cycle apex <-> java. bootDexJars := make(android.Paths, len(image.modules)) bootDexJars := make(android.Paths, image.modules.Len()) ctx.VisitAllModules(func(module android.Module) { if i, j := getBootImageJar(ctx, image, module); i != -1 { bootDexJars[i] = j Loading @@ -306,7 +306,7 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI // Ensure all modules were converted to paths for i := range bootDexJars { if bootDexJars[i] == nil { _, m := android.SplitApexJarPair(ctx, image.modules[i]) m := image.modules.Jar(i) if ctx.Config().AllowMissingDependencies() { missingDeps = append(missingDeps, m) bootDexJars[i] = android.PathForOutput(ctx, "missing") Loading Loading @@ -608,7 +608,7 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} { global := dexpreopt.GetGlobalConfig(ctx) updatableModules := android.GetJarsFromApexJarPairs(ctx, global.UpdatableBootJars) updatableModules := global.UpdatableBootJars.CopyOfJars() // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string Loading Loading
android/config.go +178 −28 Original line number Diff line number Diff line Loading @@ -913,34 +913,6 @@ func (c *config) ModulesLoadedByPrivilegedModules() []string { return c.productVariables.ModulesLoadedByPrivilegedModules } // Expected format for apexJarValue = <apex name>:<jar name> func SplitApexJarPair(ctx PathContext, str string) (string, string) { pair := strings.SplitN(str, ":", 2) if len(pair) == 2 { return pair[0], pair[1] } else { reportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str) return "error-apex", "error-jar" } } func GetJarsFromApexJarPairs(ctx PathContext, apexJarPairs []string) []string { modules := make([]string, len(apexJarPairs)) for i, p := range apexJarPairs { _, jar := SplitApexJarPair(ctx, p) modules[i] = jar } return modules } func (c *config) BootJars() []string { ctx := NullPathContext{Config{ config: c, }} return append(GetJarsFromApexJarPairs(ctx, c.productVariables.BootJars), GetJarsFromApexJarPairs(ctx, c.productVariables.UpdatableBootJars)...) } func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) { if c.productVariables.DexpreoptGlobalConfig == nil { return nil, nil Loading Loading @@ -1275,3 +1247,181 @@ func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool { func (c *deviceConfig) BoardKernelBinaries() []string { return c.config.productVariables.BoardKernelBinaries } // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs. // Such lists are used in the build system for things like bootclasspath jars or system server jars. // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a // module name. The pairs come from Make product variables as a list of colon-separated strings. // // Examples: // - "com.android.art:core-oj" // - "platform:framework" // - "system_ext:foo" // type ConfiguredJarList struct { apexes []string // A list of apex components. jars []string // A list of jar components. } // The length of the list. func (l *ConfiguredJarList) Len() int { return len(l.jars) } // Apex component of idx-th pair on the list. func (l *ConfiguredJarList) apex(idx int) string { return l.apexes[idx] } // Jar component of idx-th pair on the list. func (l *ConfiguredJarList) Jar(idx int) string { return l.jars[idx] } // If the list contains a pair with the given jar. func (l *ConfiguredJarList) ContainsJar(jar string) bool { return InList(jar, l.jars) } // If the list contains the given (apex, jar) pair. func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool { for i := 0; i < l.Len(); i++ { if apex == l.apex(i) && jar == l.Jar(i) { return true } } return false } // Index of the first pair with the given jar on the list, or -1 if none. func (l *ConfiguredJarList) IndexOfJar(jar string) int { return IndexList(jar, l.jars) } // Append an (apex, jar) pair to the list. func (l *ConfiguredJarList) Append(apex string, jar string) { l.apexes = append(l.apexes, apex) l.jars = append(l.jars, jar) } // Filter out sublist. func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) { apexes := make([]string, 0, l.Len()) jars := make([]string, 0, l.Len()) for i, jar := range l.jars { apex := l.apex(i) if !list.containsApexJarPair(apex, jar) { apexes = append(apexes, apex) jars = append(jars, jar) } } l.apexes = apexes l.jars = jars } // A copy of itself. func (l *ConfiguredJarList) CopyOf() ConfiguredJarList { return ConfiguredJarList{CopyOf(l.apexes), CopyOf(l.jars)} } // A copy of the list of strings containing jar components. func (l *ConfiguredJarList) CopyOfJars() []string { return CopyOf(l.jars) } // A copy of the list of strings with colon-separated (apex, jar) pairs. func (l *ConfiguredJarList) CopyOfApexJarPairs() []string { pairs := make([]string, 0, l.Len()) for i, jar := range l.jars { apex := l.apex(i) pairs = append(pairs, apex+":"+jar) } return pairs } // A list of build paths based on the given directory prefix. func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths { paths := make(WritablePaths, l.Len()) for i, jar := range l.jars { paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar") } return paths } func ModuleStem(module string) string { // b/139391334: the stem of framework-minus-apex is framework. This is hard coded here until we // find a good way to query the stem of a module before any other mutators are run. if module == "framework-minus-apex" { return "framework" } return module } // A list of on-device paths. func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string { paths := make([]string, l.Len()) for i, jar := range l.jars { apex := l.apexes[i] name := ModuleStem(jar) + ".jar" var subdir string if apex == "platform" { subdir = "system/framework" } else if apex == "system_ext" { subdir = "system_ext/framework" } else { subdir = filepath.Join("apex", apex, "javalib") } if ostype.Class == Host { paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name) } else { paths[i] = filepath.Join("/", subdir, name) } } return paths } // Expected format for apexJarValue = <apex name>:<jar name> func splitConfiguredJarPair(ctx PathContext, str string) (string, string) { pair := strings.SplitN(str, ":", 2) if len(pair) == 2 { return pair[0], pair[1] } else { reportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str) return "error-apex", "error-jar" } } func CreateConfiguredJarList(ctx PathContext, list []string) ConfiguredJarList { apexes := make([]string, 0, len(list)) jars := make([]string, 0, len(list)) l := ConfiguredJarList{apexes, jars} for _, apexjar := range list { apex, jar := splitConfiguredJarPair(ctx, apexjar) l.Append(apex, jar) } return l } func EmptyConfiguredJarList() ConfiguredJarList { return ConfiguredJarList{} } var earlyBootJarsKey = NewOnceKey("earlyBootJars") func (c *config) BootJars() []string { return c.Once(earlyBootJarsKey, func() interface{} { ctx := NullPathContext{Config{c}} list := CreateConfiguredJarList(ctx, append(CopyOf(c.productVariables.BootJars), c.productVariables.UpdatableBootJars...)) return list.CopyOfJars() }).([]string) }
apex/apex_test.go +13 −11 Original line number Diff line number Diff line Loading @@ -5602,13 +5602,15 @@ func TestUpdatable_should_set_min_sdk_version(t *testing.T) { } func TestNoUpdatableJarsInBootImage(t *testing.T) { var err string var transform func(*dexpreopt.GlobalConfig) config := android.TestArchConfig(buildDir, nil, "", nil) ctx := android.PathContextForTesting(config) t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"com.android.art.something:some-art-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading @@ -5616,7 +5618,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) { err = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"com.android.art.something:some-art-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5624,7 +5626,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"some-updatable-apex:some-updatable-apex-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5632,7 +5634,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { err = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5640,14 +5642,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) { err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"some-updatable-apex:some-updatable-apex-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading @@ -5655,7 +5657,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) { err = "failed to find a dex jar path for module 'nonexistent'" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"platform:nonexistent"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5663,7 +5665,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) { err = "failed to find a dex jar path for module 'nonexistent'" transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"platform:nonexistent"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) Loading @@ -5671,14 +5673,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("platform jar in the ART boot image => error", func(t *testing.T) { err = "module 'some-platform-lib' is not allowed in the ART boot image" transform = func(config *dexpreopt.GlobalConfig) { config.ArtApexJars = []string{"platform:some-platform-lib"} config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"}) } testNoUpdatableJarsInBootImage(t, err, transform) }) t.Run("platform jar in the framework boot image => ok", func(t *testing.T) { transform = func(config *dexpreopt.GlobalConfig) { config.BootJars = []string{"platform:some-platform-lib"} config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"}) } testNoUpdatableJarsInBootImage(t, "", transform) }) Loading
dexpreopt/config.go +21 −13 Original line number Diff line number Diff line Loading @@ -40,14 +40,14 @@ type GlobalConfig struct { DisableGenerateProfile bool // don't generate profiles ProfileDir string // directory to find profiles in BootJars []string // modules for jars that form the boot class path UpdatableBootJars []string // jars within apex that form the boot class path BootJars android.ConfiguredJarList // modules for jars that form the boot class path UpdatableBootJars android.ConfiguredJarList // jars within apex that form the boot class path ArtApexJars []string // modules for jars that are in the ART APEX ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX SystemServerJars []string // jars that form the system server SystemServerApps []string // apps that are loaded into system server UpdatableSystemServerJars []string // jars within apex that are loaded into system server UpdatableSystemServerJars android.ConfiguredJarList // jars within apex that are loaded into system server SpeedApps []string // apps that should be speed optimized BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error Loading Loading @@ -189,6 +189,10 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err // Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be // used to construct the real value manually below. BootJars []string UpdatableBootJars []string ArtApexJars []string UpdatableSystemServerJars []string DirtyImageObjects string BootImageProfiles []string } Loading @@ -200,6 +204,10 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err } // Construct paths that require a PathContext. config.GlobalConfig.BootJars = android.CreateConfiguredJarList(ctx, config.BootJars) config.GlobalConfig.UpdatableBootJars = android.CreateConfiguredJarList(ctx, config.UpdatableBootJars) config.GlobalConfig.ArtApexJars = android.CreateConfiguredJarList(ctx, config.ArtApexJars) config.GlobalConfig.UpdatableSystemServerJars = android.CreateConfiguredJarList(ctx, config.UpdatableSystemServerJars) config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects)) config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) Loading Loading @@ -530,12 +538,12 @@ func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { PatternsOnSystemOther: nil, DisableGenerateProfile: false, ProfileDir: "", BootJars: nil, UpdatableBootJars: nil, ArtApexJars: nil, BootJars: android.EmptyConfiguredJarList(), UpdatableBootJars: android.EmptyConfiguredJarList(), ArtApexJars: android.EmptyConfiguredJarList(), SystemServerJars: nil, SystemServerApps: nil, UpdatableSystemServerJars: nil, UpdatableSystemServerJars: android.EmptyConfiguredJarList(), SpeedApps: nil, PreoptFlags: nil, DefaultCompilerFilter: "", Loading
dexpreopt/dexpreopt.go +5 −14 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConf if !dexpreoptDisabled(ctx, global, module) { // Don't preopt individual boot jars, they will be preopted together. if !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) { if !global.BootJars.ContainsJar(module.Name) { appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) && !module.NoCreateAppImage Loading @@ -104,17 +104,15 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo } // Don't preopt system server jars that are updatable. for _, p := range global.UpdatableSystemServerJars { if _, jar := android.SplitApexJarPair(ctx, p); jar == module.Name { if global.UpdatableSystemServerJars.ContainsJar(module.Name) { return true } } // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip // Also preopt system server jars since selinux prevents system server from loading anything from // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage // or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options. if global.OnlyPreoptBootImageAndSystemServer && !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) && if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) && !contains(global.SystemServerJars, module.Name) && !module.PreoptExtractedApk { return true } Loading Loading @@ -571,20 +569,13 @@ func makefileMatch(pattern, s string) bool { } } // Expected format for apexJarValue = <apex name>:<jar name> func GetJarLocationFromApexJarPair(ctx android.PathContext, apexJarValue string) string { apex, jar := android.SplitApexJarPair(ctx, apexJarValue) return filepath.Join("/apex", apex, "javalib", jar+".jar") } var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServerJars") // TODO: eliminate the superficial global config parameter by moving global config definition // from java subpackage to dexpreopt. func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string { return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} { return android.RemoveListFromList(global.SystemServerJars, android.GetJarsFromApexJarPairs(ctx, global.UpdatableSystemServerJars)) return android.RemoveListFromList(global.SystemServerJars, global.UpdatableSystemServerJars.CopyOfJars()) }).([]string) } Loading
java/dexpreopt_bootjars.go +11 −11 Original line number Diff line number Diff line Loading @@ -49,8 +49,8 @@ type bootImageConfig struct { // Subdirectory where the image files are installed. installSubdir string // The names of jars that constitute this image. modules []string // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList // File paths to jars. dexPaths android.WritablePaths // for this image Loading Loading @@ -113,16 +113,16 @@ func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string // Dexpreopt on the boot class path produces multiple files. The first dex file // is converted into 'name'.art (to match the legacy assumption that 'name'.art // exists), and the rest are converted to 'name'-<jar>.art. _, m := android.SplitApexJarPair(ctx, image.modules[idx]) m := image.modules.Jar(idx) name := image.stem if idx != 0 || image.extends != nil { name += "-" + stemOf(m) name += "-" + android.ModuleStem(m) } return name } func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string { if len(image.modules) > 0 { if image.modules.Len() > 0 { return image.moduleName(ctx, 0) } else { return image.stem Loading @@ -130,8 +130,8 @@ func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) stri } func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths { ret := make(android.OutputPaths, 0, len(image.modules)*len(exts)) for i := range image.modules { ret := make(android.OutputPaths, 0, image.modules.Len()*len(exts)) for i := 0; i < image.modules.Len(); i++ { name := image.moduleName(ctx, i) for _, ext := range exts { ret = append(ret, dir.Join(ctx, name+ext)) Loading Loading @@ -253,7 +253,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul } name := ctx.ModuleName(module) index := android.IndexList(name, android.GetJarsFromApexJarPairs(ctx, image.modules)) index := image.modules.IndexOfJar(name) if index == -1 { return -1, nil } Loading Loading @@ -295,7 +295,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig { // Collect dex jar paths for the boot image modules. // This logic is tested in the apex package to avoid import cycle apex <-> java. bootDexJars := make(android.Paths, len(image.modules)) bootDexJars := make(android.Paths, image.modules.Len()) ctx.VisitAllModules(func(module android.Module) { if i, j := getBootImageJar(ctx, image, module); i != -1 { bootDexJars[i] = j Loading @@ -306,7 +306,7 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI // Ensure all modules were converted to paths for i := range bootDexJars { if bootDexJars[i] == nil { _, m := android.SplitApexJarPair(ctx, image.modules[i]) m := image.modules.Jar(i) if ctx.Config().AllowMissingDependencies() { missingDeps = append(missingDeps, m) bootDexJars[i] = android.PathForOutput(ctx, "missing") Loading Loading @@ -608,7 +608,7 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} { global := dexpreopt.GetGlobalConfig(ctx) updatableModules := android.GetJarsFromApexJarPairs(ctx, global.UpdatableBootJars) updatableModules := global.UpdatableBootJars.CopyOfJars() // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string Loading