diff options
85 files changed, 10034 insertions, 1135 deletions
diff --git a/Android.bp b/Android.bp index 342ca4ca9..73fad2500 100644 --- a/Android.bp +++ b/Android.bp @@ -289,6 +289,7 @@ bootstrap_go_package { "soong-dexpreopt", "soong-genrule", "soong-java-config", + "soong-remoteexec", "soong-tradefed", ], srcs: [ @@ -492,6 +493,7 @@ bootstrap_go_package { srcs: [ "apex/androidmk.go", "apex/apex.go", + "apex/apex_singleton.go", "apex/builder.go", "apex/key.go", "apex/prebuilt.go", @@ -289,6 +289,9 @@ Each rule in the property must be in one of the following forms: * `["//visibility:public"]`: Anyone can use this module. * `["//visibility:private"]`: Only rules in the module's package (not its subpackages) can use this module. +* `["//visibility:override"]`: Discards any rules inherited from defaults or a +creating module. Can only be used at the beginning of a list of visibility +rules. * `["//some/package:__pkg__", "//other/package:__pkg__"]`: Only modules in `some/package` and `other/package` (defined in `some/package/*.bp` and `other/package/*.bp`) have access to this module. Note that sub-packages do not diff --git a/android/apex.go b/android/apex.go index 9056c3de7..30152db29 100644 --- a/android/apex.go +++ b/android/apex.go @@ -421,21 +421,16 @@ type ApexModuleDepInfo struct { type DepNameToDepInfoMap map[string]ApexModuleDepInfo type ApexBundleDepsInfo struct { - minSdkVersion string - flatListPath OutputPath - fullListPath OutputPath + flatListPath OutputPath + fullListPath OutputPath } -type ApexDepsInfoIntf interface { - MinSdkVersion() string +type ApexBundleDepsInfoIntf interface { + Updatable() bool FlatListPath() Path FullListPath() Path } -func (d *ApexBundleDepsInfo) MinSdkVersion() string { - return d.minSdkVersion -} - func (d *ApexBundleDepsInfo) FlatListPath() Path { return d.flatListPath } @@ -444,14 +439,10 @@ func (d *ApexBundleDepsInfo) FullListPath() Path { return d.fullListPath } -var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil) - // Generate two module out files: // 1. FullList with transitive deps and their parents in the dep graph // 2. FlatList with a flat list of transitive deps func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) { - d.minSdkVersion = minSdkVersion - var fullContent strings.Builder var flatContent strings.Builder diff --git a/android/config.go b/android/config.go index ee31c1003..59118ce86 100644 --- a/android/config.go +++ b/android/config.go @@ -897,27 +897,31 @@ func (c *config) ModulesLoadedByPrivilegedModules() []string { } // Expected format for apexJarValue = <apex name>:<jar name> -func SplitApexJarPair(apexJarValue string) (string, string) { - var apexJarPair []string = strings.SplitN(apexJarValue, ":", 2) - if apexJarPair == nil || len(apexJarPair) != 2 { - panic(fmt.Errorf("malformed apexJarValue: %q, expected format: <apex>:<jar>", - apexJarValue)) +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" } - return apexJarPair[0], apexJarPair[1] } -func GetJarsFromApexJarPairs(apexJarPairs []string) []string { +func GetJarsFromApexJarPairs(ctx PathContext, apexJarPairs []string) []string { modules := make([]string, len(apexJarPairs)) for i, p := range apexJarPairs { - _, jar := SplitApexJarPair(p) + _, jar := SplitApexJarPair(ctx, p) modules[i] = jar } return modules } func (c *config) BootJars() []string { - return append(GetJarsFromApexJarPairs(c.productVariables.BootJars), - GetJarsFromApexJarPairs(c.productVariables.UpdatableBootJars)...) + 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) { diff --git a/android/env.go b/android/env.go index 46bd3d6c5..c7c96d5cf 100644 --- a/android/env.go +++ b/android/env.go @@ -15,9 +15,11 @@ package android import ( + "fmt" "os" "os/exec" "strings" + "syscall" "android/soong/env" ) @@ -30,28 +32,59 @@ import ( // a manifest regeneration. var originalEnv map[string]string -var SoongDelveListen string -var SoongDelvePath string +var soongDelveListen string +var soongDelvePath string +var soongDelveEnv []string func init() { // Delve support needs to read this environment variable very early, before NewConfig has created a way to // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually // ensure the dependencies are created. - SoongDelveListen = os.Getenv("SOONG_DELVE") - SoongDelvePath, _ = exec.LookPath("dlv") + soongDelveListen = os.Getenv("SOONG_DELVE") + soongDelvePath, _ = exec.LookPath("dlv") originalEnv = make(map[string]string) + soongDelveEnv = []string{} for _, env := range os.Environ() { idx := strings.IndexRune(env, '=') if idx != -1 { originalEnv[env[:idx]] = env[idx+1:] + if env[:idx] != "SOONG_DELVE" { + soongDelveEnv = append(soongDelveEnv, env) + } } } + // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc. os.Clearenv() } +func ReexecWithDelveMaybe() { + if soongDelveListen == "" { + return + } + + if soongDelvePath == "" { + fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") + os.Exit(1) + } + dlvArgv := []string{ + soongDelvePath, + "--listen=:" + soongDelveListen, + "--headless=true", + "--api-version=2", + "exec", + os.Args[0], + "--", + } + dlvArgv = append(dlvArgv, os.Args[1:]...) + os.Chdir(absSrcDir) + syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv) + fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve") + os.Exit(1) +} + // getenv checks either os.Getenv or originalEnv so that it works before or after the init() // function above. It doesn't add any dependencies on the environment variable, so it should // only be used for values that won't change. For values that might change use ctx.Config().Getenv. diff --git a/android/module.go b/android/module.go index e431adaf4..82321f417 100644 --- a/android/module.go +++ b/android/module.go @@ -104,11 +104,15 @@ type EarlyModuleContext interface { type BaseModuleContext interface { EarlyModuleContext + blueprintBaseModuleContext() blueprint.BaseModuleContext + OtherModuleName(m blueprint.Module) string OtherModuleDir(m blueprint.Module) string OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag OtherModuleExists(name string) bool + OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool + OtherModuleReverseDependencyVariantExists(name string) bool OtherModuleType(m blueprint.Module) string GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module @@ -257,9 +261,6 @@ type Module interface { // Get information about the properties that can contain visibility rules. visibilityProperties() []visibilityProperty - // Get the visibility rules that control the visibility of this module. - visibility() []string - RequiredModuleNames() []string HostRequiredModuleNames() []string TargetRequiredModuleNames() []string @@ -331,6 +332,8 @@ type commonProperties struct { // ["//visibility:public"]: Anyone can use this module. // ["//visibility:private"]: Only rules in the module's package (not its subpackages) can use // this module. + // ["//visibility:override"]: Discards any rules inherited from defaults or a creating module. + // Can only be used at the beginning of a list of visibility rules. // ["//some/package:__pkg__", "//other/package:__pkg__"]: Only modules in some/package and // other/package (defined in some/package/*.bp and other/package/*.bp) have access to // this module. Note that sub-packages do not have access to the rule; for example, @@ -807,15 +810,6 @@ func (m *ModuleBase) visibilityProperties() []visibilityProperty { return m.visibilityPropertyInfo } -func (m *ModuleBase) visibility() []string { - // The soong_namespace module does not initialize the primaryVisibilityProperty. - if m.primaryVisibilityProperty != nil { - return m.primaryVisibilityProperty.getStrings() - } else { - return nil - } -} - func (m *ModuleBase) Target() Target { return m.commonProperties.CompileTarget } @@ -908,6 +902,13 @@ func (m *ModuleBase) SystemExtSpecific() bool { return Bool(m.commonProperties.System_ext_specific) } +// RequiresStableAPIs returns true if the module will be installed to a partition that may +// be updated separately from the system image. +func (m *ModuleBase) RequiresStableAPIs(ctx BaseModuleContext) bool { + return m.SocSpecific() || m.DeviceSpecific() || + (m.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) +} + func (m *ModuleBase) PartitionTag(config DeviceConfig) string { partition := "system" if m.SocSpecific() { @@ -1434,6 +1435,12 @@ func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) bluepri return b.bp.OtherModuleDependencyTag(m) } func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) } +func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool { + return b.bp.OtherModuleDependencyVariantExists(variations, name) +} +func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool { + return b.bp.OtherModuleReverseDependencyVariantExists(name) +} func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) } @@ -1442,6 +1449,10 @@ func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.Depen return b.bp.GetDirectDepWithTag(name, tag) } +func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext { + return b.bp +} + type moduleContext struct { bp blueprint.ModuleContext baseModuleContext @@ -2363,4 +2374,10 @@ type IdeInfo struct { Classes []string `json:"class,omitempty"` Installed_paths []string `json:"installed,omitempty"` SrcJars []string `json:"srcjars,omitempty"` + Paths []string `json:"path,omitempty"` +} + +func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents string) []error { + bpctx := ctx.blueprintBaseModuleContext() + return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents) } diff --git a/android/neverallow.go b/android/neverallow.go index cf09792e0..9e075b719 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -55,6 +55,7 @@ func init() { AddNeverAllowRules(createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...) AddNeverAllowRules(createCcSdkVariantRules()...) + AddNeverAllowRules(createUncompressDexRules()...) } // Add a NeverAllow rule to the set of rules to apply. @@ -141,6 +142,7 @@ func createLibcoreRules() []Rule { "external/icu", "external/okhttp", "external/wycheproof", + "prebuilts", } // Core library constraints. The sdk_version: "none" can only be used in core library projects. @@ -209,6 +211,15 @@ func createCcSdkVariantRules() []Rule { } } +func createUncompressDexRules() []Rule { + return []Rule{ + NeverAllow(). + NotIn("art"). + WithMatcher("uncompress_dex", isSetMatcherInstance). + Because("uncompress_dex is only allowed for certain jars for test in art."), + } +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 2fc42e31f..85c8c5908 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -303,6 +303,29 @@ var neverallowTests = []struct { `module "outside_whitelist": violates neverallow`, }, }, + { + name: "uncompress_dex inside art", + fs: map[string][]byte{ + "art/Android.bp": []byte(` + java_library { + name: "inside_art_libraries", + uncompress_dex: true, + }`), + }, + }, + { + name: "uncompress_dex outside art", + fs: map[string][]byte{ + "other/Android.bp": []byte(` + java_library { + name: "outside_art_libraries", + uncompress_dex: true, + }`), + }, + expectedErrors: []string{ + "module \"outside_art_libraries\": violates neverallow", + }, + }, } func TestNeverallow(t *testing.T) { @@ -396,8 +419,9 @@ func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } type mockJavaLibraryProperties struct { - Libs []string - Sdk_version *string + Libs []string + Sdk_version *string + Uncompress_dex *bool } type mockJavaLibraryModule struct { diff --git a/android/paths.go b/android/paths.go index 8bb9a96dd..3ad27acbe 100644 --- a/android/paths.go +++ b/android/paths.go @@ -43,6 +43,14 @@ type PathGlobContext interface { var _ PathContext = SingletonContext(nil) var _ PathContext = ModuleContext(nil) +// "Null" path context is a minimal path context for a given config. +type NullPathContext struct { + config Config +} + +func (NullPathContext) AddNinjaFileDeps(...string) {} +func (ctx NullPathContext) Config() Config { return ctx.config } + type ModuleInstallPathContext interface { BaseModuleContext @@ -477,6 +485,15 @@ func FirstUniquePaths(list Paths) Paths { return firstUniquePathsList(list) } +// SortedUniquePaths returns what its name says +func SortedUniquePaths(list Paths) Paths { + unique := FirstUniquePaths(list) + sort.Slice(unique, func(i, j int) bool { + return unique[i].String() < unique[j].String() + }) + return unique +} + func firstUniquePathsList(list Paths) Paths { k := 0 outer: diff --git a/android/prebuilt.go b/android/prebuilt.go index 82745a498..a29ec911d 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -52,6 +52,9 @@ type PrebuiltProperties struct { SourceExists bool `blueprint:"mutated"` UsePrebuilt bool `blueprint:"mutated"` + + // Set if the module has been renamed to remove the "prebuilt_" prefix. + PrebuiltRenamedToSource bool `blueprint:"mutated"` } type Prebuilt struct { @@ -69,6 +72,10 @@ func (p *Prebuilt) ForcePrefer() { p.properties.Prefer = proptools.BoolPtr(true) } +func (p *Prebuilt) Prefer() bool { + return proptools.Bool(p.properties.Prefer) +} + // The below source-related functions and the srcs, src fields are based on an assumption that // prebuilt modules have a static source property at the moment. Currently there is only one // exception, android_app_import, which chooses a source file depending on the product's DPI @@ -184,25 +191,38 @@ type PrebuiltInterface interface { } func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { - ctx.BottomUp("prebuilts", PrebuiltMutator).Parallel() + ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel() } func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { + ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel() ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel() } -// PrebuiltMutator ensures that there is always a module with an undecorated name, and marks -// prebuilt modules that have both a prebuilt and a source module. -func PrebuiltMutator(ctx BottomUpMutatorContext) { +// PrebuiltRenameMutator ensures that there always is a module with an +// undecorated name. +func PrebuiltRenameMutator(ctx BottomUpMutatorContext) { if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { - p := m.Prebuilt() name := m.base().BaseModuleName() - if ctx.OtherModuleExists(name) { - ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name) - p.properties.SourceExists = true - } else { + if !ctx.OtherModuleExists(name) { ctx.Rename(name) + m.Prebuilt().properties.PrebuiltRenamedToSource = true + } + } +} + +// PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the +// corresponding source module, if one exists for the same variant. +func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { + if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { + p := m.Prebuilt() + if !p.properties.PrebuiltRenamedToSource { + name := m.base().BaseModuleName() + if ctx.OtherModuleReverseDependencyVariantExists(name) { + ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name) + p.properties.SourceExists = true + } } } } diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go index 3dea6d8f6..f0c0767b6 100644 --- a/android/prebuilt_etc.go +++ b/android/prebuilt_etc.go @@ -49,6 +49,9 @@ type prebuiltEtcProperties struct { // Whether this module is directly installable to one of the partitions. Default: true. Installable *bool + + // Install symlinks to the installed file. + Symlinks []string `android:"arch_variant"` } type PrebuiltEtcModule interface { @@ -201,10 +204,13 @@ func (p *PrebuiltEtc) AndroidMkEntries() []AndroidMkEntries { entries.SetString("LOCAL_MODULE_TAGS", "optional") entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String()) entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base()) + if len(p.properties.Symlinks) > 0 { + entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...) + } entries.SetString("LOCAL_UNINSTALLABLE_MODULE", strconv.FormatBool(!p.Installable())) if p.additionalDependencies != nil { for _, path := range *p.additionalDependencies { - entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", path.String()) + entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", path.String()) } } }, diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 8ff5c4034..b568f781d 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -24,7 +24,7 @@ import ( var prebuiltsTests = []struct { name string modules string - prebuilt bool + prebuilt []OsClass }{ { name: "no prebuilt", @@ -32,7 +32,7 @@ var prebuiltsTests = []struct { source { name: "bar", }`, - prebuilt: false, + prebuilt: nil, }, { name: "no source prebuilt not preferred", @@ -42,7 +42,7 @@ var prebuiltsTests = []struct { prefer: false, srcs: ["prebuilt_file"], }`, - prebuilt: true, + prebuilt: []OsClass{Device, Host}, }, { name: "no source prebuilt preferred", @@ -52,7 +52,7 @@ var prebuiltsTests = []struct { prefer: true, srcs: ["prebuilt_file"], }`, - prebuilt: true, + prebuilt: []OsClass{Device, Host}, }, { name: "prebuilt not preferred", @@ -60,13 +60,13 @@ var prebuiltsTests = []struct { source { name: "bar", } - + prebuilt { name: "bar", prefer: false, srcs: ["prebuilt_file"], }`, - prebuilt: false, + prebuilt: nil, }, { name: "prebuilt preferred", @@ -74,13 +74,13 @@ var prebuiltsTests = []struct { source { name: "bar", } - + prebuilt { name: "bar", prefer: true, srcs: ["prebuilt_file"], }`, - prebuilt: true, + prebuilt: []OsClass{Device, Host}, }, { name: "prebuilt no file not preferred", @@ -88,12 +88,12 @@ var prebuiltsTests = []struct { source { name: "bar", } - + prebuilt { name: "bar", prefer: false, }`, - prebuilt: false, + prebuilt: nil, }, { name: "prebuilt no file preferred", @@ -101,12 +101,12 @@ var prebuiltsTests = []struct { source { name: "bar", } - + prebuilt { name: "bar", prefer: true, }`, - prebuilt: false, + prebuilt: nil, }, { name: "prebuilt file from filegroup preferred", @@ -120,7 +120,40 @@ var prebuiltsTests = []struct { prefer: true, srcs: [":fg"], }`, - prebuilt: true, + prebuilt: []OsClass{Device, Host}, + }, + { + name: "prebuilt module for device only", + modules: ` + source { + name: "bar", + } + + prebuilt { + name: "bar", + host_supported: false, + prefer: true, + srcs: ["prebuilt_file"], + }`, + prebuilt: []OsClass{Device}, + }, + { + name: "prebuilt file for host only", + modules: ` + source { + name: "bar", + } + + prebuilt { + name: "bar", + prefer: true, + target: { + host: { + srcs: ["prebuilt_file"], + }, + }, + }`, + prebuilt: []OsClass{Host}, }, } @@ -138,9 +171,9 @@ func TestPrebuilts(t *testing.T) { deps: [":bar"], } ` + test.modules - config := TestConfig(buildDir, nil, bp, fs) + config := TestArchConfig(buildDir, nil, bp, fs) - ctx := NewTestContext() + ctx := NewTestArchContext() registerTestPrebuiltBuildComponents(ctx) ctx.RegisterModuleType("filegroup", FileGroupFactory) ctx.Register(config) @@ -150,61 +183,71 @@ func TestPrebuilts(t *testing.T) { _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) - foo := ctx.ModuleForTests("foo", "") + for _, variant := range ctx.ModuleVariantsForTests("foo") { + foo := ctx.ModuleForTests("foo", variant) + t.Run(foo.Module().Target().Os.Class.String(), func(t *testing.T) { + var dependsOnSourceModule, dependsOnPrebuiltModule bool + ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) { + if _, ok := m.(*sourceModule); ok { + dependsOnSourceModule = true + } + if p, ok := m.(*prebuiltModule); ok { + dependsOnPrebuiltModule = true + if !p.Prebuilt().properties.UsePrebuilt { + t.Errorf("dependency on prebuilt module not marked used") + } + } + }) - var dependsOnSourceModule, dependsOnPrebuiltModule bool - ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) { - if _, ok := m.(*sourceModule); ok { - dependsOnSourceModule = true - } - if p, ok := m.(*prebuiltModule); ok { - dependsOnPrebuiltModule = true - if !p.Prebuilt().properties.UsePrebuilt { - t.Errorf("dependency on prebuilt module not marked used") + deps := foo.Module().(*sourceModule).deps + if deps == nil || len(deps) != 1 { + t.Errorf("deps does not have single path, but is %v", deps) + } + var usingSourceFile, usingPrebuiltFile bool + if deps[0].String() == "source_file" { + usingSourceFile = true + } + if deps[0].String() == "prebuilt_file" { + usingPrebuiltFile = true } - } - }) - deps := foo.Module().(*sourceModule).deps - if deps == nil || len(deps) != 1 { - t.Errorf("deps does not have single path, but is %v", deps) - } - var usingSourceFile, usingPrebuiltFile bool - if deps[0].String() == "source_file" { - usingSourceFile = true - } - if deps[0].String() == "prebuilt_file" { - usingPrebuiltFile = true - } + prebuilt := false + for _, os := range test.prebuilt { + if os == foo.Module().Target().Os.Class { + prebuilt = true + } + } - if test.prebuilt { - if !dependsOnPrebuiltModule { - t.Errorf("doesn't depend on prebuilt module") - } - if !usingPrebuiltFile { - t.Errorf("doesn't use prebuilt_file") - } + if prebuilt { + if !dependsOnPrebuiltModule { + t.Errorf("doesn't depend on prebuilt module") + } + if !usingPrebuiltFile { + t.Errorf("doesn't use prebuilt_file") + } - if dependsOnSourceModule { - t.Errorf("depends on source module") - } - if usingSourceFile { - t.Errorf("using source_file") - } - } else { - if dependsOnPrebuiltModule { - t.Errorf("depends on prebuilt module") - } - if usingPrebuiltFile { - t.Errorf("using prebuilt_file") - } + if dependsOnSourceModule { + t.Errorf("depends on source module") + } + if usingSourceFile { + t.Errorf("using source_file") + } + } else { + if dependsOnPrebuiltModule { + t.Errorf("depends on prebuilt module") + } + if usingPrebuiltFile { + t.Errorf("using prebuilt_file") + } - if !dependsOnSourceModule { - t.Errorf("doesn't depend on source module") - } - if !usingSourceFile { - t.Errorf("doesn't use source_file") - } + if !dependsOnSourceModule { + t.Errorf("doesn't depend on source module") + } + if !usingSourceFile { + t.Errorf("doesn't use source_file") + } + } + }) } }) } @@ -221,7 +264,7 @@ type prebuiltModule struct { ModuleBase prebuilt Prebuilt properties struct { - Srcs []string `android:"path"` + Srcs []string `android:"path,arch_variant"` } src Path } @@ -230,7 +273,7 @@ func newPrebuiltModule() Module { m := &prebuiltModule{} m.AddProperties(&m.properties) InitPrebuiltModule(m, &m.properties.Srcs) - InitAndroidModule(m) + InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) return m } @@ -260,7 +303,7 @@ func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) { type sourceModule struct { ModuleBase properties struct { - Deps []string `android:"path"` + Deps []string `android:"path,arch_variant"` } dependsOnSourceModule, dependsOnPrebuiltModule bool deps Paths @@ -270,7 +313,7 @@ type sourceModule struct { func newSourceModule() Module { m := &sourceModule{} m.AddProperties(&m.properties) - InitAndroidModule(m) + InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) return m } diff --git a/android/visibility.go b/android/visibility.go index 1e3b91ddd..68da1c475 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -140,7 +140,7 @@ func (r packageRule) matches(m qualifiedModuleName) bool { } func (r packageRule) String() string { - return fmt.Sprintf("//%s:__pkg__", r.pkg) + return fmt.Sprintf("//%s", r.pkg) // :__pkg__ is the default, so skip it. } // A subpackagesRule is a visibility rule that matches modules in a specific package (i.e. @@ -245,7 +245,7 @@ func checkRules(ctx BaseModuleContext, currentPkg, property string, visibility [ return } - for _, v := range visibility { + for i, v := range visibility { ok, pkg, name := splitRule(ctx, v, currentPkg, property) if !ok { continue @@ -257,11 +257,18 @@ func checkRules(ctx BaseModuleContext, currentPkg, property string, visibility [ case "legacy_public": ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used") continue + case "override": + // This keyword does not create a rule so pretend it does not exist. + ruleCount -= 1 default: ctx.PropertyErrorf(property, "unrecognized visibility rule %q", v) continue } - if ruleCount != 1 { + if name == "override" { + if i != 0 { + ctx.PropertyErrorf(property, `"%v" may only be used at the start of the visibility rules`, v) + } + } else if ruleCount != 1 { ctx.PropertyErrorf(property, "cannot mix %q with any other visibility rules", v) continue } @@ -327,6 +334,14 @@ func parseRules(ctx BaseModuleContext, currentPkg, property string, visibility [ case "public": r = publicRule{} hasPublicRule = true + case "override": + // Discard all preceding rules and any state based on them. + rules = nil + hasPrivateRule = false + hasPublicRule = false + hasNonPrivateRule = false + // This does not actually create a rule so continue onto the next rule. + continue } } else { switch name { @@ -481,6 +496,24 @@ func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string { rule := effectiveVisibilityRules(ctx.Config(), qualified) + // Modules are implicitly visible to other modules in the same package, + // without checking the visibility rules. Here we need to add that visibility + // explicitly. + if rule != nil && !rule.matches(qualified) { + if len(rule) == 1 { + if _, ok := rule[0].(privateRule); ok { + // If the rule is //visibility:private we can't append another + // visibility to it. Semantically we need to convert it to a package + // visibility rule for the location where the result is used, but since + // modules are implicitly visible within the package we get the same + // result without any rule at all, so just make it an empty list to be + // appended below. + rule = compositeRule{} + } + } + rule = append(rule, packageRule{dir}) + } + return rule.Strings() } diff --git a/android/visibility_test.go b/android/visibility_test.go index 4cf41a6cc..ca0934557 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -636,6 +636,177 @@ var visibilityTests = []struct { }, }, { + name: "//visibility:private override //visibility:public", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:public"], + } + mock_library { + name: "libexample", + visibility: ["//visibility:private"], + defaults: ["libexample_defaults"], + }`), + }, + expectedErrors: []string{ + `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`, + }, + }, + { + name: "//visibility:public override //visibility:private", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:private"], + } + mock_library { + name: "libexample", + visibility: ["//visibility:public"], + defaults: ["libexample_defaults"], + }`), + }, + expectedErrors: []string{ + `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`, + }, + }, + { + name: "//visibility:override must be first in the list", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_library { + name: "libexample", + visibility: ["//other", "//visibility:override", "//namespace"], + }`), + }, + expectedErrors: []string{ + `module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`, + }, + }, + { + name: "//visibility:override discards //visibility:private", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:private"], + } + mock_library { + name: "libexample", + // Make this visibility to //other but not //visibility:private + visibility: ["//visibility:override", "//other"], + defaults: ["libexample_defaults"], + }`), + "other/Blueprints": []byte(` + mock_library { + name: "libother", + deps: ["libexample"], + }`), + }, + }, + { + name: "//visibility:override discards //visibility:public", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:public"], + } + mock_library { + name: "libexample", + // Make this visibility to //other but not //visibility:public + visibility: ["//visibility:override", "//other"], + defaults: ["libexample_defaults"], + }`), + "other/Blueprints": []byte(` + mock_library { + name: "libother", + deps: ["libexample"], + }`), + "namespace/Blueprints": []byte(` + mock_library { + name: "libnamespace", + deps: ["libexample"], + }`), + }, + expectedErrors: []string{ + `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, + }, + }, + { + name: "//visibility:override discards defaults supplied rules", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//namespace"], + } + mock_library { + name: "libexample", + // Make this visibility to //other but not //namespace + visibility: ["//visibility:override", "//other"], + defaults: ["libexample_defaults"], + }`), + "other/Blueprints": []byte(` + mock_library { + name: "libother", + deps: ["libexample"], + }`), + "namespace/Blueprints": []byte(` + mock_library { + name: "libnamespace", + deps: ["libexample"], + }`), + }, + expectedErrors: []string{ + `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, + }, + }, + { + name: "//visibility:override can override //visibility:public with //visibility:private", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:public"], + } + mock_library { + name: "libexample", + visibility: ["//visibility:override", "//visibility:private"], + defaults: ["libexample_defaults"], + }`), + "namespace/Blueprints": []byte(` + mock_library { + name: "libnamespace", + deps: ["libexample"], + }`), + }, + expectedErrors: []string{ + `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, + }, + }, + { + name: "//visibility:override can override //visibility:private with //visibility:public", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "libexample_defaults", + visibility: ["//visibility:private"], + } + mock_library { + name: "libexample", + visibility: ["//visibility:override", "//visibility:public"], + defaults: ["libexample_defaults"], + }`), + "namespace/Blueprints": []byte(` + mock_library { + name: "libnamespace", + deps: ["libexample"], + }`), + }, + }, + { name: "//visibility:private mixed with itself", fs: map[string][]byte{ "top/Blueprints": []byte(` diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go index 5a62324c1..eaf06c59f 100644 --- a/androidmk/androidmk/android.go +++ b/androidmk/androidmk/android.go @@ -40,26 +40,31 @@ type variableAssignmentContext struct { append bool } +var trueValue = &bpparser.Bool{ + Value: true, +} + var rewriteProperties = map[string](func(variableAssignmentContext) error){ // custom functions - "LOCAL_32_BIT_ONLY": local32BitOnly, - "LOCAL_AIDL_INCLUDES": localAidlIncludes, - "LOCAL_ASSET_DIR": localizePathList("asset_dirs"), - "LOCAL_C_INCLUDES": localIncludeDirs, - "LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs, - "LOCAL_JARJAR_RULES": localizePath("jarjar_rules"), - "LOCAL_LDFLAGS": ldflags, - "LOCAL_MODULE_CLASS": prebuiltClass, - "LOCAL_MODULE_STEM": stem, - "LOCAL_MODULE_HOST_OS": hostOs, - "LOCAL_RESOURCE_DIR": localizePathList("resource_dirs"), - "LOCAL_SANITIZE": sanitize(""), - "LOCAL_SANITIZE_DIAG": sanitize("diag."), - "LOCAL_STRIP_MODULE": strip(), - "LOCAL_CFLAGS": cflags, - "LOCAL_UNINSTALLABLE_MODULE": invert("installable"), - "LOCAL_PROGUARD_ENABLED": proguardEnabled, - "LOCAL_MODULE_PATH": prebuiltModulePath, + "LOCAL_32_BIT_ONLY": local32BitOnly, + "LOCAL_AIDL_INCLUDES": localAidlIncludes, + "LOCAL_ASSET_DIR": localizePathList("asset_dirs"), + "LOCAL_C_INCLUDES": localIncludeDirs, + "LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs, + "LOCAL_JARJAR_RULES": localizePath("jarjar_rules"), + "LOCAL_LDFLAGS": ldflags, + "LOCAL_MODULE_CLASS": prebuiltClass, + "LOCAL_MODULE_STEM": stem, + "LOCAL_MODULE_HOST_OS": hostOs, + "LOCAL_RESOURCE_DIR": localizePathList("resource_dirs"), + "LOCAL_SANITIZE": sanitize(""), + "LOCAL_SANITIZE_DIAG": sanitize("diag."), + "LOCAL_STRIP_MODULE": strip(), + "LOCAL_CFLAGS": cflags, + "LOCAL_UNINSTALLABLE_MODULE": invert("installable"), + "LOCAL_PROGUARD_ENABLED": proguardEnabled, + "LOCAL_MODULE_PATH": prebuiltModulePath, + "LOCAL_REPLACE_PREBUILT_APK_INSTALLED": prebuiltPreprocessed, // composite functions "LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))), @@ -495,10 +500,6 @@ func hostOs(ctx variableAssignmentContext) error { Value: false, } - trueValue := &bpparser.Bool{ - Value: true, - } - if inList("windows") { err = setVariable(ctx.file, ctx.append, "target.windows", "enabled", trueValue, true) } @@ -704,6 +705,11 @@ func ldflags(ctx variableAssignmentContext) error { return nil } +func prebuiltPreprocessed(ctx variableAssignmentContext) error { + ctx.mkvalue = ctx.mkvalue.Clone() + return setVariable(ctx.file, false, ctx.prefix, "preprocessed", trueValue, true) +} + func cflags(ctx variableAssignmentContext) error { // The Soong replacement for CFLAGS doesn't need the same extra escaped quotes that were present in Make ctx.mkvalue = ctx.mkvalue.Clone() diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go index d9bde9407..54bd586f9 100644 --- a/androidmk/androidmk/androidmk_test.go +++ b/androidmk/androidmk/androidmk_test.go @@ -1342,6 +1342,31 @@ android_app_import { `, }, { + desc: "android_test_import prebuilt", + in: ` + include $(CLEAR_VARS) + LOCAL_MODULE := foo + LOCAL_SRC_FILES := foo.apk + LOCAL_MODULE_CLASS := APPS + LOCAL_MODULE_TAGS := tests + LOCAL_MODULE_SUFFIX := .apk + LOCAL_CERTIFICATE := PRESIGNED + LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/foo.apk + LOCAL_COMPATIBILITY_SUITE := cts + include $(BUILD_PREBUILT) + `, + expected: ` +android_test_import { + name: "foo", + srcs: ["foo.apk"], + + certificate: "PRESIGNED", + preprocessed: true, + test_suites: ["cts"], +} +`, + }, + { desc: "undefined_boolean_var", in: ` include $(CLEAR_VARS) diff --git a/apex/androidmk.go b/apex/androidmk.go index 2c5407c9e..9321ad261 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -78,6 +78,8 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo } } + seenDataOutPaths := make(map[string]bool) + for _, fi := range a.filesInfo { if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake { continue @@ -112,14 +114,25 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir) if apexType == flattenedApex { // /system/apex/<name>/{lib|framework|...} - fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(), - apexBundleName, fi.installDir)) + modulePath := filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.installDir) + fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath) if a.primaryApexType && !symbolFilesNotNeeded { fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated) } if len(fi.symlinks) > 0 { fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " ")) } + newDataPaths := []android.Path{} + for _, path := range fi.dataPaths { + dataOutPath := modulePath + ":" + path.Rel() + if ok := seenDataOutPaths[dataOutPath]; !ok { + newDataPaths = append(newDataPaths, path) + seenDataOutPaths[dataOutPath] = true + } + } + if len(newDataPaths) > 0 { + fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(cc.AndroidMkDataPaths(newDataPaths), " ")) + } if fi.module != nil && len(fi.module.NoticeFiles()) > 0 { fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " ")) @@ -166,11 +179,11 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String()) } if fi.class == javaSharedLib { - javaModule := fi.module.(javaLibrary) + javaModule := fi.module.(java.Dependency) // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.jar.jar - fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".jar")) + fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".jar")) fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String()) fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String()) fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String()) @@ -181,13 +194,13 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo // soong_app_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .apk Therefore // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.apk.apk - fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".apk")) + fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".apk")) if app, ok := fi.module.(*java.AndroidApp); ok && len(app.JniCoverageOutputs()) > 0 { fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(app.JniCoverageOutputs().Strings(), " ")) } fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk") } else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest { - fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) + fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem()) if cc, ok := fi.module.(*cc.Module); ok { if cc.UnstrippedOutputFile() != nil { fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String()) @@ -199,7 +212,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo } fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk") } else { - fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) + fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem()) if fi.builtFile == a.manifestPbOut && apexType == flattenedApex { if a.primaryApexType { // Make apex_manifest.pb module for this APEX to override all other diff --git a/apex/apex.go b/apex/apex.go index fa71ffa5c..10c16f5b8 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -93,69 +93,6 @@ func makeApexAvailableWhitelist() map[string][]string { // // Module separator // - artApexContents := []string{ - "art_cmdlineparser_headers", - "art_disassembler_headers", - "art_libartbase_headers", - "bionic_libc_platform_headers", - "core-repackaged-icu4j", - "cpp-define-generator-asm-support", - "cpp-define-generator-definitions", - "crtbegin_dynamic", - "crtbegin_dynamic1", - "crtbegin_so1", - "crtbrand", - "dex2oat_headers", - "dt_fd_forward_export", - "icu4c_extra_headers", - "javavm_headers", - "jni_platform_headers", - "libPlatformProperties", - "libadbconnection_client", - "libadbconnection_server", - "libandroidicuinit", - "libart_runtime_headers_ndk", - "libartd-disassembler", - "libdexfile_all_headers", - "libdexfile_external_headers", - "libdexfile_support", - "libdmabufinfo", - "libexpat", - "libfdlibm", - "libicui18n_headers", - "libicuuc", - "libicuuc_headers", - "libicuuc_stubdata", - "libjdwp_headers", - "liblz4", - "liblzma", - "libmeminfo", - "libnativebridge-headers", - "libnativehelper_header_only", - "libnativeloader-headers", - "libnpt_headers", - "libopenjdkjvmti_headers", - "libperfetto_client_experimental", - "libprocinfo", - "libunwind_llvm", - "libunwindstack", - "libv8", - "libv8base", - "libv8gen", - "libv8platform", - "libv8sampler", - "libv8src", - "libvixl", - "libvixld", - "libz", - "libziparchive", - "perfetto_trace_protos", - } - m["com.android.art.debug"] = artApexContents - m["com.android.art.release"] = artApexContents - // - // Module separator - // m["com.android.bluetooth.updatable"] = []string{ "android.hardware.audio.common@5.0", "android.hardware.bluetooth.a2dp@1.0", @@ -244,19 +181,6 @@ func makeApexAvailableWhitelist() map[string][]string { // // Module separator // - m["com.android.extservices"] = []string{ - "flatbuffer_headers", - "liblua", - "libtextclassifier", - "libtextclassifier_hash_static", - "libtflite_static", - "libutf", - "libz_current", - "tensorflow_headers", - } - // - // Module separator - // m["com.android.neuralnetworks"] = []string{ "android.hardware.neuralnetworks@1.0", "android.hardware.neuralnetworks@1.1", @@ -300,7 +224,10 @@ func makeApexAvailableWhitelist() map[string][]string { "android.hidl.token@1.0", "android.hidl.token@1.0-utils", "bionic_libc_platform_headers", + "exoplayer2-extractor", + "exoplayer2-extractor-annotation-stubs", "gl_headers", + "jsr305", "libEGL", "libEGL_blobCache", "libEGL_getProcAddress", @@ -555,12 +482,6 @@ func makeApexAvailableWhitelist() map[string][]string { // Module separator // m["com.android.permission"] = []string{ - "androidx.annotation_annotation", - "androidx.annotation_annotation-nodeps", - "androidx.lifecycle_lifecycle-common", - "androidx.lifecycle_lifecycle-common-java8", - "androidx.lifecycle_lifecycle-common-java8-nodeps", - "androidx.lifecycle_lifecycle-common-nodeps", "kotlin-annotations", "kotlin-stdlib", "kotlin-stdlib-jdk7", @@ -631,13 +552,21 @@ func makeApexAvailableWhitelist() map[string][]string { // Module separator // m["com.android.tethering"] = []string{ - "libnativehelper_compat_libc++", - "android.hardware.tetheroffload.config@1.0", + "android.hardware.tetheroffload.config-V1.0-java", + "android.hardware.tetheroffload.control-V1.0-java", + "android.hidl.base-V1.0-java", + "ipmemorystore-aidl-interfaces-java", "libcgrouprc", "libcgrouprc_format", + "libnativehelper_compat_libc++", "libtetherutilsjni", "libvndksupport", + "net-utils-framework-common", + "netd_aidl_interface-V3-java", + "netlink-client", + "networkstack-aidl-interfaces-java", "tethering-aidl-interfaces-java", + "TetheringApiCurrentLib", } // // Module separator @@ -661,8 +590,6 @@ func makeApexAvailableWhitelist() map[string][]string { "android.hidl.manager-V1.0-java", "android.hidl.manager-V1.1-java", "android.hidl.manager-V1.2-java", - "androidx.annotation_annotation", - "androidx.annotation_annotation-nodeps", "bouncycastle-unbundled", "dnsresolver_aidl_interface-V2-java", "error_prone_annotations", @@ -684,7 +611,6 @@ func makeApexAvailableWhitelist() map[string][]string { "wifi-nano-protos", "wifi-service-pre-jarjar", "wifi-service-resources", - "prebuilt_androidx.annotation_annotation-nodeps", } // // Module separator @@ -704,6 +630,15 @@ func makeApexAvailableWhitelist() map[string][]string { // Module separator // m[android.AvailableToAnyApex] = []string{ + // TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries + "androidx", + "androidx-constraintlayout_constraintlayout", + "androidx-constraintlayout_constraintlayout-nodeps", + "androidx-constraintlayout_constraintlayout-solver", + "androidx-constraintlayout_constraintlayout-solver-nodeps", + "com.google.android.material_material", + "com.google.android.material_material-nodeps", + "libatomic", "libclang_rt", "libgcc_stripped", @@ -723,6 +658,7 @@ func init() { android.RegisterModuleType("apex_defaults", defaultsFactory) android.RegisterModuleType("prebuilt_apex", PrebuiltFactory) android.RegisterModuleType("override_apex", overrideApexFactory) + android.RegisterModuleType("apex_set", apexSetFactory) android.PreDepsMutators(RegisterPreDepsMutators) android.PostDepsMutators(RegisterPostDepsMutators) @@ -759,7 +695,7 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { apexBundles = []android.ApexInfo{{ ApexName: mctx.ModuleName(), MinSdkVersion: a.minSdkVersion(mctx), - Updatable: proptools.Bool(a.properties.Updatable), + Updatable: a.Updatable(), }} directDep = true } else if am, ok := mctx.Module().(android.ApexModule); ok { @@ -1208,12 +1144,14 @@ func (class apexFileClass) NameInMake() string { // apexFile represents a file in an APEX bundle type apexFile struct { builtFile android.Path + stem string moduleName string installDir string class apexFileClass module android.Module // list of symlinks that will be created in installDir that point to this apexFile symlinks []string + dataPaths android.Paths transitiveDep bool moduleDir string @@ -1249,16 +1187,27 @@ func (af *apexFile) Ok() bool { return af.builtFile != nil && af.builtFile.String() != "" } +func (af *apexFile) apexRelativePath(path string) string { + return filepath.Join(af.installDir, path) +} + // Path() returns path of this apex file relative to the APEX root func (af *apexFile) Path() string { - return filepath.Join(af.installDir, af.builtFile.Base()) + return af.apexRelativePath(af.Stem()) +} + +func (af *apexFile) Stem() string { + if af.stem != "" { + return af.stem + } + return af.builtFile.Base() } // SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root func (af *apexFile) SymlinkPaths() []string { var ret []string for _, symlink := range af.symlinks { - ret = append(ret, filepath.Join(af.installDir, symlink)) + ret = append(ret, af.apexRelativePath(symlink)) } return ret } @@ -1458,19 +1407,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { target, a.getImageVariation(config)) } - - if strings.HasPrefix(ctx.ModuleName(), "com.android.runtime") && target.Os.Class == android.Device { - for _, sanitizer := range ctx.Config().SanitizeDevice() { - if sanitizer == "hwaddress" { - addDependenciesForNativeModules(ctx, - ApexNativeDependencies{[]string{"libclang_rt.hwasan-aarch64-android"}, nil, nil, nil}, - target, a.getImageVariation(config)) - break - } - } - } } - } // For prebuilt_etc, use the first variant (64 on 64/32bit device, @@ -1602,6 +1539,21 @@ func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizer return android.InList(sanitizerName, globalSanitizerNames) } +func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) { + if ctx.Device() && sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") { + for _, target := range ctx.MultiTargets() { + if target.Arch.ArchType.Multilib == "lib64" { + ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ + {Mutator: "image", Variation: a.getImageVariation(ctx.DeviceConfig())}, + {Mutator: "link", Variation: "shared"}, + {Mutator: "version", Variation: ""}, // "" is the non-stub variant + }...), sharedLibTag, "libclang_rt.hwasan-aarch64-android") + break + } + } + } +} + var _ cc.Coverage = (*apexBundle)(nil) func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { @@ -1664,6 +1616,7 @@ func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFil fileToCopy := cc.OutputFile().Path() af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc) af.symlinks = cc.Symlinks() + af.dataPaths = cc.DataPaths() return af } @@ -1694,17 +1647,17 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) ap return af } -// TODO(b/146586360): replace javaLibrary(in apex/apex.go) with java.Dependency -type javaLibrary interface { - android.Module +type javaDependency interface { java.Dependency + Stem() string } -func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaLibrary) apexFile { +func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile { dirInApex := "javalib" fileToCopy := lib.DexJar() - af := newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib) + af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = lib.JacocoReportClassesFile() + af.stem = lib.Stem() + ".jar" return af } @@ -1810,6 +1763,12 @@ func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int { return intVer } +func (a *apexBundle) Updatable() bool { + return proptools.Bool(a.properties.Updatable) +} + +var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil) + // Ensures that the dependencies are marked as available for this APEX func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { // Let's be practical. Availability for test, host, and the VNDK apex isn't important @@ -1851,7 +1810,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { } func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { - if proptools.Bool(a.properties.Updatable) { + if a.Updatable() { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } @@ -1860,6 +1819,51 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { } } +// Ensures that a lib providing stub isn't statically linked +func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) { + // Practically, we only care about regular APEXes on the device. + if ctx.Host() || a.testApex || a.vndkApex { + return + } + + a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { + if ccm, ok := to.(*cc.Module); ok { + apexName := ctx.ModuleName() + fromName := ctx.OtherModuleName(from) + toName := ctx.OtherModuleName(to) + + // If `to` is not actually in the same APEX as `from` then it does not need apex_available and neither + // do any of its dependencies. + if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return false + } + + // TODO(jiyong) remove this check when R is published to AOSP. Currently, libstatssocket + // is capable of providing a stub variant, but is being statically linked from the bluetooth + // APEX. + if toName == "libstatssocket" { + return false + } + + // The dynamic linker and crash_dump tool in the runtime APEX is the only exception to this rule. + // It can't make the static dependencies dynamic because it can't + // do the dynamic linking for itself. + if apexName == "com.android.runtime" && (fromName == "linker" || fromName == "crash_dump") { + return false + } + + isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !android.DirectlyInApex(apexName, toName) + if isStubLibraryFromOtherApex && !externalDep { + ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+ + "It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false)) + } + + } + return true + }) +} + func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() switch a.properties.ApexType { @@ -1897,6 +1901,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkApexAvailability(ctx) a.checkUpdatable(ctx) + a.checkStaticLinkingToStubLibraries(ctx) handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) @@ -1941,13 +1946,13 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { case sharedLibTag, jniLibTag: isJniLib := depTag == jniLibTag if c, ok := child.(*cc.Module); ok { - // bootstrap bionic libs are treated as provided by system - if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) { - provideNativeLibs = append(provideNativeLibs, c.OutputFile().Path().Base()) - } fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs) fi.isJniLib = isJniLib filesInfo = append(filesInfo, fi) + // bootstrap bionic libs are treated as provided by system + if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) { + provideNativeLibs = append(provideNativeLibs, fi.Stem()) + } return true // track transitive dependencies } else { propertyName := "native_shared_libs" @@ -1971,7 +1976,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } case javaLibTag: if javaLib, ok := child.(*java.Library); ok { - af := apexFileForJavaLibrary(ctx, javaLib) + af := apexFileForJavaLibrary(ctx, javaLib, javaLib) if !af.Ok() { ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) } else { @@ -1979,7 +1984,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { return true // track transitive dependencies } } else if sdkLib, ok := child.(*java.SdkLibrary); ok { - af := apexFileForJavaLibrary(ctx, sdkLib) + af := apexFileForJavaLibrary(ctx, sdkLib, sdkLib) if !af.Ok() { ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) return false @@ -2067,6 +2072,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // don't include it in this APEX return false } + af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs) + af.transitiveDep = true if !a.Host() && !android.DirectlyInApex(ctx.ModuleName(), ctx.OtherModuleName(cc)) && (cc.IsStubs() || cc.HasStubsVariants()) { // If the dependency is a stubs lib, don't include it in this APEX, // but make sure that the lib is installed on the device. @@ -2078,12 +2085,10 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.BaseModuleName(), a.requiredDeps) { a.requiredDeps = append(a.requiredDeps, cc.BaseModuleName()) } - requireNativeLibs = append(requireNativeLibs, cc.OutputFile().Path().Base()) + requireNativeLibs = append(requireNativeLibs, af.Stem()) // Don't track further return false } - af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs) - af.transitiveDep = true filesInfo = append(filesInfo, af) return true // track transitive dependencies } @@ -2191,7 +2196,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // We don't need the optimization for updatable APEXes, as it might give false signal // to the system health when the APEXes are still bundled (b/149805758) - if proptools.Bool(a.properties.Updatable) && a.properties.ApexType == imageApex { + if a.Updatable() && a.properties.ApexType == imageApex { a.linkToSystemLib = false } @@ -2257,6 +2262,10 @@ func normalizeModuleName(moduleName string) string { // We don't want to list them all moduleName = "libclang_rt" } + if strings.HasPrefix(moduleName, "androidx.") { + // TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries + moduleName = "androidx" + } return moduleName } diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go new file mode 100644 index 000000000..83a56a2b5 --- /dev/null +++ b/apex/apex_singleton.go @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package apex + +import ( + "github.com/google/blueprint" + + "android/soong/android" +) + +func init() { + android.RegisterSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory) +} + +type apexDepsInfoSingleton struct { + // Output file with all flatlists from updatable modules' deps-info combined + updatableFlatListsPath android.OutputPath +} + +func apexDepsInfoSingletonFactory() android.Singleton { + return &apexDepsInfoSingleton{} +} + +var combineFilesRule = pctx.AndroidStaticRule("combineFilesRule", + blueprint.RuleParams{ + Command: "cat $out.rsp | xargs cat > $out", + Rspfile: "$out.rsp", + RspfileContent: "$in", + }, +) + +func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) { + updatableFlatLists := android.Paths{} + ctx.VisitAllModules(func(module android.Module) { + if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok { + if path := binaryInfo.FlatListPath(); path != nil { + if binaryInfo.Updatable() { + updatableFlatLists = append(updatableFlatLists, path) + } + } + } + }) + + s.updatableFlatListsPath = android.PathForOutput(ctx, "apex", "depsinfo", "updatable-flatlists.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: combineFilesRule, + Description: "Generate " + s.updatableFlatListsPath.String(), + Inputs: updatableFlatLists, + Output: s.updatableFlatListsPath, + }) +} diff --git a/apex/apex_test.go b/apex/apex_test.go index dc6986244..29bd087c6 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -19,6 +19,7 @@ import ( "os" "path" "reflect" + "regexp" "sort" "strings" "testing" @@ -175,11 +176,15 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr "testkey2.pem": nil, "myapex-arm64.apex": nil, "myapex-arm.apex": nil, + "myapex.apks": nil, "frameworks/base/api/current.txt": nil, "framework/aidl/a.aidl": nil, "build/make/core/proguard.flags": nil, "build/make/core/proguard_basic_keeps.flags": nil, "dummy.txt": nil, + "baz": nil, + "bar/baz": nil, + "testdata/baz": nil, } cc.GatherRequiredFilesForTest(fs) @@ -216,6 +221,7 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr ctx.RegisterModuleType("apex_defaults", defaultsFactory) ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory) ctx.RegisterModuleType("override_apex", overrideApexFactory) + ctx.RegisterModuleType("apex_set", apexSetFactory) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) @@ -269,6 +275,15 @@ func ensureContains(t *testing.T, result string, expected string) { } } +// ensure that 'result' contains 'expected' exactly one time +func ensureContainsOnce(t *testing.T, result string, expected string) { + t.Helper() + count := strings.Count(result, expected) + if count != 1 { + t.Errorf("%q is found %d times (expected 1 time) in %q", expected, count, result) + } +} + // ensures that 'result' does not contain 'notExpected' func ensureNotContains(t *testing.T, result string, notExpected string) { t.Helper() @@ -409,6 +424,7 @@ func TestBasicApex(t *testing.T) { java_library { name: "myjar", srcs: ["foo/bar/MyClass.java"], + stem: "myjar_stem", sdk_version: "none", system_modules: "none", static_libs: ["myotherjar"], @@ -463,7 +479,7 @@ func TestBasicApex(t *testing.T) { // Ensure that both direct and indirect deps are copied into apex ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") - ensureContains(t, copyCmds, "image.apex/javalib/myjar.jar") + ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar") // .. but not for java libs ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar") ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar") @@ -905,6 +921,130 @@ func TestApexWithRuntimeLibsDependency(t *testing.T) { } +func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) { + ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) { + bp := ` + apex { + name: "com.android.runtime", + key: "com.android.runtime.key", + native_shared_libs: ["libc"], + } + + apex_key { + name: "com.android.runtime.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libc", + no_libcrt: true, + nocrt: true, + stl: "none", + system_shared_libs: [], + stubs: { versions: ["1"] }, + apex_available: ["com.android.runtime"], + + sanitize: { + hwaddress: true, + } + } + + cc_prebuilt_library_shared { + name: "libclang_rt.hwasan-aarch64-android", + no_libcrt: true, + nocrt: true, + stl: "none", + system_shared_libs: [], + srcs: [""], + stubs: { versions: ["1"] }, + + sanitize: { + never: true, + }, + } + ` + // override bp to use hard-coded names: com.android.runtime and libc + fs["Android.bp"] = []byte(bp) + fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil + }) + + ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{ + "lib64/bionic/libc.so", + "lib64/bionic/libclang_rt.hwasan-aarch64-android.so", + }) + + hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared") + + installed := hwasan.Description("install libclang_rt.hwasan") + ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so") + + symlink := hwasan.Description("install symlink libclang_rt.hwasan") + ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so") + ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so") +} + +func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) { + ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) { + bp := ` + apex { + name: "com.android.runtime", + key: "com.android.runtime.key", + native_shared_libs: ["libc"], + } + + apex_key { + name: "com.android.runtime.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libc", + no_libcrt: true, + nocrt: true, + stl: "none", + system_shared_libs: [], + stubs: { versions: ["1"] }, + apex_available: ["com.android.runtime"], + } + + cc_prebuilt_library_shared { + name: "libclang_rt.hwasan-aarch64-android", + no_libcrt: true, + nocrt: true, + stl: "none", + system_shared_libs: [], + srcs: [""], + stubs: { versions: ["1"] }, + + sanitize: { + never: true, + }, + } + ` + // override bp to use hard-coded names: com.android.runtime and libc + fs["Android.bp"] = []byte(bp) + fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil + + config.TestProductVariables.SanitizeDevice = []string{"hwaddress"} + }) + + ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{ + "lib64/bionic/libc.so", + "lib64/bionic/libclang_rt.hwasan-aarch64-android.so", + }) + + hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared") + + installed := hwasan.Description("install libclang_rt.hwasan") + ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so") + + symlink := hwasan.Description("install symlink libclang_rt.hwasan") + ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so") + ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so") +} + func TestApexDependsOnLLNDKTransitively(t *testing.T) { testcases := []struct { name string @@ -3267,6 +3407,14 @@ func TestApexWithTests(t *testing.T) { private_key: "testkey.pem", } + filegroup { + name: "fg", + srcs: [ + "baz", + "bar/baz" + ], + } + cc_test { name: "mytest", gtest: false, @@ -3276,6 +3424,7 @@ func TestApexWithTests(t *testing.T) { system_shared_libs: [], static_executable: true, stl: "none", + data: [":fg"], } cc_library { @@ -3285,6 +3434,13 @@ func TestApexWithTests(t *testing.T) { stl: "none", } + filegroup { + name: "fg2", + srcs: [ + "testdata/baz" + ], + } + cc_test { name: "mytests", gtest: false, @@ -3298,6 +3454,10 @@ func TestApexWithTests(t *testing.T) { system_shared_libs: [], static_executable: true, stl: "none", + data: [ + ":fg", + ":fg2", + ], } `) @@ -3308,15 +3468,19 @@ func TestApexWithTests(t *testing.T) { ensureContains(t, copyCmds, "image.apex/bin/test/mytest") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") + //Ensure that test data are copied into apex. + ensureContains(t, copyCmds, "image.apex/bin/test/baz") + ensureContains(t, copyCmds, "image.apex/bin/test/bar/baz") + // Ensure that test deps built with `test_per_src` are copied into apex. ensureContains(t, copyCmds, "image.apex/bin/test/mytest1") ensureContains(t, copyCmds, "image.apex/bin/test/mytest2") ensureContains(t, copyCmds, "image.apex/bin/test/mytest3") // Ensure the module is correctly translated. - apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) - data := android.AndroidMkDataForTest(t, config, "", apexBundle) - name := apexBundle.BaseModuleName() + bundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, config, "", bundle) + name := bundle.BaseModuleName() prefix := "TARGET_" var builder strings.Builder data.Custom(&builder, name, prefix, "", data) @@ -3328,6 +3492,13 @@ func TestApexWithTests(t *testing.T) { ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex\n") ensureContains(t, androidMk, "LOCAL_MODULE := apex_pubkey.myapex\n") ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n") + + flatBundle := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle) + data = android.AndroidMkDataForTest(t, config, "", flatBundle) + data.Custom(&builder, name, prefix, "", data) + flatAndroidMk := builder.String() + ensureContainsOnce(t, flatAndroidMk, "LOCAL_TEST_DATA := :baz :bar/baz\n") + ensureContainsOnce(t, flatAndroidMk, "LOCAL_TEST_DATA := :testdata/baz\n") } func TestInstallExtraFlattenedApexes(t *testing.T) { @@ -4115,6 +4286,15 @@ func TestLegacyAndroid10Support(t *testing.T) { } } +var filesForSdkLibrary = map[string][]byte{ + "api/current.txt": nil, + "api/removed.txt": nil, + "api/system-current.txt": nil, + "api/system-removed.txt": nil, + "api/test-current.txt": nil, + "api/test-removed.txt": nil, +} + func TestJavaSDKLibrary(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -4135,14 +4315,7 @@ func TestJavaSDKLibrary(t *testing.T) { api_packages: ["foo"], apex_available: [ "myapex" ], } - `, withFiles(map[string][]byte{ - "api/current.txt": nil, - "api/removed.txt": nil, - "api/system-current.txt": nil, - "api/system-removed.txt": nil, - "api/test-current.txt": nil, - "api/test-removed.txt": nil, - })) + `, withFiles(filesForSdkLibrary)) // java_sdk_library installs both impl jar and permission XML ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ @@ -4154,6 +4327,98 @@ func TestJavaSDKLibrary(t *testing.T) { ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`) } +func TestJavaSDKLibrary_WithinApex(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["foo", "bar"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "bar", + srcs: ["a.java"], + libs: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + `, withFiles(filesForSdkLibrary)) + + // java_sdk_library installs both impl jar and permission XML + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "javalib/bar.jar", + "javalib/foo.jar", + "etc/permissions/foo.xml", + }) + + // The bar library should depend on the implementation jar. + barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac") + if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + +func TestJavaSDKLibrary_CrossBoundary(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["foo"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "bar", + srcs: ["a.java"], + libs: ["foo"], + sdk_version: "none", + system_modules: "none", + } + `, withFiles(filesForSdkLibrary)) + + // java_sdk_library installs both impl jar and permission XML + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "javalib/foo.jar", + "etc/permissions/foo.xml", + }) + + // The bar library should depend on the stubs jar. + barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac") + if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + func TestCompatConfig(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -4491,10 +4756,78 @@ func TestAppBundle(t *testing.T) { ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`) } -func testNoUpdatableJarsInBootImage(t *testing.T, errmsg, bp string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) { +func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) { t.Helper() - bp = bp + ` + bp := ` + java_library { + name: "some-updatable-apex-lib", + srcs: ["a.java"], + sdk_version: "current", + apex_available: [ + "some-updatable-apex", + ], + } + + java_library { + name: "some-non-updatable-apex-lib", + srcs: ["a.java"], + apex_available: [ + "some-non-updatable-apex", + ], + } + + java_library { + name: "some-platform-lib", + srcs: ["a.java"], + sdk_version: "current", + installable: true, + } + + java_library { + name: "some-art-lib", + srcs: ["a.java"], + sdk_version: "current", + apex_available: [ + "com.android.art.something", + ], + hostdex: true, + } + + apex { + name: "some-updatable-apex", + key: "some-updatable-apex.key", + java_libs: ["some-updatable-apex-lib"], + updatable: true, + min_sdk_version: "current", + } + + apex { + name: "some-non-updatable-apex", + key: "some-non-updatable-apex.key", + java_libs: ["some-non-updatable-apex-lib"], + } + + apex_key { + name: "some-updatable-apex.key", + } + + apex_key { + name: "some-non-updatable-apex.key", + } + + apex { + name: "com.android.art.something", + key: "com.android.art.something.key", + java_libs: ["some-art-lib"], + updatable: true, + min_sdk_version: "current", + } + + apex_key { + name: "com.android.art.something.key", + } + filegroup { name: "some-updatable-apex-file_contexts", srcs: [ @@ -4581,145 +4914,86 @@ func TestUpdatable_should_set_min_sdk_version(t *testing.T) { } func TestNoUpdatableJarsInBootImage(t *testing.T) { - bp := ` - java_library { - name: "some-updatable-apex-lib", - srcs: ["a.java"], - sdk_version: "current", - apex_available: [ - "some-updatable-apex", - ], - } - java_library { - name: "some-non-updatable-apex-lib", - srcs: ["a.java"], - apex_available: [ - "some-non-updatable-apex", - ], - } + var error string + var transform func(*dexpreopt.GlobalConfig) - java_library { - name: "some-platform-lib", - srcs: ["a.java"], - sdk_version: "current", - installable: true, + 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"} } + testNoUpdatableJarsInBootImage(t, "", transform) + }) - java_library { - name: "some-art-lib", - srcs: ["a.java"], - sdk_version: "current", - apex_available: [ - "com.android.art.something", - ], - hostdex: true, + t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) { + error = "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"} } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - apex { - name: "some-updatable-apex", - key: "some-updatable-apex.key", - java_libs: ["some-updatable-apex-lib"], - updatable: true, - min_sdk_version: "current", + t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { + error = "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"} } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - apex { - name: "some-non-updatable-apex", - key: "some-non-updatable-apex.key", - java_libs: ["some-non-updatable-apex-lib"], + t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { + error = "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"} } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - apex_key { - name: "some-updatable-apex.key", + t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) { + error = "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"} } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - apex_key { - name: "some-non-updatable-apex.key", + 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"} } + testNoUpdatableJarsInBootImage(t, "", transform) + }) - apex { - name: "com.android.art.something", - key: "com.android.art.something.key", - java_libs: ["some-art-lib"], - updatable: true, - min_sdk_version: "current", + t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) { + error = "failed to find a dex jar path for module 'nonexistent'" + transform = func(config *dexpreopt.GlobalConfig) { + config.ArtApexJars = []string{"platform:nonexistent"} } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - apex_key { - name: "com.android.art.something.key", + t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) { + error = "failed to find a dex jar path for module 'nonexistent'" + transform = func(config *dexpreopt.GlobalConfig) { + config.BootJars = []string{"platform:nonexistent"} } - ` - - var error string - var transform func(*dexpreopt.GlobalConfig) - - // updatable jar from ART apex in the ART boot image => ok - transform = func(config *dexpreopt.GlobalConfig) { - config.ArtApexJars = []string{"com.android.art.something:some-art-lib"} - } - testNoUpdatableJarsInBootImage(t, "", bp, transform) - - // updatable jar from ART apex in the framework boot image => error - error = "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"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) - - // updatable jar from some other apex in the ART boot image => error - error = "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"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) - - // non-updatable jar from some other apex in the ART boot image => error - error = "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"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) - - // updatable jar from some other apex in the framework boot image => error - error = "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"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) - - // non-updatable jar from some other apex in the framework boot image => ok - transform = func(config *dexpreopt.GlobalConfig) { - config.BootJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"} - } - testNoUpdatableJarsInBootImage(t, "", bp, transform) - - // nonexistent jar in the ART boot image => error - error = "failed to find a dex jar path for module 'nonexistent'" - transform = func(config *dexpreopt.GlobalConfig) { - config.ArtApexJars = []string{"platform:nonexistent"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) - - // nonexistent jar in the framework boot image => error - error = "failed to find a dex jar path for module 'nonexistent'" - transform = func(config *dexpreopt.GlobalConfig) { - config.BootJars = []string{"platform:nonexistent"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) + testNoUpdatableJarsInBootImage(t, error, transform) + }) - // platform jar in the ART boot image => error - error = "module 'some-platform-lib' is not allowed in the ART boot image" - transform = func(config *dexpreopt.GlobalConfig) { - config.ArtApexJars = []string{"platform:some-platform-lib"} - } - testNoUpdatableJarsInBootImage(t, error, bp, transform) + t.Run("platform jar in the ART boot image => error", func(t *testing.T) { + error = "module 'some-platform-lib' is not allowed in the ART boot image" + transform = func(config *dexpreopt.GlobalConfig) { + config.ArtApexJars = []string{"platform:some-platform-lib"} + } + testNoUpdatableJarsInBootImage(t, error, transform) + }) - // platform jar in the framework boot image => ok - transform = func(config *dexpreopt.GlobalConfig) { - config.BootJars = []string{"platform:some-platform-lib"} - } - testNoUpdatableJarsInBootImage(t, "", bp, 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"} + } + testNoUpdatableJarsInBootImage(t, "", transform) + }) } func TestTestFor(t *testing.T) { @@ -4774,6 +5048,84 @@ func TestTestFor(t *testing.T) { ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so") } +// TODO(jungjw): Move this to proptools +func intPtr(i int) *int { + return &i +} + +func TestApexSet(t *testing.T) { + ctx, config := testApex(t, ` + apex_set { + name: "myapex", + set: "myapex.apks", + filename: "foo_v2.apex", + overrides: ["foo"], + } + `, func(fs map[string][]byte, config android.Config) { + config.TestProductVariables.Platform_sdk_version = intPtr(30) + config.TestProductVariables.DeviceArch = proptools.StringPtr("arm") + config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm64") + }) + + m := ctx.ModuleForTests("myapex", "android_common") + + // Check extract_apks tool parameters. + extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex") + actual := extractedApex.Args["abis"] + expected := "ARMEABI_V7A,ARM64_V8A" + if actual != expected { + t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual) + } + actual = extractedApex.Args["sdk-version"] + expected = "30" + if actual != expected { + t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual) + } + + a := m.Module().(*ApexSet) + expectedOverrides := []string{"foo"} + actualOverrides := android.AndroidMkEntriesForTest(t, config, "", a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"] + if !reflect.DeepEqual(actualOverrides, expectedOverrides) { + t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES - expected %q vs actual %q", expectedOverrides, actualOverrides) + } +} + +func TestNoStaticLinkingToStubsLib(t *testing.T) { + testApexError(t, `.*required by "mylib" is a native library providing stub.*`, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + static_libs: ["otherlib"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + } + + cc_library { + name: "otherlib", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["1", "2", "3"], + }, + apex_available: [ "myapex" ], + } + `) +} + func TestMain(m *testing.M) { run := func() int { setUp() diff --git a/apex/builder.go b/apex/builder.go index ca24f2cff..0108d068a 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -61,6 +61,7 @@ func init() { pctx.HostBinToolVariable("zipalign", "zipalign") pctx.HostBinToolVariable("jsonmodify", "jsonmodify") pctx.HostBinToolVariable("conv_apex_manifest", "conv_apex_manifest") + pctx.HostBinToolVariable("extract_apks", "extract_apks") } var ( @@ -189,7 +190,7 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, var jniLibs []string for _, fi := range a.filesInfo { if fi.isJniLib { - jniLibs = append(jniLibs, fi.builtFile.Base()) + jniLibs = append(jniLibs, fi.Stem()) } } if len(jniLibs) > 0 { @@ -246,7 +247,7 @@ func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName st return android.NoticeOutputs{} } - return android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)) + return android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.SortedUniquePaths(noticeFiles)) } func (a *apexBundle) buildInstalledFilesFile(ctx android.ModuleContext, builtApex android.Path, imageDir android.Path) android.OutputPath { @@ -350,6 +351,19 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { symlinkDest := android.PathForModuleOut(ctx, "image"+suffix, symlinkPath).String() copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest) } + for _, d := range fi.dataPaths { + // TODO(eakammer): This is now the third repetition of ~this logic for test paths, refactoring should be possible + relPath := d.Rel() + dataPath := d.String() + if !strings.HasSuffix(dataPath, relPath) { + panic(fmt.Errorf("path %q does not end with %q", dataPath, relPath)) + } + + dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath)).String() + + copyCommands = append(copyCommands, "cp -f "+d.String()+" "+dataDest) + implicitInputs = append(implicitInputs, d) + } } // TODO(jiyong): use RuleBuilder @@ -403,9 +417,12 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"} var executablePaths []string // this also includes dirs for _, f := range a.filesInfo { - pathInApex := filepath.Join(f.installDir, f.builtFile.Base()) + pathInApex := f.Path() if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") { executablePaths = append(executablePaths, pathInApex) + for _, d := range f.dataPaths { + readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.Rel())) + } for _, s := range f.symlinks { executablePaths = append(executablePaths, filepath.Join(f.installDir, s)) } @@ -453,11 +470,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { } targetSdkVersion := ctx.Config().DefaultAppTargetSdk() + // TODO(b/157078772): propagate min_sdk_version to apexer. minSdkVersion := ctx.Config().DefaultAppTargetSdk() if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) - targetSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) } if java.UseApiFingerprint(ctx) { @@ -565,19 +582,27 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { } a.outputFile = android.PathForModuleOut(ctx, a.Name()+suffix) + rule := java.Signapk + args := map[string]string{ + "certificates": a.container_certificate_file.String() + " " + a.container_private_key_file.String(), + "flags": "-a 4096", //alignment + } + implicits := android.Paths{ + a.container_certificate_file, + a.container_private_key_file, + } + if ctx.Config().IsEnvTrue("RBE_SIGNAPK") { + rule = java.SignapkRE + args["implicits"] = strings.Join(implicits.Strings(), ",") + args["outCommaList"] = a.outputFile.String() + } ctx.Build(pctx, android.BuildParams{ - Rule: java.Signapk, + Rule: rule, Description: "signapk", Output: a.outputFile, Input: unsignedOutputFile, - Implicits: []android.Path{ - a.container_certificate_file, - a.container_private_key_file, - }, - Args: map[string]string{ - "certificates": a.container_certificate_file.String() + " " + a.container_private_key_file.String(), - "flags": "-a 4096", //alignment - }, + Implicits: implicits, + Args: args, }) // Install to $OUT/soong/{target,host}/.../apex @@ -642,7 +667,7 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) { apexBundleName := a.Name() for _, fi := range a.filesInfo { dir := filepath.Join("apex", apexBundleName, fi.installDir) - target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile) + target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.Stem(), fi.builtFile) for _, sym := range fi.symlinks { ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target) } diff --git a/apex/prebuilt.go b/apex/prebuilt.go index d089c285d..03266c55e 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -16,13 +16,29 @@ package apex import ( "fmt" + "strconv" "strings" "android/soong/android" + "android/soong/java" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) +var ( + extractMatchingApex = pctx.StaticRule( + "extractMatchingApex", + blueprint.RuleParams{ + Command: `rm -rf "$out" && ` + + `${extract_apks} -o "${out}" -allow-prereleased=${allow-prereleased} ` + + `-sdk-version=${sdk-version} -abis=${abis} -screen-densities=all -extract-single ` + + `${in}`, + CommandDeps: []string{"${extract_apks}"}, + }, + "abis", "allow-prereleased", "sdk-version") +) + type Prebuilt struct { android.ModuleBase prebuilt android.Prebuilt @@ -208,3 +224,117 @@ func (p *Prebuilt) AndroidMkEntries() []android.AndroidMkEntries { }, }} } + +type ApexSet struct { + android.ModuleBase + prebuilt android.Prebuilt + + properties ApexSetProperties + + installDir android.InstallPath + installFilename string + outputApex android.WritablePath + + // list of commands to create symlinks for backward compatibility. + // these commands will be attached as LOCAL_POST_INSTALL_CMD + compatSymlinks []string +} + +type ApexSetProperties struct { + // the .apks file path that contains prebuilt apex files to be extracted. + Set *string + + // whether the extracted apex file installable. + Installable *bool + + // optional name for the installed apex. If unspecified, name of the + // module is used as the file name + Filename *string + + // names of modules to be overridden. Listed modules can only be other binaries + // (in Make or Soong). + // This does not completely prevent installation of the overridden binaries, but if both + // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed + // from PRODUCT_PACKAGES. + Overrides []string + + // apexes in this set use prerelease SDK version + Prerelease *bool +} + +func (a *ApexSet) installable() bool { + return a.properties.Installable == nil || proptools.Bool(a.properties.Installable) +} + +func (a *ApexSet) InstallFilename() string { + return proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+imageApexSuffix) +} + +func (a *ApexSet) Prebuilt() *android.Prebuilt { + return &a.prebuilt +} + +func (a *ApexSet) Name() string { + return a.prebuilt.Name(a.ModuleBase.Name()) +} + +// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. +func apexSetFactory() android.Module { + module := &ApexSet{} + module.AddProperties(&module.properties) + android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set") + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) + return module +} + +func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { + a.installFilename = a.InstallFilename() + if !strings.HasSuffix(a.installFilename, imageApexSuffix) { + ctx.ModuleErrorf("filename should end in %s for apex_set", imageApexSuffix) + } + + apexSet := a.prebuilt.SingleSourcePath(ctx) + a.outputApex = android.PathForModuleOut(ctx, a.installFilename) + ctx.Build(pctx, + android.BuildParams{ + Rule: extractMatchingApex, + Description: "Extract an apex from an apex set", + Inputs: android.Paths{apexSet}, + Output: a.outputApex, + Args: map[string]string{ + "abis": strings.Join(java.SupportedAbis(ctx), ","), + "allow-prereleased": strconv.FormatBool(proptools.Bool(a.properties.Prerelease)), + "sdk-version": ctx.Config().PlatformSdkVersion(), + }, + }) + a.installDir = android.PathForModuleInstall(ctx, "apex") + if a.installable() { + ctx.InstallFile(a.installDir, a.installFilename, a.outputApex) + } + + // in case that apex_set replaces source apex (using prefer: prop) + a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) + // or that apex_set overrides other apexes (using overrides: prop) + for _, overridden := range a.properties.Overrides { + a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) + } +} + +func (a *ApexSet) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{android.AndroidMkEntries{ + Class: "ETC", + OutputFile: android.OptionalPathForPath(a.outputApex), + Include: "$(BUILD_PREBUILT)", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.SetString("LOCAL_MODULE_PATH", a.installDir.ToMakePath().String()) + entries.SetString("LOCAL_MODULE_STEM", a.installFilename) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !a.installable()) + entries.AddStrings("LOCAL_OVERRIDES_MODULES", a.properties.Overrides...) + if len(a.compatSymlinks) > 0 { + entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(a.compatSymlinks, " && ")) + } + }, + }, + }} +} diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go index a1c5de122..e731750fb 100644 --- a/bpfix/bpfix/bpfix.go +++ b/bpfix/bpfix/bpfix.go @@ -408,6 +408,8 @@ func rewriteTestModuleTypes(f *Fixer) error { switch mod.Type { case "android_app": mod.Type = "android_test" + case "android_app_import": + mod.Type = "android_test_import" case "java_library", "java_library_installable": mod.Type = "java_test" case "java_library_host": @@ -951,7 +953,8 @@ func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) err case strings.Contains(mod.Type, "cc_test"), strings.Contains(mod.Type, "cc_library_static"), strings.Contains(mod.Type, "java_test"), - mod.Type == "android_test": + mod.Type == "android_test", + mod.Type == "android_test_import": continue case strings.Contains(mod.Type, "cc_lib"): replaceStr += `// WARNING: Module tags are not supported in Soong. diff --git a/cc/androidmk.go b/cc/androidmk.go index 671adb55f..3ce1a8955 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -149,7 +149,7 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{entries} } -func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) { +func AndroidMkDataPaths(data android.Paths) []string { var testFiles []string for _, d := range data { rel := d.Rel() @@ -160,6 +160,11 @@ func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *a path = strings.TrimSuffix(path, rel) testFiles = append(testFiles, path+":"+rel) } + return testFiles +} + +func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) { + testFiles := AndroidMkDataPaths(data) if len(testFiles) > 0 { entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { entries.AddStrings("LOCAL_TEST_DATA", testFiles...) diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go index 88ac51349..372a72e2c 100644 --- a/cc/binary_sdk_member.go +++ b/cc/binary_sdk_member.go @@ -20,6 +20,7 @@ import ( "android/soong/android" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) func init() { @@ -65,7 +66,15 @@ func (mt *binarySdkMemberType) IsInstance(module android.Module) bool { } func (mt *binarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { - return ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary") + pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary") + + ccModule := member.Variants()[0].(*Module) + + if stl := ccModule.stl.Properties.Stl; stl != nil { + pbm.AddProperty("stl", proptools.String(stl)) + } + + return pbm } func (mt *binarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { @@ -105,6 +114,10 @@ type nativeBinaryInfoProperties struct { // // This field is exported as its contents may not be arch specific. SystemSharedLibs []string + + // Arch specific flags. + StaticExecutable bool + Nocrt bool } func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { @@ -113,6 +126,10 @@ func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberCo p.archType = ccModule.Target().Arch.ArchType.String() p.outputFile = getRequiredMemberOutputFile(ctx, ccModule) + binaryLinker := ccModule.linker.(*binaryDecorator) + p.StaticExecutable = binaryLinker.static() + p.Nocrt = Bool(binaryLinker.baseLinker.Properties.Nocrt) + if ccModule.linker != nil { specifiedDeps := specifiedDeps{} specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps) @@ -143,4 +160,11 @@ func (p *nativeBinaryInfoProperties) AddToPropertySet(ctx android.SdkMemberConte if p.SystemSharedLibs != nil { propertySet.AddPropertyWithTag("system_shared_libs", p.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false)) } + + if p.StaticExecutable { + propertySet.AddProperty("static_executable", p.StaticExecutable) + } + if p.Nocrt { + propertySet.AddProperty("nocrt", p.Nocrt) + } } diff --git a/cc/builder.go b/cc/builder.go index 4e8f1fa59..e571e5a0c 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -99,6 +99,15 @@ var ( }, "arCmd", "arFlags") + arWithLibs = pctx.AndroidStaticRule("arWithLibs", + blueprint.RuleParams{ + Command: "rm -f ${out} && $arCmd $arObjFlags $out @${out}.rsp && $arCmd $arLibFlags $out $arLibs", + CommandDeps: []string{"$arCmd"}, + Rspfile: "${out}.rsp", + RspfileContent: "${arObjs}", + }, + "arCmd", "arObjFlags", "arObjs", "arLibFlags", "arLibs") + darwinStrip = pctx.AndroidStaticRule("darwinStrip", blueprint.RuleParams{ Command: "${config.MacStripPath} -u -r -o $out $in", @@ -207,15 +216,23 @@ var ( }, []string{"cFlags", "exportDirs"}, nil) _ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker") + _ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64") - sAbiLink = pctx.AndroidStaticRule("sAbiLink", + sAbiLink, sAbiLinkRE = remoteexec.StaticRules(pctx, "sAbiLink", blueprint.RuleParams{ - Command: "$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ", + Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ", CommandDeps: []string{"$sAbiLinker"}, Rspfile: "${out}.rsp", RspfileContent: "${in}", - }, - "symbolFilter", "arch", "exportedHeaderFlags") + }, &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "abi-linker"}, + ExecStrategy: "${config.REAbiLinkerExecStrategy}", + Inputs: []string{"$sAbiLinkerLibs", "${out}.rsp", "$implicits"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out"}, + ToolchainInputs: []string{"$sAbiLinker"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXPool}"}, + }, []string{"symbolFilter", "arch", "exportedHeaderFlags"}, []string{"implicits"}) _ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff") @@ -601,26 +618,45 @@ func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles and } // Generate a rule for compiling multiple .o files to a static library (.a) -func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, +func TransformObjToStaticLib(ctx android.ModuleContext, + objFiles android.Paths, wholeStaticLibs android.Paths, flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) { arCmd := "${config.ClangBin}/llvm-ar" - arFlags := "crsPD" + arFlags := "" if !ctx.Darwin() { arFlags += " -format=gnu" } - ctx.Build(pctx, android.BuildParams{ - Rule: ar, - Description: "static link " + outputFile.Base(), - Output: outputFile, - Inputs: objFiles, - Implicits: deps, - Args: map[string]string{ - "arFlags": arFlags, - "arCmd": arCmd, - }, - }) + if len(wholeStaticLibs) == 0 { + ctx.Build(pctx, android.BuildParams{ + Rule: ar, + Description: "static link " + outputFile.Base(), + Output: outputFile, + Inputs: objFiles, + Implicits: deps, + Args: map[string]string{ + "arFlags": "crsPD" + arFlags, + "arCmd": arCmd, + }, + }) + + } else { + ctx.Build(pctx, android.BuildParams{ + Rule: arWithLibs, + Description: "static link " + outputFile.Base(), + Output: outputFile, + Inputs: append(objFiles, wholeStaticLibs...), + Implicits: deps, + Args: map[string]string{ + "arCmd": arCmd, + "arObjFlags": "crsPD" + arFlags, + "arObjs": strings.Join(objFiles.Strings(), " "), + "arLibFlags": "cqsL" + arFlags, + "arLibs": strings.Join(wholeStaticLibs.Strings(), " "), + }, + }) + } } // Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries, @@ -724,17 +760,30 @@ func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Path for _, tag := range excludedSymbolTags { symbolFilterStr += " --exclude-symbol-tag " + tag } + rule := sAbiLink + args := map[string]string{ + "symbolFilter": symbolFilterStr, + "arch": ctx.Arch().ArchType.Name, + "exportedHeaderFlags": exportedHeaderFlags, + } + if ctx.Config().IsEnvTrue("RBE_ABI_LINKER") { + rule = sAbiLinkRE + rbeImplicits := implicits.Strings() + for _, p := range strings.Split(exportedHeaderFlags, " ") { + if len(p) > 2 { + // Exclude the -I prefix. + rbeImplicits = append(rbeImplicits, p[2:]) + } + } + args["implicits"] = strings.Join(rbeImplicits, ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: sAbiLink, + Rule: rule, Description: "header-abi-linker " + outputFile.Base(), Output: outputFile, Inputs: sAbiDumps, Implicits: implicits, - Args: map[string]string{ - "symbolFilter": symbolFilterStr, - "arch": ctx.Arch().ArchType.Name, - "exportedHeaderFlags": exportedHeaderFlags, - }, + Args: args, }) return android.OptionalPathForPath(outputFile) } @@ -124,10 +124,16 @@ type PathDeps struct { StaticLibs, LateStaticLibs, WholeStaticLibs android.Paths // Paths to .o files - Objs Objects + Objs Objects + // Paths to .o files in dependencies that provide them. Note that these lists + // aren't complete since prebuilt modules don't provide the .o files. StaticLibObjs Objects WholeStaticLibObjs Objects + // Paths to .a files in prebuilts. Complements WholeStaticLibObjs to contain + // the libs from all whole_static_lib dependencies. + WholeStaticLibsFromPrebuilts android.Paths + // Paths to generated source files GeneratedSources android.Paths GeneratedHeaders android.Paths @@ -1068,7 +1074,7 @@ func isBionic(name string) bool { func InstallToBootstrap(name string, config android.Config) bool { if name == "libclang_rt.hwasan-aarch64-android" { - return inList("hwaddress", config.SanitizeDevice()) + return true } return isBionic(name) } @@ -1395,6 +1401,15 @@ func (c *Module) IsTestPerSrcAllTestsVariation() bool { return ok && test.isAllTestsVariation() } +func (c *Module) DataPaths() android.Paths { + if p, ok := c.installer.(interface { + dataPaths() android.Paths + }); ok { + return p.dataPaths() + } + return nil +} + func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string { // Returns the name suffix for product and vendor variants. If the VNDK version is not // "current", it will append the VNDK version to the name suffix. @@ -2473,7 +2488,11 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } ctx.AddMissingDependencies(missingDeps) } - depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) + if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok { + depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path()) + } else { + depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) + } } else { ctx.ModuleErrorf( "non-cc.Modules cannot be included as whole static libraries.", depName) @@ -2862,6 +2881,9 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return false } } + } else if ctx.OtherModuleDependencyTag(dep) == llndkImplDep { + // We don't track beyond LLNDK + return false } return true } diff --git a/cc/config/global.go b/cc/config/global.go index 4e51ae924..1dd8a2d03 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -162,7 +162,7 @@ func init() { // http://b/131390872 // Automatically initialize any uninitialized stack variables. - // Prefer zero-init if both options are set. + // Prefer zero-init if multiple options are set. if ctx.Config().IsEnvTrue("AUTO_ZERO_INITIALIZE") { flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang") } else if ctx.Config().IsEnvTrue("AUTO_PATTERN_INITIALIZE") { @@ -170,8 +170,8 @@ func init() { } else if ctx.Config().IsEnvTrue("AUTO_UNINITIALIZE") { flags = append(flags, "-ftrivial-auto-var-init=uninitialized") } else { - // Default to pattern initialization. - flags = append(flags, "-ftrivial-auto-var-init=pattern") + // Default to zero initialization. + flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang") } return strings.Join(flags, " ") @@ -261,6 +261,7 @@ func init() { pctx.VariableFunc("RECXXLinksPool", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool)) pctx.VariableFunc("RECXXLinksExecStrategy", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("REAbiDumperExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("REAbiLinkerExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) } var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS) diff --git a/cc/coverage.go b/cc/coverage.go index cc9a1adab..f885fcbc2 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -92,7 +92,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags // flags that the module may use. flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0") } else if clangCoverage { - flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-fprofile-instr-generate", "-fcoverage-mapping") + flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-fprofile-instr-generate", "-fcoverage-mapping", "-Wno-pass-failed") } } diff --git a/cc/library.go b/cc/library.go index ecea2ea54..ba8b0f40d 100644 --- a/cc/library.go +++ b/cc/library.go @@ -407,6 +407,31 @@ func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) { continue } + // libeigen wrongly exports the root directory "external/eigen". But only two + // subdirectories "Eigen" and "unsupported" contain exported header files. Even worse + // some of them have no extension. So we need special treatment for libeigen in order + // to glob correctly. + if dir == "external/eigen" { + // Only these two directories contains exported headers. + for _, subdir := range []string{"Eigen", "unsupported/Eigen"} { + glob, err := ctx.GlobWithDeps("external/eigen/"+subdir+"/**/*", nil) + if err != nil { + ctx.ModuleErrorf("glob failed: %#v", err) + return + } + for _, header := range glob { + if strings.HasSuffix(header, "/") { + continue + } + ext := filepath.Ext(header) + if ext != "" && ext != ".h" { + continue + } + ret = append(ret, android.PathForSource(ctx, header)) + } + } + continue + } exts := headerExts // Glob all files under this special directory, because of C++ headers. if strings.HasPrefix(dir, "external/libcxx/include") { @@ -874,7 +899,7 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, } } - TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles) + TransformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, objs.tidyFiles) library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName()) diff --git a/cc/sanitize.go b/cc/sanitize.go index 3412c9b21..aaaf694d9 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -989,6 +989,7 @@ type Sanitizeable interface { android.Module IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool EnableSanitizer(sanitizerName string) + AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) } // Create sanitized variants for modules that need them @@ -1075,6 +1076,7 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { c.sanitize.Properties.SanitizeDep = false } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) { // APEX modules fall here + sanitizeable.AddSanitizerDependencies(mctx, t.name()) mctx.CreateVariations(t.variationName()) } } diff --git a/cc/test.go b/cc/test.go index b1f8eec53..2439c9465 100644 --- a/cc/test.go +++ b/cc/test.go @@ -160,6 +160,10 @@ func (test *testBinary) srcs() []string { return test.baseCompiler.Properties.Srcs } +func (test *testBinary) dataPaths() android.Paths { + return test.data +} + func (test *testBinary) isAllTestsVariation() bool { stem := test.binaryDecorator.Properties.Stem return stem != nil && *stem == "" @@ -345,9 +349,7 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { } if Bool(test.Properties.Disable_framework) { var options []tradefed.Option - options = append(options, tradefed.Option{Name: "run-command", Value: "stop"}) - options = append(options, tradefed.Option{Name: "teardown-command", Value: "start"}) - configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RunCommandTargetPreparer", options}) + configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options}) } if Bool(test.testDecorator.Properties.Isolated) { configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"}) diff --git a/cc/vndk.go b/cc/vndk.go index dbe1f3b5b..e5e453305 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -309,7 +309,13 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { panic(err) } - if m.HasStubsVariants() { + if m.HasStubsVariants() && name != "libz" { + // b/155456180 libz is the ONLY exception here. We don't want to make + // libz an LLNDK library because we in general can't guarantee that + // libz will behave consistently especially about the compression. + // i.e. the compressed output might be different across releases. + // As the library is an external one, it's risky to keep the compatibility + // promise if it becomes an LLNDK. mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK") } diff --git a/cmd/extract_apks/Android.bp b/cmd/extract_apks/Android.bp new file mode 100644 index 000000000..90548cd25 --- /dev/null +++ b/cmd/extract_apks/Android.bp @@ -0,0 +1,21 @@ +blueprint_go_binary { + name: "extract_apks", + srcs: ["main.go"], + deps: [ + "android-archive-zip", + "golang-protobuf-proto", + "soong-cmd-extract_apks-proto", + ], + testSrcs: ["main_test.go"] +} + +bootstrap_go_package { + name: "soong-cmd-extract_apks-proto", + pkgPath: "android/soong/cmd/extract_apks/bundle_proto", + deps: ["golang-protobuf-proto"], + srcs: [ + "bundle_proto/commands.pb.go", + "bundle_proto/config.pb.go", + "bundle_proto/targeting.pb.go", + ], +} diff --git a/cmd/extract_apks/bundle_proto/commands.pb.go b/cmd/extract_apks/bundle_proto/commands.pb.go new file mode 100644 index 000000000..bbf3314a0 --- /dev/null +++ b/cmd/extract_apks/bundle_proto/commands.pb.go @@ -0,0 +1,1033 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: commands.proto + +package android_bundle_proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type DeliveryType int32 + +const ( + DeliveryType_UNKNOWN_DELIVERY_TYPE DeliveryType = 0 + DeliveryType_INSTALL_TIME DeliveryType = 1 + DeliveryType_ON_DEMAND DeliveryType = 2 + DeliveryType_FAST_FOLLOW DeliveryType = 3 +) + +var DeliveryType_name = map[int32]string{ + 0: "UNKNOWN_DELIVERY_TYPE", + 1: "INSTALL_TIME", + 2: "ON_DEMAND", + 3: "FAST_FOLLOW", +} + +var DeliveryType_value = map[string]int32{ + "UNKNOWN_DELIVERY_TYPE": 0, + "INSTALL_TIME": 1, + "ON_DEMAND": 2, + "FAST_FOLLOW": 3, +} + +func (x DeliveryType) String() string { + return proto.EnumName(DeliveryType_name, int32(x)) +} + +func (DeliveryType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{0} +} + +type SystemApkMetadata_SystemApkType int32 + +const ( + SystemApkMetadata_UNSPECIFIED_VALUE SystemApkMetadata_SystemApkType = 0 + // Uncompressed APK for system image. + SystemApkMetadata_SYSTEM SystemApkMetadata_SystemApkType = 1 + // Stub APK for compressed APK in the system image + // (contains only android manifest). + SystemApkMetadata_SYSTEM_STUB SystemApkMetadata_SystemApkType = 2 + // Compressed APK for system image. + SystemApkMetadata_SYSTEM_COMPRESSED SystemApkMetadata_SystemApkType = 3 +) + +var SystemApkMetadata_SystemApkType_name = map[int32]string{ + 0: "UNSPECIFIED_VALUE", + 1: "SYSTEM", + 2: "SYSTEM_STUB", + 3: "SYSTEM_COMPRESSED", +} + +var SystemApkMetadata_SystemApkType_value = map[string]int32{ + "UNSPECIFIED_VALUE": 0, + "SYSTEM": 1, + "SYSTEM_STUB": 2, + "SYSTEM_COMPRESSED": 3, +} + +func (x SystemApkMetadata_SystemApkType) String() string { + return proto.EnumName(SystemApkMetadata_SystemApkType_name, int32(x)) +} + +func (SystemApkMetadata_SystemApkType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{10, 0} +} + +// Describes the output of the "build-apks" command. +type BuildApksResult struct { + // The package name of this app. + PackageName string `protobuf:"bytes,4,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` + // List of the created variants. + Variant []*Variant `protobuf:"bytes,1,rep,name=variant,proto3" json:"variant,omitempty"` + // Metadata about BundleTool used to build the APKs. + Bundletool *Bundletool `protobuf:"bytes,2,opt,name=bundletool,proto3" json:"bundletool,omitempty"` + // List of the created asset slices. + AssetSliceSet []*AssetSliceSet `protobuf:"bytes,3,rep,name=asset_slice_set,json=assetSliceSet,proto3" json:"asset_slice_set,omitempty"` + // Information about local testing mode. + LocalTestingInfo *LocalTestingInfo `protobuf:"bytes,5,opt,name=local_testing_info,json=localTestingInfo,proto3" json:"local_testing_info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BuildApksResult) Reset() { *m = BuildApksResult{} } +func (m *BuildApksResult) String() string { return proto.CompactTextString(m) } +func (*BuildApksResult) ProtoMessage() {} +func (*BuildApksResult) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{0} +} + +func (m *BuildApksResult) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BuildApksResult.Unmarshal(m, b) +} +func (m *BuildApksResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BuildApksResult.Marshal(b, m, deterministic) +} +func (m *BuildApksResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_BuildApksResult.Merge(m, src) +} +func (m *BuildApksResult) XXX_Size() int { + return xxx_messageInfo_BuildApksResult.Size(m) +} +func (m *BuildApksResult) XXX_DiscardUnknown() { + xxx_messageInfo_BuildApksResult.DiscardUnknown(m) +} + +var xxx_messageInfo_BuildApksResult proto.InternalMessageInfo + +func (m *BuildApksResult) GetPackageName() string { + if m != nil { + return m.PackageName + } + return "" +} + +func (m *BuildApksResult) GetVariant() []*Variant { + if m != nil { + return m.Variant + } + return nil +} + +func (m *BuildApksResult) GetBundletool() *Bundletool { + if m != nil { + return m.Bundletool + } + return nil +} + +func (m *BuildApksResult) GetAssetSliceSet() []*AssetSliceSet { + if m != nil { + return m.AssetSliceSet + } + return nil +} + +func (m *BuildApksResult) GetLocalTestingInfo() *LocalTestingInfo { + if m != nil { + return m.LocalTestingInfo + } + return nil +} + +// Variant is a group of APKs that covers a part of the device configuration +// space. APKs from multiple variants are never combined on one device. +type Variant struct { + // Variant-level targeting. + // This targeting is fairly high-level and each APK has its own targeting as + // well. + Targeting *VariantTargeting `protobuf:"bytes,1,opt,name=targeting,proto3" json:"targeting,omitempty"` + // Set of APKs, one set per module. + ApkSet []*ApkSet `protobuf:"bytes,2,rep,name=apk_set,json=apkSet,proto3" json:"apk_set,omitempty"` + // Number of the variant, starting at 0 (unless overridden). + // A device will receive APKs from the first variant that matches the device + // configuration, with higher variant numbers having priority over lower + // variant numbers. + VariantNumber uint32 `protobuf:"varint,3,opt,name=variant_number,json=variantNumber,proto3" json:"variant_number,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Variant) Reset() { *m = Variant{} } +func (m *Variant) String() string { return proto.CompactTextString(m) } +func (*Variant) ProtoMessage() {} +func (*Variant) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{1} +} + +func (m *Variant) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Variant.Unmarshal(m, b) +} +func (m *Variant) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Variant.Marshal(b, m, deterministic) +} +func (m *Variant) XXX_Merge(src proto.Message) { + xxx_messageInfo_Variant.Merge(m, src) +} +func (m *Variant) XXX_Size() int { + return xxx_messageInfo_Variant.Size(m) +} +func (m *Variant) XXX_DiscardUnknown() { + xxx_messageInfo_Variant.DiscardUnknown(m) +} + +var xxx_messageInfo_Variant proto.InternalMessageInfo + +func (m *Variant) GetTargeting() *VariantTargeting { + if m != nil { + return m.Targeting + } + return nil +} + +func (m *Variant) GetApkSet() []*ApkSet { + if m != nil { + return m.ApkSet + } + return nil +} + +func (m *Variant) GetVariantNumber() uint32 { + if m != nil { + return m.VariantNumber + } + return 0 +} + +// Represents a module. +// For pre-L devices multiple modules (possibly all) may be merged into one. +type ApkSet struct { + ModuleMetadata *ModuleMetadata `protobuf:"bytes,1,opt,name=module_metadata,json=moduleMetadata,proto3" json:"module_metadata,omitempty"` + // APKs. + ApkDescription []*ApkDescription `protobuf:"bytes,2,rep,name=apk_description,json=apkDescription,proto3" json:"apk_description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApkSet) Reset() { *m = ApkSet{} } +func (m *ApkSet) String() string { return proto.CompactTextString(m) } +func (*ApkSet) ProtoMessage() {} +func (*ApkSet) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{2} +} + +func (m *ApkSet) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApkSet.Unmarshal(m, b) +} +func (m *ApkSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApkSet.Marshal(b, m, deterministic) +} +func (m *ApkSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApkSet.Merge(m, src) +} +func (m *ApkSet) XXX_Size() int { + return xxx_messageInfo_ApkSet.Size(m) +} +func (m *ApkSet) XXX_DiscardUnknown() { + xxx_messageInfo_ApkSet.DiscardUnknown(m) +} + +var xxx_messageInfo_ApkSet proto.InternalMessageInfo + +func (m *ApkSet) GetModuleMetadata() *ModuleMetadata { + if m != nil { + return m.ModuleMetadata + } + return nil +} + +func (m *ApkSet) GetApkDescription() []*ApkDescription { + if m != nil { + return m.ApkDescription + } + return nil +} + +type ModuleMetadata struct { + // Module name. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Indicates the delivery type (e.g. on-demand) of the module. + DeliveryType DeliveryType `protobuf:"varint,6,opt,name=delivery_type,json=deliveryType,proto3,enum=android.bundle.DeliveryType" json:"delivery_type,omitempty"` + // Indicates whether this module is marked "instant". + IsInstant bool `protobuf:"varint,3,opt,name=is_instant,json=isInstant,proto3" json:"is_instant,omitempty"` + // Names of the modules that this module directly depends on. + // Each module implicitly depends on the base module. + Dependencies []string `protobuf:"bytes,4,rep,name=dependencies,proto3" json:"dependencies,omitempty"` + // The targeting that makes a conditional module installed. + // Relevant only for Split APKs. + Targeting *ModuleTargeting `protobuf:"bytes,5,opt,name=targeting,proto3" json:"targeting,omitempty"` + // Deprecated. Please use delivery_type. + OnDemandDeprecated bool `protobuf:"varint,2,opt,name=on_demand_deprecated,json=onDemandDeprecated,proto3" json:"on_demand_deprecated,omitempty"` // Deprecated: Do not use. + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ModuleMetadata) Reset() { *m = ModuleMetadata{} } +func (m *ModuleMetadata) String() string { return proto.CompactTextString(m) } +func (*ModuleMetadata) ProtoMessage() {} +func (*ModuleMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{3} +} + +func (m *ModuleMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ModuleMetadata.Unmarshal(m, b) +} +func (m *ModuleMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ModuleMetadata.Marshal(b, m, deterministic) +} +func (m *ModuleMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_ModuleMetadata.Merge(m, src) +} +func (m *ModuleMetadata) XXX_Size() int { + return xxx_messageInfo_ModuleMetadata.Size(m) +} +func (m *ModuleMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_ModuleMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_ModuleMetadata proto.InternalMessageInfo + +func (m *ModuleMetadata) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ModuleMetadata) GetDeliveryType() DeliveryType { + if m != nil { + return m.DeliveryType + } + return DeliveryType_UNKNOWN_DELIVERY_TYPE +} + +func (m *ModuleMetadata) GetIsInstant() bool { + if m != nil { + return m.IsInstant + } + return false +} + +func (m *ModuleMetadata) GetDependencies() []string { + if m != nil { + return m.Dependencies + } + return nil +} + +func (m *ModuleMetadata) GetTargeting() *ModuleTargeting { + if m != nil { + return m.Targeting + } + return nil +} + +// Deprecated: Do not use. +func (m *ModuleMetadata) GetOnDemandDeprecated() bool { + if m != nil { + return m.OnDemandDeprecated + } + return false +} + +// Set of asset slices belonging to a single asset module. +type AssetSliceSet struct { + // Module level metadata. + AssetModuleMetadata *AssetModuleMetadata `protobuf:"bytes,1,opt,name=asset_module_metadata,json=assetModuleMetadata,proto3" json:"asset_module_metadata,omitempty"` + // Asset slices. + ApkDescription []*ApkDescription `protobuf:"bytes,2,rep,name=apk_description,json=apkDescription,proto3" json:"apk_description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssetSliceSet) Reset() { *m = AssetSliceSet{} } +func (m *AssetSliceSet) String() string { return proto.CompactTextString(m) } +func (*AssetSliceSet) ProtoMessage() {} +func (*AssetSliceSet) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{4} +} + +func (m *AssetSliceSet) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AssetSliceSet.Unmarshal(m, b) +} +func (m *AssetSliceSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AssetSliceSet.Marshal(b, m, deterministic) +} +func (m *AssetSliceSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetSliceSet.Merge(m, src) +} +func (m *AssetSliceSet) XXX_Size() int { + return xxx_messageInfo_AssetSliceSet.Size(m) +} +func (m *AssetSliceSet) XXX_DiscardUnknown() { + xxx_messageInfo_AssetSliceSet.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetSliceSet proto.InternalMessageInfo + +func (m *AssetSliceSet) GetAssetModuleMetadata() *AssetModuleMetadata { + if m != nil { + return m.AssetModuleMetadata + } + return nil +} + +func (m *AssetSliceSet) GetApkDescription() []*ApkDescription { + if m != nil { + return m.ApkDescription + } + return nil +} + +type AssetModuleMetadata struct { + // Module name. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Indicates the delivery type for persistent install. + DeliveryType DeliveryType `protobuf:"varint,4,opt,name=delivery_type,json=deliveryType,proto3,enum=android.bundle.DeliveryType" json:"delivery_type,omitempty"` + // Metadata for instant installs. + InstantMetadata *InstantMetadata `protobuf:"bytes,3,opt,name=instant_metadata,json=instantMetadata,proto3" json:"instant_metadata,omitempty"` + // Deprecated. Use delivery_type. + OnDemandDeprecated bool `protobuf:"varint,2,opt,name=on_demand_deprecated,json=onDemandDeprecated,proto3" json:"on_demand_deprecated,omitempty"` // Deprecated: Do not use. + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssetModuleMetadata) Reset() { *m = AssetModuleMetadata{} } +func (m *AssetModuleMetadata) String() string { return proto.CompactTextString(m) } +func (*AssetModuleMetadata) ProtoMessage() {} +func (*AssetModuleMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{5} +} + +func (m *AssetModuleMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AssetModuleMetadata.Unmarshal(m, b) +} +func (m *AssetModuleMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AssetModuleMetadata.Marshal(b, m, deterministic) +} +func (m *AssetModuleMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetModuleMetadata.Merge(m, src) +} +func (m *AssetModuleMetadata) XXX_Size() int { + return xxx_messageInfo_AssetModuleMetadata.Size(m) +} +func (m *AssetModuleMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_AssetModuleMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetModuleMetadata proto.InternalMessageInfo + +func (m *AssetModuleMetadata) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AssetModuleMetadata) GetDeliveryType() DeliveryType { + if m != nil { + return m.DeliveryType + } + return DeliveryType_UNKNOWN_DELIVERY_TYPE +} + +func (m *AssetModuleMetadata) GetInstantMetadata() *InstantMetadata { + if m != nil { + return m.InstantMetadata + } + return nil +} + +// Deprecated: Do not use. +func (m *AssetModuleMetadata) GetOnDemandDeprecated() bool { + if m != nil { + return m.OnDemandDeprecated + } + return false +} + +type InstantMetadata struct { + // Indicates whether this module is marked "instant". + IsInstant bool `protobuf:"varint,1,opt,name=is_instant,json=isInstant,proto3" json:"is_instant,omitempty"` + // Indicates the delivery type for instant install. + DeliveryType DeliveryType `protobuf:"varint,3,opt,name=delivery_type,json=deliveryType,proto3,enum=android.bundle.DeliveryType" json:"delivery_type,omitempty"` + // Deprecated. Use delivery_type. + OnDemandDeprecated bool `protobuf:"varint,2,opt,name=on_demand_deprecated,json=onDemandDeprecated,proto3" json:"on_demand_deprecated,omitempty"` // Deprecated: Do not use. + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InstantMetadata) Reset() { *m = InstantMetadata{} } +func (m *InstantMetadata) String() string { return proto.CompactTextString(m) } +func (*InstantMetadata) ProtoMessage() {} +func (*InstantMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{6} +} + +func (m *InstantMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InstantMetadata.Unmarshal(m, b) +} +func (m *InstantMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InstantMetadata.Marshal(b, m, deterministic) +} +func (m *InstantMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_InstantMetadata.Merge(m, src) +} +func (m *InstantMetadata) XXX_Size() int { + return xxx_messageInfo_InstantMetadata.Size(m) +} +func (m *InstantMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_InstantMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_InstantMetadata proto.InternalMessageInfo + +func (m *InstantMetadata) GetIsInstant() bool { + if m != nil { + return m.IsInstant + } + return false +} + +func (m *InstantMetadata) GetDeliveryType() DeliveryType { + if m != nil { + return m.DeliveryType + } + return DeliveryType_UNKNOWN_DELIVERY_TYPE +} + +// Deprecated: Do not use. +func (m *InstantMetadata) GetOnDemandDeprecated() bool { + if m != nil { + return m.OnDemandDeprecated + } + return false +} + +type ApkDescription struct { + Targeting *ApkTargeting `protobuf:"bytes,1,opt,name=targeting,proto3" json:"targeting,omitempty"` + // Path to the APK file. + // BEGIN-INTERNAL + // The path may be a blobkey if the proto is not constructed by bundletool. + // END-INTERNAL + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + // Types that are valid to be assigned to ApkMetadataOneofValue: + // *ApkDescription_SplitApkMetadata + // *ApkDescription_StandaloneApkMetadata + // *ApkDescription_InstantApkMetadata + // *ApkDescription_SystemApkMetadata + // *ApkDescription_AssetSliceMetadata + // *ApkDescription_ApexApkMetadata + ApkMetadataOneofValue isApkDescription_ApkMetadataOneofValue `protobuf_oneof:"apk_metadata_oneof_value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApkDescription) Reset() { *m = ApkDescription{} } +func (m *ApkDescription) String() string { return proto.CompactTextString(m) } +func (*ApkDescription) ProtoMessage() {} +func (*ApkDescription) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{7} +} + +func (m *ApkDescription) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApkDescription.Unmarshal(m, b) +} +func (m *ApkDescription) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApkDescription.Marshal(b, m, deterministic) +} +func (m *ApkDescription) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApkDescription.Merge(m, src) +} +func (m *ApkDescription) XXX_Size() int { + return xxx_messageInfo_ApkDescription.Size(m) +} +func (m *ApkDescription) XXX_DiscardUnknown() { + xxx_messageInfo_ApkDescription.DiscardUnknown(m) +} + +var xxx_messageInfo_ApkDescription proto.InternalMessageInfo + +func (m *ApkDescription) GetTargeting() *ApkTargeting { + if m != nil { + return m.Targeting + } + return nil +} + +func (m *ApkDescription) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +type isApkDescription_ApkMetadataOneofValue interface { + isApkDescription_ApkMetadataOneofValue() +} + +type ApkDescription_SplitApkMetadata struct { + SplitApkMetadata *SplitApkMetadata `protobuf:"bytes,3,opt,name=split_apk_metadata,json=splitApkMetadata,proto3,oneof"` +} + +type ApkDescription_StandaloneApkMetadata struct { + StandaloneApkMetadata *StandaloneApkMetadata `protobuf:"bytes,4,opt,name=standalone_apk_metadata,json=standaloneApkMetadata,proto3,oneof"` +} + +type ApkDescription_InstantApkMetadata struct { + InstantApkMetadata *SplitApkMetadata `protobuf:"bytes,5,opt,name=instant_apk_metadata,json=instantApkMetadata,proto3,oneof"` +} + +type ApkDescription_SystemApkMetadata struct { + SystemApkMetadata *SystemApkMetadata `protobuf:"bytes,6,opt,name=system_apk_metadata,json=systemApkMetadata,proto3,oneof"` +} + +type ApkDescription_AssetSliceMetadata struct { + AssetSliceMetadata *SplitApkMetadata `protobuf:"bytes,7,opt,name=asset_slice_metadata,json=assetSliceMetadata,proto3,oneof"` +} + +type ApkDescription_ApexApkMetadata struct { + ApexApkMetadata *ApexApkMetadata `protobuf:"bytes,8,opt,name=apex_apk_metadata,json=apexApkMetadata,proto3,oneof"` +} + +func (*ApkDescription_SplitApkMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (*ApkDescription_StandaloneApkMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (*ApkDescription_InstantApkMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (*ApkDescription_SystemApkMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (*ApkDescription_AssetSliceMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (*ApkDescription_ApexApkMetadata) isApkDescription_ApkMetadataOneofValue() {} + +func (m *ApkDescription) GetApkMetadataOneofValue() isApkDescription_ApkMetadataOneofValue { + if m != nil { + return m.ApkMetadataOneofValue + } + return nil +} + +func (m *ApkDescription) GetSplitApkMetadata() *SplitApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_SplitApkMetadata); ok { + return x.SplitApkMetadata + } + return nil +} + +func (m *ApkDescription) GetStandaloneApkMetadata() *StandaloneApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_StandaloneApkMetadata); ok { + return x.StandaloneApkMetadata + } + return nil +} + +func (m *ApkDescription) GetInstantApkMetadata() *SplitApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_InstantApkMetadata); ok { + return x.InstantApkMetadata + } + return nil +} + +func (m *ApkDescription) GetSystemApkMetadata() *SystemApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_SystemApkMetadata); ok { + return x.SystemApkMetadata + } + return nil +} + +func (m *ApkDescription) GetAssetSliceMetadata() *SplitApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_AssetSliceMetadata); ok { + return x.AssetSliceMetadata + } + return nil +} + +func (m *ApkDescription) GetApexApkMetadata() *ApexApkMetadata { + if x, ok := m.GetApkMetadataOneofValue().(*ApkDescription_ApexApkMetadata); ok { + return x.ApexApkMetadata + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*ApkDescription) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*ApkDescription_SplitApkMetadata)(nil), + (*ApkDescription_StandaloneApkMetadata)(nil), + (*ApkDescription_InstantApkMetadata)(nil), + (*ApkDescription_SystemApkMetadata)(nil), + (*ApkDescription_AssetSliceMetadata)(nil), + (*ApkDescription_ApexApkMetadata)(nil), + } +} + +// Holds data specific to Split APKs. +type SplitApkMetadata struct { + SplitId string `protobuf:"bytes,1,opt,name=split_id,json=splitId,proto3" json:"split_id,omitempty"` + // Indicates whether this APK is the master split of the module. + IsMasterSplit bool `protobuf:"varint,2,opt,name=is_master_split,json=isMasterSplit,proto3" json:"is_master_split,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SplitApkMetadata) Reset() { *m = SplitApkMetadata{} } +func (m *SplitApkMetadata) String() string { return proto.CompactTextString(m) } +func (*SplitApkMetadata) ProtoMessage() {} +func (*SplitApkMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{8} +} + +func (m *SplitApkMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SplitApkMetadata.Unmarshal(m, b) +} +func (m *SplitApkMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SplitApkMetadata.Marshal(b, m, deterministic) +} +func (m *SplitApkMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_SplitApkMetadata.Merge(m, src) +} +func (m *SplitApkMetadata) XXX_Size() int { + return xxx_messageInfo_SplitApkMetadata.Size(m) +} +func (m *SplitApkMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_SplitApkMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_SplitApkMetadata proto.InternalMessageInfo + +func (m *SplitApkMetadata) GetSplitId() string { + if m != nil { + return m.SplitId + } + return "" +} + +func (m *SplitApkMetadata) GetIsMasterSplit() bool { + if m != nil { + return m.IsMasterSplit + } + return false +} + +// Holds data specific to Standalone APKs. +type StandaloneApkMetadata struct { + // Names of the modules fused in this standalone APK. + FusedModuleName []string `protobuf:"bytes,1,rep,name=fused_module_name,json=fusedModuleName,proto3" json:"fused_module_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StandaloneApkMetadata) Reset() { *m = StandaloneApkMetadata{} } +func (m *StandaloneApkMetadata) String() string { return proto.CompactTextString(m) } +func (*StandaloneApkMetadata) ProtoMessage() {} +func (*StandaloneApkMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{9} +} + +func (m *StandaloneApkMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StandaloneApkMetadata.Unmarshal(m, b) +} +func (m *StandaloneApkMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StandaloneApkMetadata.Marshal(b, m, deterministic) +} +func (m *StandaloneApkMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_StandaloneApkMetadata.Merge(m, src) +} +func (m *StandaloneApkMetadata) XXX_Size() int { + return xxx_messageInfo_StandaloneApkMetadata.Size(m) +} +func (m *StandaloneApkMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_StandaloneApkMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_StandaloneApkMetadata proto.InternalMessageInfo + +func (m *StandaloneApkMetadata) GetFusedModuleName() []string { + if m != nil { + return m.FusedModuleName + } + return nil +} + +// Holds data specific to system APKs. +type SystemApkMetadata struct { + // Names of the modules fused in this system APK. + FusedModuleName []string `protobuf:"bytes,1,rep,name=fused_module_name,json=fusedModuleName,proto3" json:"fused_module_name,omitempty"` + // Indicates whether the APK is uncompressed system APK, stub APK or + // compressed system APK. + SystemApkType SystemApkMetadata_SystemApkType `protobuf:"varint,2,opt,name=system_apk_type,json=systemApkType,proto3,enum=android.bundle.SystemApkMetadata_SystemApkType" json:"system_apk_type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SystemApkMetadata) Reset() { *m = SystemApkMetadata{} } +func (m *SystemApkMetadata) String() string { return proto.CompactTextString(m) } +func (*SystemApkMetadata) ProtoMessage() {} +func (*SystemApkMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{10} +} + +func (m *SystemApkMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SystemApkMetadata.Unmarshal(m, b) +} +func (m *SystemApkMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SystemApkMetadata.Marshal(b, m, deterministic) +} +func (m *SystemApkMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_SystemApkMetadata.Merge(m, src) +} +func (m *SystemApkMetadata) XXX_Size() int { + return xxx_messageInfo_SystemApkMetadata.Size(m) +} +func (m *SystemApkMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_SystemApkMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_SystemApkMetadata proto.InternalMessageInfo + +func (m *SystemApkMetadata) GetFusedModuleName() []string { + if m != nil { + return m.FusedModuleName + } + return nil +} + +func (m *SystemApkMetadata) GetSystemApkType() SystemApkMetadata_SystemApkType { + if m != nil { + return m.SystemApkType + } + return SystemApkMetadata_UNSPECIFIED_VALUE +} + +// Holds data specific to APEX APKs. +type ApexApkMetadata struct { + // Configuration for processing of APKs embedded in an APEX image. + ApexEmbeddedApkConfig []*ApexEmbeddedApkConfig `protobuf:"bytes,1,rep,name=apex_embedded_apk_config,json=apexEmbeddedApkConfig,proto3" json:"apex_embedded_apk_config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApexApkMetadata) Reset() { *m = ApexApkMetadata{} } +func (m *ApexApkMetadata) String() string { return proto.CompactTextString(m) } +func (*ApexApkMetadata) ProtoMessage() {} +func (*ApexApkMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{11} +} + +func (m *ApexApkMetadata) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApexApkMetadata.Unmarshal(m, b) +} +func (m *ApexApkMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApexApkMetadata.Marshal(b, m, deterministic) +} +func (m *ApexApkMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApexApkMetadata.Merge(m, src) +} +func (m *ApexApkMetadata) XXX_Size() int { + return xxx_messageInfo_ApexApkMetadata.Size(m) +} +func (m *ApexApkMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_ApexApkMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_ApexApkMetadata proto.InternalMessageInfo + +func (m *ApexApkMetadata) GetApexEmbeddedApkConfig() []*ApexEmbeddedApkConfig { + if m != nil { + return m.ApexEmbeddedApkConfig + } + return nil +} + +type LocalTestingInfo struct { + // Indicates if the bundle is built in local testing mode. + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + // The local testing path, as specified in the base manifest. + // This refers to the relative path on the external directory of the app where + // APKs will be pushed for local testing. + // Set only if local testing is enabled. + LocalTestingPath string `protobuf:"bytes,2,opt,name=local_testing_path,json=localTestingPath,proto3" json:"local_testing_path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LocalTestingInfo) Reset() { *m = LocalTestingInfo{} } +func (m *LocalTestingInfo) String() string { return proto.CompactTextString(m) } +func (*LocalTestingInfo) ProtoMessage() {} +func (*LocalTestingInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_0dff099eb2e3dfdb, []int{12} +} + +func (m *LocalTestingInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LocalTestingInfo.Unmarshal(m, b) +} +func (m *LocalTestingInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LocalTestingInfo.Marshal(b, m, deterministic) +} +func (m *LocalTestingInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_LocalTestingInfo.Merge(m, src) +} +func (m *LocalTestingInfo) XXX_Size() int { + return xxx_messageInfo_LocalTestingInfo.Size(m) +} +func (m *LocalTestingInfo) XXX_DiscardUnknown() { + xxx_messageInfo_LocalTestingInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_LocalTestingInfo proto.InternalMessageInfo + +func (m *LocalTestingInfo) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +func (m *LocalTestingInfo) GetLocalTestingPath() string { + if m != nil { + return m.LocalTestingPath + } + return "" +} + +func init() { + proto.RegisterEnum("android.bundle.DeliveryType", DeliveryType_name, DeliveryType_value) + proto.RegisterEnum("android.bundle.SystemApkMetadata_SystemApkType", SystemApkMetadata_SystemApkType_name, SystemApkMetadata_SystemApkType_value) + proto.RegisterType((*BuildApksResult)(nil), "android.bundle.BuildApksResult") + proto.RegisterType((*Variant)(nil), "android.bundle.Variant") + proto.RegisterType((*ApkSet)(nil), "android.bundle.ApkSet") + proto.RegisterType((*ModuleMetadata)(nil), "android.bundle.ModuleMetadata") + proto.RegisterType((*AssetSliceSet)(nil), "android.bundle.AssetSliceSet") + proto.RegisterType((*AssetModuleMetadata)(nil), "android.bundle.AssetModuleMetadata") + proto.RegisterType((*InstantMetadata)(nil), "android.bundle.InstantMetadata") + proto.RegisterType((*ApkDescription)(nil), "android.bundle.ApkDescription") + proto.RegisterType((*SplitApkMetadata)(nil), "android.bundle.SplitApkMetadata") + proto.RegisterType((*StandaloneApkMetadata)(nil), "android.bundle.StandaloneApkMetadata") + proto.RegisterType((*SystemApkMetadata)(nil), "android.bundle.SystemApkMetadata") + proto.RegisterType((*ApexApkMetadata)(nil), "android.bundle.ApexApkMetadata") + proto.RegisterType((*LocalTestingInfo)(nil), "android.bundle.LocalTestingInfo") +} + +func init() { + proto.RegisterFile("commands.proto", fileDescriptor_0dff099eb2e3dfdb) +} + +var fileDescriptor_0dff099eb2e3dfdb = []byte{ + // 1104 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6f, 0xe2, 0x46, + 0x14, 0x5e, 0x03, 0x0b, 0xe1, 0x05, 0xb0, 0x33, 0x1b, 0xba, 0xde, 0x68, 0x77, 0xcb, 0xba, 0x4a, + 0x85, 0xa2, 0x2a, 0xab, 0xa6, 0x3d, 0xad, 0xd4, 0x4a, 0x10, 0x9c, 0x96, 0x2d, 0x90, 0xc8, 0x26, + 0x89, 0x92, 0x4a, 0x1d, 0x4d, 0x98, 0x49, 0xd6, 0xc2, 0xbf, 0xca, 0x98, 0x28, 0xf9, 0x57, 0x7a, + 0xa9, 0x7a, 0xec, 0xb1, 0xd7, 0xfe, 0x51, 0x3d, 0xf5, 0xde, 0xca, 0x63, 0x03, 0xb6, 0xb1, 0xd4, + 0x64, 0xd5, 0x13, 0x7e, 0x6f, 0xbe, 0xf9, 0xe6, 0xbd, 0xf7, 0xbd, 0x79, 0x0c, 0x34, 0x26, 0x9e, + 0xe3, 0x10, 0x97, 0xf2, 0x7d, 0x7f, 0xe6, 0x05, 0x1e, 0x6a, 0x10, 0x97, 0xce, 0x3c, 0x8b, 0xee, + 0x5f, 0xcd, 0x5d, 0x6a, 0xb3, 0x9d, 0xda, 0xc4, 0x73, 0xaf, 0xad, 0x9b, 0x68, 0x75, 0x47, 0x0e, + 0xc8, 0xec, 0x86, 0x05, 0x96, 0x1b, 0x3b, 0xb4, 0x3f, 0x0b, 0x20, 0x77, 0xe7, 0x96, 0x4d, 0x3b, + 0xfe, 0x94, 0x1b, 0x8c, 0xcf, 0xed, 0x00, 0xbd, 0x81, 0x9a, 0x4f, 0x26, 0x53, 0x72, 0xc3, 0xb0, + 0x4b, 0x1c, 0xa6, 0x96, 0x5a, 0x52, 0xbb, 0x6a, 0x6c, 0xc6, 0xbe, 0x11, 0x71, 0x18, 0xfa, 0x12, + 0x2a, 0xb7, 0x64, 0x66, 0x11, 0x37, 0x50, 0xa5, 0x56, 0xb1, 0xbd, 0x79, 0xf0, 0x7c, 0x3f, 0x7d, + 0xee, 0xfe, 0x59, 0xb4, 0x6c, 0x2c, 0x70, 0xe8, 0x1d, 0x40, 0xb4, 0x14, 0x78, 0x9e, 0xad, 0x16, + 0x5a, 0x52, 0x7b, 0xf3, 0x60, 0x27, 0xbb, 0xab, 0xbb, 0x44, 0x18, 0x09, 0x34, 0xd2, 0x41, 0x26, + 0x9c, 0xb3, 0x00, 0x73, 0xdb, 0x9a, 0x30, 0xcc, 0x59, 0xa0, 0x16, 0xc5, 0xb1, 0xaf, 0xb2, 0x04, + 0x9d, 0x10, 0x66, 0x86, 0x28, 0x93, 0x05, 0x46, 0x9d, 0x24, 0x4d, 0x34, 0x02, 0x64, 0x7b, 0x13, + 0x62, 0xe3, 0x80, 0xf1, 0xb0, 0x06, 0xd8, 0x72, 0xaf, 0x3d, 0xf5, 0xa9, 0x08, 0xa5, 0x95, 0x65, + 0x1a, 0x84, 0xc8, 0x71, 0x04, 0xec, 0xbb, 0xd7, 0x9e, 0xa1, 0xd8, 0x19, 0x8f, 0xf6, 0x9b, 0x04, + 0x95, 0x38, 0x4f, 0xf4, 0x2d, 0x54, 0x97, 0xb5, 0x55, 0xa5, 0x7c, 0xca, 0x18, 0x3b, 0x5e, 0xe0, + 0x8c, 0xd5, 0x16, 0xf4, 0x16, 0x2a, 0xc4, 0x9f, 0x8a, 0xd4, 0x0a, 0x22, 0xb5, 0x4f, 0xd6, 0x52, + 0xf3, 0xa7, 0x61, 0x4e, 0x65, 0x22, 0x7e, 0xd1, 0x2e, 0x34, 0xe2, 0xd2, 0x62, 0x77, 0xee, 0x5c, + 0xb1, 0x99, 0x5a, 0x6c, 0x49, 0xed, 0xba, 0x51, 0x8f, 0xbd, 0x23, 0xe1, 0xd4, 0x7e, 0x91, 0xa0, + 0x1c, 0xed, 0x44, 0xdf, 0x81, 0xec, 0x78, 0x74, 0x6e, 0x33, 0xec, 0xb0, 0x80, 0x50, 0x12, 0x90, + 0x38, 0xd0, 0xd7, 0xd9, 0xa3, 0x86, 0x02, 0x36, 0x8c, 0x51, 0x46, 0xc3, 0x49, 0xd9, 0x21, 0x51, + 0x18, 0x2b, 0x65, 0x7c, 0x32, 0xb3, 0xfc, 0xc0, 0xf2, 0xdc, 0x38, 0xe6, 0xd7, 0x39, 0x31, 0xf7, + 0x56, 0x28, 0xa3, 0x41, 0x52, 0xb6, 0xf6, 0x6b, 0x01, 0x1a, 0xe9, 0xb3, 0x10, 0x82, 0x92, 0x68, + 0x3a, 0x49, 0x34, 0x9d, 0xf8, 0x46, 0x1d, 0xa8, 0x53, 0x66, 0x5b, 0xb7, 0x6c, 0x76, 0x8f, 0x83, + 0x7b, 0x9f, 0xa9, 0xe5, 0x96, 0xd4, 0x6e, 0x1c, 0xbc, 0xcc, 0x9e, 0xd6, 0x8b, 0x41, 0xe3, 0x7b, + 0x9f, 0x19, 0x35, 0x9a, 0xb0, 0xd0, 0x2b, 0x00, 0x8b, 0x63, 0xcb, 0xe5, 0x41, 0xd8, 0xb3, 0x61, + 0xa5, 0x36, 0x8c, 0xaa, 0xc5, 0xfb, 0x91, 0x03, 0x69, 0x50, 0xa3, 0xcc, 0x67, 0x2e, 0x65, 0xee, + 0xc4, 0x62, 0x5c, 0x2d, 0xb5, 0x8a, 0xed, 0xaa, 0x91, 0xf2, 0xa1, 0x6f, 0x92, 0x0a, 0x47, 0x4d, + 0xf3, 0x69, 0x7e, 0xe1, 0x72, 0x05, 0xfe, 0x1a, 0xb6, 0x3d, 0x17, 0x53, 0x16, 0x5e, 0x56, 0x4c, + 0x99, 0x3f, 0x63, 0x13, 0x12, 0x30, 0x2a, 0x6e, 0xc2, 0x46, 0xb7, 0xa0, 0x4a, 0x06, 0xf2, 0xdc, + 0x9e, 0x58, 0xee, 0x2d, 0x57, 0xb5, 0x3f, 0x24, 0xa8, 0xa7, 0x7a, 0x1a, 0x9d, 0x43, 0x33, 0xba, + 0x0b, 0xf9, 0x5a, 0x7e, 0x96, 0x7b, 0x23, 0x32, 0x82, 0x3e, 0x23, 0xeb, 0xce, 0xff, 0x4f, 0xd5, + 0xbf, 0x24, 0x78, 0x96, 0x73, 0xea, 0xc3, 0xa4, 0x2d, 0x3d, 0x5a, 0xda, 0xf7, 0xa0, 0xc4, 0xba, + 0xae, 0x6a, 0x51, 0xcc, 0x97, 0x27, 0x96, 0x7b, 0x59, 0x07, 0xd9, 0x4a, 0x3b, 0x3e, 0x52, 0xa4, + 0xdf, 0x25, 0x90, 0x33, 0xd4, 0x99, 0x86, 0x93, 0xb2, 0x0d, 0xb7, 0x96, 0x77, 0xf1, 0xd1, 0x79, + 0x7f, 0x5c, 0xac, 0xff, 0x94, 0xa0, 0x91, 0xd6, 0x0f, 0xbd, 0x5b, 0x1f, 0x5d, 0x2f, 0x73, 0x24, + 0xcf, 0xed, 0x6a, 0x04, 0x25, 0x9f, 0x04, 0x1f, 0xc4, 0xa1, 0x55, 0x43, 0x7c, 0xa3, 0x13, 0x40, + 0xdc, 0xb7, 0xad, 0x00, 0x87, 0xed, 0x94, 0x91, 0x64, 0x6d, 0x26, 0x9a, 0x21, 0xb2, 0xe3, 0x4f, + 0x17, 0x85, 0xfb, 0xfe, 0x89, 0xa1, 0xf0, 0x8c, 0x0f, 0x61, 0x78, 0x1e, 0x96, 0x8d, 0x12, 0xdb, + 0x73, 0x59, 0x9a, 0xb6, 0x24, 0x68, 0x77, 0xd7, 0x68, 0x97, 0xf0, 0x34, 0x77, 0x93, 0xe7, 0x2d, + 0xa0, 0x31, 0x6c, 0x2f, 0x7a, 0x28, 0xc5, 0xfe, 0xf4, 0xc1, 0x41, 0xa3, 0x78, 0x7f, 0x92, 0xd5, + 0x84, 0x67, 0xfc, 0x9e, 0x07, 0xcc, 0x49, 0x93, 0x96, 0x05, 0xe9, 0x9b, 0x35, 0x52, 0x01, 0x4d, + 0xb3, 0x6e, 0xf1, 0xac, 0x33, 0x0c, 0x35, 0xf9, 0x5f, 0xb8, 0x64, 0xad, 0x3c, 0x3c, 0xd4, 0xd5, + 0xbf, 0xe2, 0x92, 0x75, 0x08, 0x5b, 0xc4, 0x67, 0x77, 0xe9, 0x40, 0x37, 0xf2, 0x6f, 0x51, 0xc7, + 0x67, 0x77, 0x69, 0x46, 0x99, 0xa4, 0x5d, 0xdd, 0x1d, 0x50, 0x93, 0x4c, 0xd8, 0x73, 0x99, 0x77, + 0x8d, 0x6f, 0x89, 0x3d, 0x67, 0xda, 0x29, 0x28, 0xd9, 0xa0, 0xd0, 0x0b, 0xd8, 0x88, 0x5a, 0xc6, + 0xa2, 0xf1, 0x78, 0xa8, 0x08, 0xbb, 0x4f, 0xd1, 0xe7, 0x20, 0x5b, 0x1c, 0x3b, 0x84, 0x07, 0x6c, + 0x86, 0x85, 0x33, 0xea, 0x70, 0xa3, 0x6e, 0xf1, 0xa1, 0xf0, 0x0a, 0x36, 0xad, 0x0f, 0xcd, 0x5c, + 0xd1, 0xd1, 0x1e, 0x6c, 0x5d, 0xcf, 0x39, 0xa3, 0x8b, 0x81, 0x19, 0xcf, 0xa0, 0x70, 0xc0, 0xcb, + 0x62, 0x21, 0x1a, 0x53, 0xe1, 0xbb, 0xe6, 0x7d, 0x69, 0xa3, 0xa0, 0x14, 0xb5, 0xbf, 0x25, 0xd8, + 0x5a, 0x53, 0xe3, 0x31, 0x3c, 0xe8, 0x1c, 0xe4, 0x84, 0xf2, 0xe2, 0x82, 0x17, 0xc4, 0x05, 0x7f, + 0xfb, 0x9f, 0xaa, 0xaf, 0x3c, 0xe2, 0xce, 0xd7, 0x79, 0xd2, 0xd4, 0x2e, 0xa1, 0x9e, 0x5a, 0x47, + 0x4d, 0xd8, 0x3a, 0x1d, 0x99, 0x27, 0xfa, 0x61, 0xff, 0xa8, 0xaf, 0xf7, 0xf0, 0x59, 0x67, 0x70, + 0xaa, 0x2b, 0x4f, 0x10, 0x40, 0xd9, 0xbc, 0x30, 0xc7, 0xfa, 0x50, 0x91, 0x90, 0x0c, 0x9b, 0xd1, + 0x37, 0x36, 0xc7, 0xa7, 0x5d, 0xa5, 0x10, 0xee, 0x89, 0x1d, 0x87, 0xc7, 0xc3, 0x13, 0x43, 0x37, + 0x4d, 0xbd, 0xa7, 0x14, 0xb5, 0x9f, 0x41, 0xce, 0x48, 0x8b, 0x7e, 0x0a, 0x75, 0x64, 0x77, 0x98, + 0x39, 0x57, 0x8c, 0x52, 0x46, 0x45, 0x3a, 0xd1, 0x8b, 0x32, 0x7e, 0xf8, 0xed, 0xe6, 0x75, 0x87, + 0x1e, 0xc3, 0x3b, 0xfe, 0xf4, 0x50, 0x80, 0x8d, 0x26, 0xc9, 0x73, 0x6b, 0x97, 0xa0, 0x64, 0xdf, + 0x59, 0x48, 0x85, 0x0a, 0x73, 0xc9, 0x95, 0xcd, 0x68, 0x3c, 0x36, 0x17, 0x26, 0xfa, 0x22, 0xfb, + 0x7e, 0x4b, 0x8c, 0x9e, 0xd4, 0xeb, 0xec, 0x84, 0x04, 0x1f, 0xf6, 0x7e, 0x84, 0x5a, 0x72, 0x7a, + 0xa2, 0x17, 0xd0, 0x3c, 0x1d, 0xfd, 0x30, 0x3a, 0x3e, 0x1f, 0xe1, 0x9e, 0x3e, 0xe8, 0x9f, 0xe9, + 0xc6, 0x05, 0x1e, 0x5f, 0x9c, 0x84, 0xd5, 0x52, 0xa0, 0xd6, 0x1f, 0x99, 0xe3, 0xce, 0x60, 0x80, + 0xc7, 0xfd, 0xa1, 0xae, 0x48, 0xa8, 0x0e, 0xd5, 0xe3, 0x10, 0x37, 0xec, 0x8c, 0x7a, 0x4a, 0x21, + 0x2c, 0xe1, 0x51, 0xc7, 0x1c, 0xe3, 0xa3, 0xe3, 0xc1, 0xe0, 0xf8, 0x5c, 0x29, 0x76, 0xf7, 0x00, + 0x4d, 0x3c, 0x27, 0x93, 0xfb, 0xe5, 0x76, 0x6c, 0xe3, 0xc8, 0xc6, 0xe2, 0x8d, 0x7d, 0x55, 0x16, + 0x3f, 0x5f, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xe5, 0xcb, 0x87, 0xab, 0x0b, 0x00, 0x00, +} diff --git a/cmd/extract_apks/bundle_proto/commands.proto b/cmd/extract_apks/bundle_proto/commands.proto new file mode 100644 index 000000000..b36340b08 --- /dev/null +++ b/cmd/extract_apks/bundle_proto/commands.proto @@ -0,0 +1,197 @@ +// Messages describing APK Set's table of contents (toc.pb entry). +// Please be advised that the ultimate source is at +// https://github.com/google/bundletool/tree/master/src/main/proto +// so you have been warned. +syntax = "proto3"; + +package android.bundle; + +import "config.proto"; +import "targeting.proto"; + +option go_package = "android_bundle_proto"; +option java_package = "com.android.bundle"; + +// Describes the output of the "build-apks" command. +message BuildApksResult { + // The package name of this app. + string package_name = 4; + + // List of the created variants. + repeated Variant variant = 1; + + // Metadata about BundleTool used to build the APKs. + Bundletool bundletool = 2; + + // List of the created asset slices. + repeated AssetSliceSet asset_slice_set = 3; + + // Information about local testing mode. + LocalTestingInfo local_testing_info = 5; +} + +// Variant is a group of APKs that covers a part of the device configuration +// space. APKs from multiple variants are never combined on one device. +message Variant { + // Variant-level targeting. + // This targeting is fairly high-level and each APK has its own targeting as + // well. + VariantTargeting targeting = 1; + + // Set of APKs, one set per module. + repeated ApkSet apk_set = 2; + + // Number of the variant, starting at 0 (unless overridden). + // A device will receive APKs from the first variant that matches the device + // configuration, with higher variant numbers having priority over lower + // variant numbers. + uint32 variant_number = 3; +} + +// Represents a module. +// For pre-L devices multiple modules (possibly all) may be merged into one. +message ApkSet { + ModuleMetadata module_metadata = 1; + + // APKs. + repeated ApkDescription apk_description = 2; +} + +message ModuleMetadata { + // Module name. + string name = 1; + + // Indicates the delivery type (e.g. on-demand) of the module. + DeliveryType delivery_type = 6; + + // Indicates whether this module is marked "instant". + bool is_instant = 3; + + // Names of the modules that this module directly depends on. + // Each module implicitly depends on the base module. + repeated string dependencies = 4; + + // The targeting that makes a conditional module installed. + // Relevant only for Split APKs. + ModuleTargeting targeting = 5; + + // Deprecated. Please use delivery_type. + bool on_demand_deprecated = 2 [deprecated = true]; +} + +// Set of asset slices belonging to a single asset module. +message AssetSliceSet { + // Module level metadata. + AssetModuleMetadata asset_module_metadata = 1; + + // Asset slices. + repeated ApkDescription apk_description = 2; +} + +message AssetModuleMetadata { + // Module name. + string name = 1; + + // Indicates the delivery type for persistent install. + DeliveryType delivery_type = 4; + + // Metadata for instant installs. + InstantMetadata instant_metadata = 3; + + // Deprecated. Use delivery_type. + bool on_demand_deprecated = 2 [deprecated = true]; +} + +message InstantMetadata { + // Indicates whether this module is marked "instant". + bool is_instant = 1; + + // Indicates the delivery type for instant install. + DeliveryType delivery_type = 3; + + // Deprecated. Use delivery_type. + bool on_demand_deprecated = 2 [deprecated = true]; +} + +enum DeliveryType { + UNKNOWN_DELIVERY_TYPE = 0; + INSTALL_TIME = 1; + ON_DEMAND = 2; + FAST_FOLLOW = 3; +} + +message ApkDescription { + ApkTargeting targeting = 1; + + // Path to the APK file. + // BEGIN-INTERNAL + // The path may be a blobkey if the proto is not constructed by bundletool. + // END-INTERNAL + string path = 2; + + oneof apk_metadata_oneof_value { + // Set only for Split APKs. + SplitApkMetadata split_apk_metadata = 3; + // Set only for standalone APKs. + StandaloneApkMetadata standalone_apk_metadata = 4; + // Set only for Instant split APKs. + SplitApkMetadata instant_apk_metadata = 5; + // Set only for system APKs. + SystemApkMetadata system_apk_metadata = 6; + // Set only for asset slices. + SplitApkMetadata asset_slice_metadata = 7; + // Set only for APEX APKs. + ApexApkMetadata apex_apk_metadata = 8; + } +} + +// Holds data specific to Split APKs. +message SplitApkMetadata { + string split_id = 1; + + // Indicates whether this APK is the master split of the module. + bool is_master_split = 2; +} + +// Holds data specific to Standalone APKs. +message StandaloneApkMetadata { + // Names of the modules fused in this standalone APK. + repeated string fused_module_name = 1; + + reserved 2; +} + +// Holds data specific to system APKs. +message SystemApkMetadata { + // Names of the modules fused in this system APK. + repeated string fused_module_name = 1; + enum SystemApkType { + UNSPECIFIED_VALUE = 0; + // Uncompressed APK for system image. + SYSTEM = 1; + // Stub APK for compressed APK in the system image + // (contains only android manifest). + SYSTEM_STUB = 2; + // Compressed APK for system image. + SYSTEM_COMPRESSED = 3; + } + // Indicates whether the APK is uncompressed system APK, stub APK or + // compressed system APK. + SystemApkType system_apk_type = 2; +} + +// Holds data specific to APEX APKs. +message ApexApkMetadata { + // Configuration for processing of APKs embedded in an APEX image. + repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1; +} + +message LocalTestingInfo { + // Indicates if the bundle is built in local testing mode. + bool enabled = 1; + // The local testing path, as specified in the base manifest. + // This refers to the relative path on the external directory of the app where + // APKs will be pushed for local testing. + // Set only if local testing is enabled. + string local_testing_path = 2; +} diff --git a/cmd/extract_apks/bundle_proto/config.pb.go b/cmd/extract_apks/bundle_proto/config.pb.go new file mode 100644 index 000000000..a28147af3 --- /dev/null +++ b/cmd/extract_apks/bundle_proto/config.pb.go @@ -0,0 +1,952 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: config.proto + +package android_bundle_proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type BundleConfig_BundleType int32 + +const ( + BundleConfig_REGULAR BundleConfig_BundleType = 0 + BundleConfig_APEX BundleConfig_BundleType = 1 + BundleConfig_ASSET_ONLY BundleConfig_BundleType = 2 +) + +var BundleConfig_BundleType_name = map[int32]string{ + 0: "REGULAR", + 1: "APEX", + 2: "ASSET_ONLY", +} + +var BundleConfig_BundleType_value = map[string]int32{ + "REGULAR": 0, + "APEX": 1, + "ASSET_ONLY": 2, +} + +func (x BundleConfig_BundleType) String() string { + return proto.EnumName(BundleConfig_BundleType_name, int32(x)) +} + +func (BundleConfig_BundleType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{0, 0} +} + +type SplitDimension_Value int32 + +const ( + SplitDimension_UNSPECIFIED_VALUE SplitDimension_Value = 0 + SplitDimension_ABI SplitDimension_Value = 1 + SplitDimension_SCREEN_DENSITY SplitDimension_Value = 2 + SplitDimension_LANGUAGE SplitDimension_Value = 3 + SplitDimension_TEXTURE_COMPRESSION_FORMAT SplitDimension_Value = 4 + // BEGIN-INTERNAL + SplitDimension_GRAPHICS_API SplitDimension_Value = 5 +) + +var SplitDimension_Value_name = map[int32]string{ + 0: "UNSPECIFIED_VALUE", + 1: "ABI", + 2: "SCREEN_DENSITY", + 3: "LANGUAGE", + 4: "TEXTURE_COMPRESSION_FORMAT", + 5: "GRAPHICS_API", +} + +var SplitDimension_Value_value = map[string]int32{ + "UNSPECIFIED_VALUE": 0, + "ABI": 1, + "SCREEN_DENSITY": 2, + "LANGUAGE": 3, + "TEXTURE_COMPRESSION_FORMAT": 4, + "GRAPHICS_API": 5, +} + +func (x SplitDimension_Value) String() string { + return proto.EnumName(SplitDimension_Value_name, int32(x)) +} + +func (SplitDimension_Value) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{9, 0} +} + +type BundleConfig struct { + Bundletool *Bundletool `protobuf:"bytes,1,opt,name=bundletool,proto3" json:"bundletool,omitempty"` + Optimizations *Optimizations `protobuf:"bytes,2,opt,name=optimizations,proto3" json:"optimizations,omitempty"` + Compression *Compression `protobuf:"bytes,3,opt,name=compression,proto3" json:"compression,omitempty"` + // Resources to be always kept in the master split. + MasterResources *MasterResources `protobuf:"bytes,4,opt,name=master_resources,json=masterResources,proto3" json:"master_resources,omitempty"` + ApexConfig *ApexConfig `protobuf:"bytes,5,opt,name=apex_config,json=apexConfig,proto3" json:"apex_config,omitempty"` + // APKs to be signed with the same key as generated APKs. + UnsignedEmbeddedApkConfig []*UnsignedEmbeddedApkConfig `protobuf:"bytes,6,rep,name=unsigned_embedded_apk_config,json=unsignedEmbeddedApkConfig,proto3" json:"unsigned_embedded_apk_config,omitempty"` + AssetModulesConfig *AssetModulesConfig `protobuf:"bytes,7,opt,name=asset_modules_config,json=assetModulesConfig,proto3" json:"asset_modules_config,omitempty"` + Type BundleConfig_BundleType `protobuf:"varint,8,opt,name=type,proto3,enum=android.bundle.BundleConfig_BundleType" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BundleConfig) Reset() { *m = BundleConfig{} } +func (m *BundleConfig) String() string { return proto.CompactTextString(m) } +func (*BundleConfig) ProtoMessage() {} +func (*BundleConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{0} +} + +func (m *BundleConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BundleConfig.Unmarshal(m, b) +} +func (m *BundleConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BundleConfig.Marshal(b, m, deterministic) +} +func (m *BundleConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_BundleConfig.Merge(m, src) +} +func (m *BundleConfig) XXX_Size() int { + return xxx_messageInfo_BundleConfig.Size(m) +} +func (m *BundleConfig) XXX_DiscardUnknown() { + xxx_messageInfo_BundleConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_BundleConfig proto.InternalMessageInfo + +func (m *BundleConfig) GetBundletool() *Bundletool { + if m != nil { + return m.Bundletool + } + return nil +} + +func (m *BundleConfig) GetOptimizations() *Optimizations { + if m != nil { + return m.Optimizations + } + return nil +} + +func (m *BundleConfig) GetCompression() *Compression { + if m != nil { + return m.Compression + } + return nil +} + +func (m *BundleConfig) GetMasterResources() *MasterResources { + if m != nil { + return m.MasterResources + } + return nil +} + +func (m *BundleConfig) GetApexConfig() *ApexConfig { + if m != nil { + return m.ApexConfig + } + return nil +} + +func (m *BundleConfig) GetUnsignedEmbeddedApkConfig() []*UnsignedEmbeddedApkConfig { + if m != nil { + return m.UnsignedEmbeddedApkConfig + } + return nil +} + +func (m *BundleConfig) GetAssetModulesConfig() *AssetModulesConfig { + if m != nil { + return m.AssetModulesConfig + } + return nil +} + +func (m *BundleConfig) GetType() BundleConfig_BundleType { + if m != nil { + return m.Type + } + return BundleConfig_REGULAR +} + +type Bundletool struct { + // Version of BundleTool used to build the Bundle. + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Bundletool) Reset() { *m = Bundletool{} } +func (m *Bundletool) String() string { return proto.CompactTextString(m) } +func (*Bundletool) ProtoMessage() {} +func (*Bundletool) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{1} +} + +func (m *Bundletool) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Bundletool.Unmarshal(m, b) +} +func (m *Bundletool) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Bundletool.Marshal(b, m, deterministic) +} +func (m *Bundletool) XXX_Merge(src proto.Message) { + xxx_messageInfo_Bundletool.Merge(m, src) +} +func (m *Bundletool) XXX_Size() int { + return xxx_messageInfo_Bundletool.Size(m) +} +func (m *Bundletool) XXX_DiscardUnknown() { + xxx_messageInfo_Bundletool.DiscardUnknown(m) +} + +var xxx_messageInfo_Bundletool proto.InternalMessageInfo + +func (m *Bundletool) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +type Compression struct { + // Glob matching the list of files to leave uncompressed in the APKs. + // The matching is done against the path of files in the APK, thus excluding + // the name of the modules, and using forward slash ("/") as a name separator. + // Examples: "res/raw/**", "assets/**/*.uncompressed", etc. + UncompressedGlob []string `protobuf:"bytes,1,rep,name=uncompressed_glob,json=uncompressedGlob,proto3" json:"uncompressed_glob,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Compression) Reset() { *m = Compression{} } +func (m *Compression) String() string { return proto.CompactTextString(m) } +func (*Compression) ProtoMessage() {} +func (*Compression) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{2} +} + +func (m *Compression) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Compression.Unmarshal(m, b) +} +func (m *Compression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Compression.Marshal(b, m, deterministic) +} +func (m *Compression) XXX_Merge(src proto.Message) { + xxx_messageInfo_Compression.Merge(m, src) +} +func (m *Compression) XXX_Size() int { + return xxx_messageInfo_Compression.Size(m) +} +func (m *Compression) XXX_DiscardUnknown() { + xxx_messageInfo_Compression.DiscardUnknown(m) +} + +var xxx_messageInfo_Compression proto.InternalMessageInfo + +func (m *Compression) GetUncompressedGlob() []string { + if m != nil { + return m.UncompressedGlob + } + return nil +} + +// Resources to keep in the master split. +type MasterResources struct { + // Resource IDs to be kept in master split. + ResourceIds []int32 `protobuf:"varint,1,rep,packed,name=resource_ids,json=resourceIds,proto3" json:"resource_ids,omitempty"` + // Resource names to be kept in master split. + ResourceNames []string `protobuf:"bytes,2,rep,name=resource_names,json=resourceNames,proto3" json:"resource_names,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MasterResources) Reset() { *m = MasterResources{} } +func (m *MasterResources) String() string { return proto.CompactTextString(m) } +func (*MasterResources) ProtoMessage() {} +func (*MasterResources) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{3} +} + +func (m *MasterResources) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MasterResources.Unmarshal(m, b) +} +func (m *MasterResources) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MasterResources.Marshal(b, m, deterministic) +} +func (m *MasterResources) XXX_Merge(src proto.Message) { + xxx_messageInfo_MasterResources.Merge(m, src) +} +func (m *MasterResources) XXX_Size() int { + return xxx_messageInfo_MasterResources.Size(m) +} +func (m *MasterResources) XXX_DiscardUnknown() { + xxx_messageInfo_MasterResources.DiscardUnknown(m) +} + +var xxx_messageInfo_MasterResources proto.InternalMessageInfo + +func (m *MasterResources) GetResourceIds() []int32 { + if m != nil { + return m.ResourceIds + } + return nil +} + +func (m *MasterResources) GetResourceNames() []string { + if m != nil { + return m.ResourceNames + } + return nil +} + +type Optimizations struct { + SplitsConfig *SplitsConfig `protobuf:"bytes,1,opt,name=splits_config,json=splitsConfig,proto3" json:"splits_config,omitempty"` + // This is for uncompressing native libraries on M+ devices (L+ devices on + // instant apps). + UncompressNativeLibraries *UncompressNativeLibraries `protobuf:"bytes,2,opt,name=uncompress_native_libraries,json=uncompressNativeLibraries,proto3" json:"uncompress_native_libraries,omitempty"` + // This is for uncompressing dex files on P+ devices. + UncompressDexFiles *UncompressDexFiles `protobuf:"bytes,3,opt,name=uncompress_dex_files,json=uncompressDexFiles,proto3" json:"uncompress_dex_files,omitempty"` + // Configuration for the generation of standalone APKs. + // If no StandaloneConfig is set, the configuration is inherited from + // splits_config. + StandaloneConfig *StandaloneConfig `protobuf:"bytes,4,opt,name=standalone_config,json=standaloneConfig,proto3" json:"standalone_config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Optimizations) Reset() { *m = Optimizations{} } +func (m *Optimizations) String() string { return proto.CompactTextString(m) } +func (*Optimizations) ProtoMessage() {} +func (*Optimizations) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{4} +} + +func (m *Optimizations) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Optimizations.Unmarshal(m, b) +} +func (m *Optimizations) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Optimizations.Marshal(b, m, deterministic) +} +func (m *Optimizations) XXX_Merge(src proto.Message) { + xxx_messageInfo_Optimizations.Merge(m, src) +} +func (m *Optimizations) XXX_Size() int { + return xxx_messageInfo_Optimizations.Size(m) +} +func (m *Optimizations) XXX_DiscardUnknown() { + xxx_messageInfo_Optimizations.DiscardUnknown(m) +} + +var xxx_messageInfo_Optimizations proto.InternalMessageInfo + +func (m *Optimizations) GetSplitsConfig() *SplitsConfig { + if m != nil { + return m.SplitsConfig + } + return nil +} + +func (m *Optimizations) GetUncompressNativeLibraries() *UncompressNativeLibraries { + if m != nil { + return m.UncompressNativeLibraries + } + return nil +} + +func (m *Optimizations) GetUncompressDexFiles() *UncompressDexFiles { + if m != nil { + return m.UncompressDexFiles + } + return nil +} + +func (m *Optimizations) GetStandaloneConfig() *StandaloneConfig { + if m != nil { + return m.StandaloneConfig + } + return nil +} + +type UncompressNativeLibraries struct { + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UncompressNativeLibraries) Reset() { *m = UncompressNativeLibraries{} } +func (m *UncompressNativeLibraries) String() string { return proto.CompactTextString(m) } +func (*UncompressNativeLibraries) ProtoMessage() {} +func (*UncompressNativeLibraries) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{5} +} + +func (m *UncompressNativeLibraries) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UncompressNativeLibraries.Unmarshal(m, b) +} +func (m *UncompressNativeLibraries) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UncompressNativeLibraries.Marshal(b, m, deterministic) +} +func (m *UncompressNativeLibraries) XXX_Merge(src proto.Message) { + xxx_messageInfo_UncompressNativeLibraries.Merge(m, src) +} +func (m *UncompressNativeLibraries) XXX_Size() int { + return xxx_messageInfo_UncompressNativeLibraries.Size(m) +} +func (m *UncompressNativeLibraries) XXX_DiscardUnknown() { + xxx_messageInfo_UncompressNativeLibraries.DiscardUnknown(m) +} + +var xxx_messageInfo_UncompressNativeLibraries proto.InternalMessageInfo + +func (m *UncompressNativeLibraries) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +type UncompressDexFiles struct { + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UncompressDexFiles) Reset() { *m = UncompressDexFiles{} } +func (m *UncompressDexFiles) String() string { return proto.CompactTextString(m) } +func (*UncompressDexFiles) ProtoMessage() {} +func (*UncompressDexFiles) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{6} +} + +func (m *UncompressDexFiles) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UncompressDexFiles.Unmarshal(m, b) +} +func (m *UncompressDexFiles) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UncompressDexFiles.Marshal(b, m, deterministic) +} +func (m *UncompressDexFiles) XXX_Merge(src proto.Message) { + xxx_messageInfo_UncompressDexFiles.Merge(m, src) +} +func (m *UncompressDexFiles) XXX_Size() int { + return xxx_messageInfo_UncompressDexFiles.Size(m) +} +func (m *UncompressDexFiles) XXX_DiscardUnknown() { + xxx_messageInfo_UncompressDexFiles.DiscardUnknown(m) +} + +var xxx_messageInfo_UncompressDexFiles proto.InternalMessageInfo + +func (m *UncompressDexFiles) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +// Optimization configuration used to generate Split APKs. +type SplitsConfig struct { + SplitDimension []*SplitDimension `protobuf:"bytes,1,rep,name=split_dimension,json=splitDimension,proto3" json:"split_dimension,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SplitsConfig) Reset() { *m = SplitsConfig{} } +func (m *SplitsConfig) String() string { return proto.CompactTextString(m) } +func (*SplitsConfig) ProtoMessage() {} +func (*SplitsConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{7} +} + +func (m *SplitsConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SplitsConfig.Unmarshal(m, b) +} +func (m *SplitsConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SplitsConfig.Marshal(b, m, deterministic) +} +func (m *SplitsConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_SplitsConfig.Merge(m, src) +} +func (m *SplitsConfig) XXX_Size() int { + return xxx_messageInfo_SplitsConfig.Size(m) +} +func (m *SplitsConfig) XXX_DiscardUnknown() { + xxx_messageInfo_SplitsConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_SplitsConfig proto.InternalMessageInfo + +func (m *SplitsConfig) GetSplitDimension() []*SplitDimension { + if m != nil { + return m.SplitDimension + } + return nil +} + +// Optimization configuration used to generate Standalone APKs. +type StandaloneConfig struct { + // Device targeting dimensions to shard. + SplitDimension []*SplitDimension `protobuf:"bytes,1,rep,name=split_dimension,json=splitDimension,proto3" json:"split_dimension,omitempty"` + // Whether 64 bit libraries should be stripped from Standalone APKs. + Strip_64BitLibraries bool `protobuf:"varint,2,opt,name=strip_64_bit_libraries,json=strip64BitLibraries,proto3" json:"strip_64_bit_libraries,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StandaloneConfig) Reset() { *m = StandaloneConfig{} } +func (m *StandaloneConfig) String() string { return proto.CompactTextString(m) } +func (*StandaloneConfig) ProtoMessage() {} +func (*StandaloneConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{8} +} + +func (m *StandaloneConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StandaloneConfig.Unmarshal(m, b) +} +func (m *StandaloneConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StandaloneConfig.Marshal(b, m, deterministic) +} +func (m *StandaloneConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_StandaloneConfig.Merge(m, src) +} +func (m *StandaloneConfig) XXX_Size() int { + return xxx_messageInfo_StandaloneConfig.Size(m) +} +func (m *StandaloneConfig) XXX_DiscardUnknown() { + xxx_messageInfo_StandaloneConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_StandaloneConfig proto.InternalMessageInfo + +func (m *StandaloneConfig) GetSplitDimension() []*SplitDimension { + if m != nil { + return m.SplitDimension + } + return nil +} + +func (m *StandaloneConfig) GetStrip_64BitLibraries() bool { + if m != nil { + return m.Strip_64BitLibraries + } + return false +} + +type SplitDimension struct { + Value SplitDimension_Value `protobuf:"varint,1,opt,name=value,proto3,enum=android.bundle.SplitDimension_Value" json:"value,omitempty"` + // If set to 'true', indicates that APKs should *not* be split by this + // dimension. + Negate bool `protobuf:"varint,2,opt,name=negate,proto3" json:"negate,omitempty"` + // Optional transformation to be applied to asset directories where + // the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1) + SuffixStripping *SuffixStripping `protobuf:"bytes,3,opt,name=suffix_stripping,json=suffixStripping,proto3" json:"suffix_stripping,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SplitDimension) Reset() { *m = SplitDimension{} } +func (m *SplitDimension) String() string { return proto.CompactTextString(m) } +func (*SplitDimension) ProtoMessage() {} +func (*SplitDimension) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{9} +} + +func (m *SplitDimension) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SplitDimension.Unmarshal(m, b) +} +func (m *SplitDimension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SplitDimension.Marshal(b, m, deterministic) +} +func (m *SplitDimension) XXX_Merge(src proto.Message) { + xxx_messageInfo_SplitDimension.Merge(m, src) +} +func (m *SplitDimension) XXX_Size() int { + return xxx_messageInfo_SplitDimension.Size(m) +} +func (m *SplitDimension) XXX_DiscardUnknown() { + xxx_messageInfo_SplitDimension.DiscardUnknown(m) +} + +var xxx_messageInfo_SplitDimension proto.InternalMessageInfo + +func (m *SplitDimension) GetValue() SplitDimension_Value { + if m != nil { + return m.Value + } + return SplitDimension_UNSPECIFIED_VALUE +} + +func (m *SplitDimension) GetNegate() bool { + if m != nil { + return m.Negate + } + return false +} + +func (m *SplitDimension) GetSuffixStripping() *SuffixStripping { + if m != nil { + return m.SuffixStripping + } + return nil +} + +type SuffixStripping struct { + // If set to 'true', indicates that the targeting suffix should be removed + // from assets paths for this dimension when splits (or asset slices) are + // generated. + // This only applies to assets. + // For example a folder with path "assets/level1_textures#tcf_etc1" + // would be outputted to "assets/level1_textures". File contents are + // unchanged. + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + // The default suffix to be used for the cases where separate slices can't + // be generated for this dimension. In the case of standalone/universal APKs + // generation, stripping the suffix can lead to file name collisions. This + // default suffix defines the directories to retain. The others are + // discarded: standalone/universal APKs will contain only directories + // targeted at this value for the dimension. + // + // If not set or empty, the fallback directory in each directory group will be + // used (for example, if both "assets/level1_textures#tcf_etc1" and + // "assets/level1_textures" are present and the default suffix is empty, + // then only "assets/level1_textures" will be used). + DefaultSuffix string `protobuf:"bytes,2,opt,name=default_suffix,json=defaultSuffix,proto3" json:"default_suffix,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SuffixStripping) Reset() { *m = SuffixStripping{} } +func (m *SuffixStripping) String() string { return proto.CompactTextString(m) } +func (*SuffixStripping) ProtoMessage() {} +func (*SuffixStripping) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{10} +} + +func (m *SuffixStripping) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SuffixStripping.Unmarshal(m, b) +} +func (m *SuffixStripping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SuffixStripping.Marshal(b, m, deterministic) +} +func (m *SuffixStripping) XXX_Merge(src proto.Message) { + xxx_messageInfo_SuffixStripping.Merge(m, src) +} +func (m *SuffixStripping) XXX_Size() int { + return xxx_messageInfo_SuffixStripping.Size(m) +} +func (m *SuffixStripping) XXX_DiscardUnknown() { + xxx_messageInfo_SuffixStripping.DiscardUnknown(m) +} + +var xxx_messageInfo_SuffixStripping proto.InternalMessageInfo + +func (m *SuffixStripping) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +func (m *SuffixStripping) GetDefaultSuffix() string { + if m != nil { + return m.DefaultSuffix + } + return "" +} + +// Configuration for processing APEX bundles. +// https://source.android.com/devices/tech/ota/apex +type ApexConfig struct { + // Configuration for processing of APKs embedded in an APEX image. + ApexEmbeddedApkConfig []*ApexEmbeddedApkConfig `protobuf:"bytes,1,rep,name=apex_embedded_apk_config,json=apexEmbeddedApkConfig,proto3" json:"apex_embedded_apk_config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApexConfig) Reset() { *m = ApexConfig{} } +func (m *ApexConfig) String() string { return proto.CompactTextString(m) } +func (*ApexConfig) ProtoMessage() {} +func (*ApexConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{11} +} + +func (m *ApexConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApexConfig.Unmarshal(m, b) +} +func (m *ApexConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApexConfig.Marshal(b, m, deterministic) +} +func (m *ApexConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApexConfig.Merge(m, src) +} +func (m *ApexConfig) XXX_Size() int { + return xxx_messageInfo_ApexConfig.Size(m) +} +func (m *ApexConfig) XXX_DiscardUnknown() { + xxx_messageInfo_ApexConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_ApexConfig proto.InternalMessageInfo + +func (m *ApexConfig) GetApexEmbeddedApkConfig() []*ApexEmbeddedApkConfig { + if m != nil { + return m.ApexEmbeddedApkConfig + } + return nil +} + +type ApexEmbeddedApkConfig struct { + // Android package name of the APK. + PackageName string `protobuf:"bytes,1,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` + // Path to the APK within the APEX system image. + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApexEmbeddedApkConfig) Reset() { *m = ApexEmbeddedApkConfig{} } +func (m *ApexEmbeddedApkConfig) String() string { return proto.CompactTextString(m) } +func (*ApexEmbeddedApkConfig) ProtoMessage() {} +func (*ApexEmbeddedApkConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{12} +} + +func (m *ApexEmbeddedApkConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApexEmbeddedApkConfig.Unmarshal(m, b) +} +func (m *ApexEmbeddedApkConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApexEmbeddedApkConfig.Marshal(b, m, deterministic) +} +func (m *ApexEmbeddedApkConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApexEmbeddedApkConfig.Merge(m, src) +} +func (m *ApexEmbeddedApkConfig) XXX_Size() int { + return xxx_messageInfo_ApexEmbeddedApkConfig.Size(m) +} +func (m *ApexEmbeddedApkConfig) XXX_DiscardUnknown() { + xxx_messageInfo_ApexEmbeddedApkConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_ApexEmbeddedApkConfig proto.InternalMessageInfo + +func (m *ApexEmbeddedApkConfig) GetPackageName() string { + if m != nil { + return m.PackageName + } + return "" +} + +func (m *ApexEmbeddedApkConfig) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +type UnsignedEmbeddedApkConfig struct { + // Path to the APK inside the module (e.g. if the path inside the bundle + // is split/assets/example.apk, this will be assets/example.apk). + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UnsignedEmbeddedApkConfig) Reset() { *m = UnsignedEmbeddedApkConfig{} } +func (m *UnsignedEmbeddedApkConfig) String() string { return proto.CompactTextString(m) } +func (*UnsignedEmbeddedApkConfig) ProtoMessage() {} +func (*UnsignedEmbeddedApkConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{13} +} + +func (m *UnsignedEmbeddedApkConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UnsignedEmbeddedApkConfig.Unmarshal(m, b) +} +func (m *UnsignedEmbeddedApkConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UnsignedEmbeddedApkConfig.Marshal(b, m, deterministic) +} +func (m *UnsignedEmbeddedApkConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_UnsignedEmbeddedApkConfig.Merge(m, src) +} +func (m *UnsignedEmbeddedApkConfig) XXX_Size() int { + return xxx_messageInfo_UnsignedEmbeddedApkConfig.Size(m) +} +func (m *UnsignedEmbeddedApkConfig) XXX_DiscardUnknown() { + xxx_messageInfo_UnsignedEmbeddedApkConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_UnsignedEmbeddedApkConfig proto.InternalMessageInfo + +func (m *UnsignedEmbeddedApkConfig) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +type AssetModulesConfig struct { + // App versionCodes that will be updated with these asset modules. + // Only relevant for asset-only bundles. + AppVersion []int64 `protobuf:"varint,1,rep,packed,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + // Version tag for the asset upload. + // Only relevant for asset-only bundles. + AssetVersionTag string `protobuf:"bytes,2,opt,name=asset_version_tag,json=assetVersionTag,proto3" json:"asset_version_tag,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssetModulesConfig) Reset() { *m = AssetModulesConfig{} } +func (m *AssetModulesConfig) String() string { return proto.CompactTextString(m) } +func (*AssetModulesConfig) ProtoMessage() {} +func (*AssetModulesConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_3eaf2c85e69e9ea4, []int{14} +} + +func (m *AssetModulesConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AssetModulesConfig.Unmarshal(m, b) +} +func (m *AssetModulesConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AssetModulesConfig.Marshal(b, m, deterministic) +} +func (m *AssetModulesConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetModulesConfig.Merge(m, src) +} +func (m *AssetModulesConfig) XXX_Size() int { + return xxx_messageInfo_AssetModulesConfig.Size(m) +} +func (m *AssetModulesConfig) XXX_DiscardUnknown() { + xxx_messageInfo_AssetModulesConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetModulesConfig proto.InternalMessageInfo + +func (m *AssetModulesConfig) GetAppVersion() []int64 { + if m != nil { + return m.AppVersion + } + return nil +} + +func (m *AssetModulesConfig) GetAssetVersionTag() string { + if m != nil { + return m.AssetVersionTag + } + return "" +} + +func init() { + proto.RegisterEnum("android.bundle.BundleConfig_BundleType", BundleConfig_BundleType_name, BundleConfig_BundleType_value) + proto.RegisterEnum("android.bundle.SplitDimension_Value", SplitDimension_Value_name, SplitDimension_Value_value) + proto.RegisterType((*BundleConfig)(nil), "android.bundle.BundleConfig") + proto.RegisterType((*Bundletool)(nil), "android.bundle.Bundletool") + proto.RegisterType((*Compression)(nil), "android.bundle.Compression") + proto.RegisterType((*MasterResources)(nil), "android.bundle.MasterResources") + proto.RegisterType((*Optimizations)(nil), "android.bundle.Optimizations") + proto.RegisterType((*UncompressNativeLibraries)(nil), "android.bundle.UncompressNativeLibraries") + proto.RegisterType((*UncompressDexFiles)(nil), "android.bundle.UncompressDexFiles") + proto.RegisterType((*SplitsConfig)(nil), "android.bundle.SplitsConfig") + proto.RegisterType((*StandaloneConfig)(nil), "android.bundle.StandaloneConfig") + proto.RegisterType((*SplitDimension)(nil), "android.bundle.SplitDimension") + proto.RegisterType((*SuffixStripping)(nil), "android.bundle.SuffixStripping") + proto.RegisterType((*ApexConfig)(nil), "android.bundle.ApexConfig") + proto.RegisterType((*ApexEmbeddedApkConfig)(nil), "android.bundle.ApexEmbeddedApkConfig") + proto.RegisterType((*UnsignedEmbeddedApkConfig)(nil), "android.bundle.UnsignedEmbeddedApkConfig") + proto.RegisterType((*AssetModulesConfig)(nil), "android.bundle.AssetModulesConfig") +} + +func init() { + proto.RegisterFile("config.proto", fileDescriptor_3eaf2c85e69e9ea4) +} + +var fileDescriptor_3eaf2c85e69e9ea4 = []byte{ + // 1001 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdb, 0x6e, 0xdb, 0x46, + 0x10, 0x0d, 0x75, 0xb1, 0xe5, 0x91, 0x2c, 0xd1, 0xdb, 0x38, 0x50, 0x2e, 0x4d, 0x5c, 0xa2, 0x41, + 0xdd, 0xb4, 0x50, 0x01, 0x3b, 0xcd, 0x83, 0x83, 0x3e, 0xd0, 0x32, 0xad, 0x2a, 0xd0, 0x0d, 0x4b, + 0xc9, 0x4d, 0x5a, 0xa0, 0x8b, 0x95, 0xb8, 0x52, 0xb7, 0xa6, 0x48, 0x82, 0x4b, 0x1a, 0x4a, 0xfb, + 0x09, 0x7d, 0xe9, 0x8f, 0xf4, 0xa7, 0xfa, 0x25, 0x05, 0x97, 0xa4, 0x2c, 0x51, 0x52, 0x9e, 0xfa, + 0x24, 0xce, 0xec, 0x39, 0xb3, 0x3b, 0xb3, 0x67, 0x67, 0x04, 0x95, 0x89, 0xeb, 0x4c, 0xf9, 0xac, + 0xe1, 0xf9, 0x6e, 0xe0, 0xa2, 0x2a, 0x75, 0x2c, 0xdf, 0xe5, 0x56, 0x63, 0x1c, 0x3a, 0x96, 0xcd, + 0xb4, 0xbf, 0x8a, 0x50, 0xb9, 0x94, 0x9f, 0x4d, 0x09, 0x43, 0x17, 0x00, 0xf1, 0x52, 0xe0, 0xba, + 0x76, 0x5d, 0x39, 0x51, 0x4e, 0xcb, 0x67, 0x4f, 0x1a, 0xeb, 0xac, 0xc6, 0xe5, 0x12, 0x81, 0x57, + 0xd0, 0xa8, 0x09, 0x87, 0xae, 0x17, 0xf0, 0x39, 0xff, 0x83, 0x06, 0xdc, 0x75, 0x44, 0x3d, 0x27, + 0xe9, 0x9f, 0x67, 0xe9, 0xfd, 0x55, 0x10, 0x5e, 0xe7, 0xa0, 0x1f, 0xa0, 0x3c, 0x71, 0xe7, 0x9e, + 0xcf, 0x84, 0xe0, 0xae, 0x53, 0xcf, 0xcb, 0x10, 0x4f, 0xb3, 0x21, 0x9a, 0xf7, 0x10, 0xbc, 0x8a, + 0x47, 0xef, 0x40, 0x9d, 0x53, 0x11, 0x30, 0x9f, 0xf8, 0x4c, 0xb8, 0xa1, 0x3f, 0x61, 0xa2, 0x5e, + 0x90, 0x31, 0x5e, 0x64, 0x63, 0x74, 0x25, 0x0e, 0xa7, 0x30, 0x5c, 0x9b, 0xaf, 0x3b, 0xd0, 0x5b, + 0x28, 0x53, 0x8f, 0x2d, 0x48, 0x5c, 0xc1, 0x7a, 0x71, 0x7b, 0x31, 0x74, 0x8f, 0x2d, 0xe2, 0xe2, + 0x61, 0xa0, 0xcb, 0x6f, 0xf4, 0x3b, 0x3c, 0x0b, 0x1d, 0xc1, 0x67, 0x0e, 0xb3, 0x08, 0x9b, 0x8f, + 0x99, 0x65, 0x31, 0x8b, 0x50, 0xef, 0x36, 0x8d, 0xb6, 0x77, 0x92, 0x3f, 0x2d, 0x9f, 0x7d, 0x9d, + 0x8d, 0x36, 0x4a, 0x38, 0x46, 0x42, 0xd1, 0xbd, 0xdb, 0x24, 0xf8, 0xe3, 0x70, 0xd7, 0x12, 0x1a, + 0xc2, 0x43, 0x2a, 0x04, 0x0b, 0xc8, 0xdc, 0xb5, 0x42, 0x9b, 0x89, 0x74, 0x8f, 0x7d, 0x79, 0x62, + 0x6d, 0xe3, 0xc4, 0x11, 0xb6, 0x1b, 0x43, 0x93, 0xe0, 0x88, 0x6e, 0xf8, 0xd0, 0x5b, 0x28, 0x04, + 0x1f, 0x3d, 0x56, 0x2f, 0x9d, 0x28, 0xa7, 0xd5, 0xb3, 0xaf, 0xb6, 0x8b, 0x20, 0xc6, 0x26, 0xc6, + 0xf0, 0xa3, 0xc7, 0xb0, 0x24, 0x69, 0xe7, 0x00, 0xf7, 0x3e, 0x54, 0x86, 0x7d, 0x6c, 0xb4, 0x46, + 0x1d, 0x1d, 0xab, 0x0f, 0x50, 0x09, 0x0a, 0xfa, 0xc0, 0x78, 0xaf, 0x2a, 0xa8, 0x0a, 0xa0, 0x9b, + 0xa6, 0x31, 0x24, 0xfd, 0x5e, 0xe7, 0x83, 0x9a, 0xd3, 0xbe, 0x4d, 0x49, 0x52, 0x4e, 0x75, 0xd8, + 0xbf, 0x63, 0xbe, 0x54, 0x41, 0x24, 0xa4, 0x03, 0x9c, 0x9a, 0xef, 0x0a, 0x25, 0x45, 0xcd, 0x69, + 0x17, 0x50, 0x5e, 0x91, 0x01, 0xfa, 0x06, 0x8e, 0x42, 0x27, 0x95, 0x02, 0xb3, 0xc8, 0xcc, 0x76, + 0xc7, 0x75, 0xe5, 0x24, 0x7f, 0x7a, 0x80, 0xd5, 0xd5, 0x85, 0x96, 0xed, 0x8e, 0xb5, 0x5f, 0xa0, + 0x96, 0xb9, 0x7e, 0xf4, 0x05, 0x54, 0x52, 0xc9, 0x10, 0x6e, 0x09, 0x49, 0x2d, 0xe2, 0x72, 0xea, + 0x6b, 0x5b, 0x02, 0xbd, 0x84, 0xea, 0x12, 0xe2, 0xd0, 0x39, 0x8b, 0x14, 0x1e, 0xc5, 0x3f, 0x4c, + 0xbd, 0xbd, 0xc8, 0xa9, 0xfd, 0x9b, 0x83, 0xc3, 0x35, 0x8d, 0x23, 0x1d, 0x0e, 0x85, 0x67, 0xf3, + 0x60, 0x79, 0x33, 0xf1, 0xc3, 0x7a, 0x96, 0xad, 0xa9, 0x29, 0x41, 0xc9, 0x9d, 0x54, 0xc4, 0x8a, + 0x85, 0x38, 0x3c, 0xbd, 0xcf, 0x82, 0x38, 0x34, 0xe0, 0x77, 0x8c, 0xd8, 0x7c, 0xec, 0x53, 0x9f, + 0xb3, 0xf4, 0xa9, 0x6d, 0x91, 0x53, 0x4a, 0xe9, 0x49, 0x46, 0x27, 0x25, 0x44, 0x72, 0xda, 0xb1, + 0x14, 0xc9, 0x69, 0x65, 0x2b, 0x8b, 0x2d, 0xc8, 0x94, 0xdb, 0x4c, 0x24, 0x6f, 0x51, 0xdb, 0xbd, + 0xc7, 0x15, 0x5b, 0x5c, 0x47, 0x48, 0x8c, 0xc2, 0x0d, 0x1f, 0xea, 0xc2, 0x91, 0x08, 0xa8, 0x63, + 0x51, 0xdb, 0x75, 0x58, 0x5a, 0x87, 0xf8, 0x69, 0x9e, 0x6c, 0xd4, 0x61, 0x09, 0x4c, 0x6a, 0xa1, + 0x8a, 0x8c, 0x47, 0xfb, 0x1e, 0x1e, 0xef, 0x4c, 0x2e, 0x92, 0x0e, 0x73, 0xe8, 0xd8, 0x66, 0x96, + 0xac, 0x74, 0x09, 0xa7, 0xa6, 0xd6, 0x00, 0xb4, 0x79, 0xde, 0x4f, 0xe0, 0x7f, 0x82, 0xca, 0xea, + 0xa5, 0xa0, 0x16, 0xd4, 0xe4, 0xb5, 0x10, 0x8b, 0xcf, 0x99, 0x23, 0xc5, 0xa9, 0xc8, 0x97, 0xfc, + 0x7c, 0xeb, 0x5d, 0x5e, 0xa5, 0x28, 0x5c, 0x15, 0x6b, 0xb6, 0xf6, 0xb7, 0x02, 0x6a, 0x36, 0xcd, + 0xff, 0x2d, 0x3a, 0x3a, 0x87, 0x47, 0x22, 0xf0, 0xb9, 0x47, 0xde, 0xbc, 0x26, 0x63, 0x1e, 0x64, + 0x84, 0x52, 0xc2, 0x9f, 0xc9, 0xd5, 0x37, 0xaf, 0x2f, 0x79, 0xb0, 0xac, 0x9a, 0xf6, 0x4f, 0x0e, + 0xaa, 0xeb, 0x71, 0xd1, 0x05, 0x14, 0xef, 0xa8, 0x1d, 0x32, 0x59, 0x96, 0xea, 0xd9, 0x97, 0x9f, + 0x3e, 0x46, 0xe3, 0x26, 0xc2, 0xe2, 0x98, 0x82, 0x1e, 0xc1, 0x9e, 0xc3, 0x66, 0x34, 0x60, 0xc9, + 0x9e, 0x89, 0x15, 0xb5, 0x68, 0x11, 0x4e, 0xa7, 0x7c, 0x41, 0xe4, 0x21, 0x3c, 0xee, 0xcc, 0x12, + 0x69, 0x6d, 0xb4, 0x68, 0x53, 0xe2, 0xcc, 0x14, 0x86, 0x6b, 0x62, 0xdd, 0xa1, 0xfd, 0x09, 0x45, + 0xb9, 0x27, 0x3a, 0x86, 0xa3, 0x51, 0xcf, 0x1c, 0x18, 0xcd, 0xf6, 0x75, 0xdb, 0xb8, 0x22, 0x37, + 0x7a, 0x67, 0x64, 0xa8, 0x0f, 0xd0, 0x3e, 0xe4, 0xf5, 0xcb, 0xb6, 0xaa, 0x20, 0x04, 0x55, 0xb3, + 0x89, 0x0d, 0xa3, 0x47, 0xae, 0x8c, 0x9e, 0xd9, 0x1e, 0x7e, 0x50, 0x73, 0xa8, 0x02, 0xa5, 0x8e, + 0xde, 0x6b, 0x8d, 0xf4, 0x96, 0xa1, 0xe6, 0xd1, 0x73, 0x78, 0x32, 0x34, 0xde, 0x0f, 0x47, 0xd8, + 0x20, 0xcd, 0x7e, 0x77, 0x80, 0x0d, 0xd3, 0x6c, 0xf7, 0x7b, 0xe4, 0xba, 0x8f, 0xbb, 0xfa, 0x50, + 0x2d, 0x20, 0x15, 0x2a, 0x2d, 0xac, 0x0f, 0x7e, 0x6c, 0x37, 0x4d, 0xa2, 0x0f, 0xda, 0x6a, 0x51, + 0xc3, 0x50, 0xcb, 0x1c, 0x70, 0xb7, 0x90, 0xa2, 0xde, 0x61, 0xb1, 0x29, 0x0d, 0xed, 0x80, 0xc4, + 0x49, 0x24, 0x4d, 0xed, 0x30, 0xf1, 0xc6, 0x91, 0x34, 0x1b, 0xe0, 0x7e, 0xa0, 0xa0, 0x5f, 0xa1, + 0x2e, 0x27, 0xd0, 0xb6, 0x01, 0x12, 0x0b, 0xe3, 0xe5, 0xb6, 0x71, 0xb4, 0x39, 0x3c, 0x8e, 0xe9, + 0x36, 0xb7, 0xd6, 0x83, 0xe3, 0xad, 0xf8, 0xa8, 0x19, 0x7a, 0x74, 0x72, 0x4b, 0x67, 0x71, 0xa3, + 0x93, 0xc9, 0x1c, 0xe0, 0x72, 0xe2, 0x8b, 0xda, 0x1c, 0x42, 0x50, 0xf0, 0x68, 0xf0, 0x5b, 0x92, + 0x86, 0xfc, 0xd6, 0xbe, 0x8b, 0x1e, 0xe5, 0xae, 0x29, 0x95, 0x12, 0x94, 0x15, 0x02, 0x05, 0xb4, + 0x39, 0x8d, 0xd0, 0x8b, 0x68, 0xf0, 0x7a, 0x24, 0xed, 0xfe, 0x51, 0xa6, 0xf9, 0x68, 0xb8, 0x7a, + 0x37, 0xb1, 0x07, 0xbd, 0x82, 0xa3, 0x78, 0xe0, 0x25, 0x10, 0x12, 0xd0, 0x59, 0x72, 0x90, 0x9a, + 0x5c, 0x48, 0x80, 0x43, 0x3a, 0xbb, 0x7c, 0x05, 0x68, 0xe2, 0xce, 0x33, 0x65, 0xfa, 0xf9, 0x61, + 0x62, 0x93, 0xd8, 0x26, 0xf2, 0xef, 0xd1, 0x78, 0x4f, 0xfe, 0x9c, 0xff, 0x17, 0x00, 0x00, 0xff, + 0xff, 0x6b, 0x05, 0xbf, 0x99, 0x35, 0x09, 0x00, 0x00, +} diff --git a/cmd/extract_apks/bundle_proto/config.proto b/cmd/extract_apks/bundle_proto/config.proto new file mode 100644 index 000000000..1c161aa6c --- /dev/null +++ b/cmd/extract_apks/bundle_proto/config.proto @@ -0,0 +1,162 @@ +// Messages describing APK Set's table of contents (toc.pb entry). +// Please be advised that the ultimate source is at +// https://github.com/google/bundletool/tree/master/src/main/proto +// so you have been warned. +syntax = "proto3"; + +package android.bundle; + +option go_package = "android_bundle_proto"; +option java_package = "com.android.bundle"; + +message BundleConfig { + Bundletool bundletool = 1; + Optimizations optimizations = 2; + Compression compression = 3; + // Resources to be always kept in the master split. + MasterResources master_resources = 4; + ApexConfig apex_config = 5; + // APKs to be signed with the same key as generated APKs. + repeated UnsignedEmbeddedApkConfig unsigned_embedded_apk_config = 6; + AssetModulesConfig asset_modules_config = 7; + + enum BundleType { + REGULAR = 0; + APEX = 1; + ASSET_ONLY = 2; + } + BundleType type = 8; +} + +message Bundletool { + reserved 1; + // Version of BundleTool used to build the Bundle. + string version = 2; +} + +message Compression { + // Glob matching the list of files to leave uncompressed in the APKs. + // The matching is done against the path of files in the APK, thus excluding + // the name of the modules, and using forward slash ("/") as a name separator. + // Examples: "res/raw/**", "assets/**/*.uncompressed", etc. + repeated string uncompressed_glob = 1; +} + +// Resources to keep in the master split. +message MasterResources { + // Resource IDs to be kept in master split. + repeated int32 resource_ids = 1; + // Resource names to be kept in master split. + repeated string resource_names = 2; +} + +message Optimizations { + SplitsConfig splits_config = 1; + // This is for uncompressing native libraries on M+ devices (L+ devices on + // instant apps). + UncompressNativeLibraries uncompress_native_libraries = 2; + // This is for uncompressing dex files on P+ devices. + UncompressDexFiles uncompress_dex_files = 3; + // Configuration for the generation of standalone APKs. + // If no StandaloneConfig is set, the configuration is inherited from + // splits_config. + StandaloneConfig standalone_config = 4; +} + +message UncompressNativeLibraries { + bool enabled = 1; +} + +message UncompressDexFiles { + bool enabled = 1; +} + +// Optimization configuration used to generate Split APKs. +message SplitsConfig { + repeated SplitDimension split_dimension = 1; +} + +// Optimization configuration used to generate Standalone APKs. +message StandaloneConfig { + // Device targeting dimensions to shard. + repeated SplitDimension split_dimension = 1; + // Whether 64 bit libraries should be stripped from Standalone APKs. + bool strip_64_bit_libraries = 2; +} + +message SplitDimension { + enum Value { + UNSPECIFIED_VALUE = 0; + ABI = 1; + SCREEN_DENSITY = 2; + LANGUAGE = 3; + TEXTURE_COMPRESSION_FORMAT = 4; + // BEGIN-INTERNAL + GRAPHICS_API = 5; + // END-INTERNAL + } + Value value = 1; + + // If set to 'true', indicates that APKs should *not* be split by this + // dimension. + bool negate = 2; + + // Optional transformation to be applied to asset directories where + // the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1) + SuffixStripping suffix_stripping = 3; +} + +message SuffixStripping { + // If set to 'true', indicates that the targeting suffix should be removed + // from assets paths for this dimension when splits (or asset slices) are + // generated. + // This only applies to assets. + // For example a folder with path "assets/level1_textures#tcf_etc1" + // would be outputted to "assets/level1_textures". File contents are + // unchanged. + bool enabled = 1; + + // The default suffix to be used for the cases where separate slices can't + // be generated for this dimension. In the case of standalone/universal APKs + // generation, stripping the suffix can lead to file name collisions. This + // default suffix defines the directories to retain. The others are + // discarded: standalone/universal APKs will contain only directories + // targeted at this value for the dimension. + // + // If not set or empty, the fallback directory in each directory group will be + // used (for example, if both "assets/level1_textures#tcf_etc1" and + // "assets/level1_textures" are present and the default suffix is empty, + // then only "assets/level1_textures" will be used). + string default_suffix = 2; +} + +// Configuration for processing APEX bundles. +// https://source.android.com/devices/tech/ota/apex +message ApexConfig { + // Configuration for processing of APKs embedded in an APEX image. + repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1; +} + +message ApexEmbeddedApkConfig { + // Android package name of the APK. + string package_name = 1; + + // Path to the APK within the APEX system image. + string path = 2; +} + +message UnsignedEmbeddedApkConfig { + // Path to the APK inside the module (e.g. if the path inside the bundle + // is split/assets/example.apk, this will be assets/example.apk). + string path = 1; +} + +message AssetModulesConfig { + // App versionCodes that will be updated with these asset modules. + // Only relevant for asset-only bundles. + repeated int64 app_version = 1; + + // Version tag for the asset upload. + // Only relevant for asset-only bundles. + string asset_version_tag = 2; +} diff --git a/cmd/extract_apks/bundle_proto/regen.sh b/cmd/extract_apks/bundle_proto/regen.sh new file mode 100755 index 000000000..89fb6554d --- /dev/null +++ b/cmd/extract_apks/bundle_proto/regen.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Generates the golang source file of protos file describing APK set table of +# contents (toc.pb file). + +set -e +function die() { echo "ERROR: $1" >&2; exit 1; } + +readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?" + +hash aprotoc &>/dev/null || die "could not find aprotoc. ${error_msg}" +# TODO(asmundak): maybe have the paths relative to repo top? +(cd "${0%/*}" && aprotoc --go_out=paths=source_relative:. commands.proto config.proto targeting.proto ) || die "build failed. ${error_msg}" diff --git a/cmd/extract_apks/bundle_proto/targeting.pb.go b/cmd/extract_apks/bundle_proto/targeting.pb.go new file mode 100644 index 000000000..187bc443b --- /dev/null +++ b/cmd/extract_apks/bundle_proto/targeting.pb.go @@ -0,0 +1,1734 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: targeting.proto + +package android_bundle_proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type ScreenDensity_DensityAlias int32 + +const ( + ScreenDensity_DENSITY_UNSPECIFIED ScreenDensity_DensityAlias = 0 + ScreenDensity_NODPI ScreenDensity_DensityAlias = 1 + ScreenDensity_LDPI ScreenDensity_DensityAlias = 2 + ScreenDensity_MDPI ScreenDensity_DensityAlias = 3 + ScreenDensity_TVDPI ScreenDensity_DensityAlias = 4 + ScreenDensity_HDPI ScreenDensity_DensityAlias = 5 + ScreenDensity_XHDPI ScreenDensity_DensityAlias = 6 + ScreenDensity_XXHDPI ScreenDensity_DensityAlias = 7 + ScreenDensity_XXXHDPI ScreenDensity_DensityAlias = 8 +) + +var ScreenDensity_DensityAlias_name = map[int32]string{ + 0: "DENSITY_UNSPECIFIED", + 1: "NODPI", + 2: "LDPI", + 3: "MDPI", + 4: "TVDPI", + 5: "HDPI", + 6: "XHDPI", + 7: "XXHDPI", + 8: "XXXHDPI", +} + +var ScreenDensity_DensityAlias_value = map[string]int32{ + "DENSITY_UNSPECIFIED": 0, + "NODPI": 1, + "LDPI": 2, + "MDPI": 3, + "TVDPI": 4, + "HDPI": 5, + "XHDPI": 6, + "XXHDPI": 7, + "XXXHDPI": 8, +} + +func (x ScreenDensity_DensityAlias) String() string { + return proto.EnumName(ScreenDensity_DensityAlias_name, int32(x)) +} + +func (ScreenDensity_DensityAlias) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{4, 0} +} + +type TextureCompressionFormat_TextureCompressionFormatAlias int32 + +const ( + TextureCompressionFormat_UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT TextureCompressionFormat_TextureCompressionFormatAlias = 0 + TextureCompressionFormat_ETC1_RGB8 TextureCompressionFormat_TextureCompressionFormatAlias = 1 + TextureCompressionFormat_PALETTED TextureCompressionFormat_TextureCompressionFormatAlias = 2 + TextureCompressionFormat_THREE_DC TextureCompressionFormat_TextureCompressionFormatAlias = 3 + TextureCompressionFormat_ATC TextureCompressionFormat_TextureCompressionFormatAlias = 4 + TextureCompressionFormat_LATC TextureCompressionFormat_TextureCompressionFormatAlias = 5 + TextureCompressionFormat_DXT1 TextureCompressionFormat_TextureCompressionFormatAlias = 6 + TextureCompressionFormat_S3TC TextureCompressionFormat_TextureCompressionFormatAlias = 7 + TextureCompressionFormat_PVRTC TextureCompressionFormat_TextureCompressionFormatAlias = 8 + TextureCompressionFormat_ASTC TextureCompressionFormat_TextureCompressionFormatAlias = 9 + TextureCompressionFormat_ETC2 TextureCompressionFormat_TextureCompressionFormatAlias = 10 +) + +var TextureCompressionFormat_TextureCompressionFormatAlias_name = map[int32]string{ + 0: "UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT", + 1: "ETC1_RGB8", + 2: "PALETTED", + 3: "THREE_DC", + 4: "ATC", + 5: "LATC", + 6: "DXT1", + 7: "S3TC", + 8: "PVRTC", + 9: "ASTC", + 10: "ETC2", +} + +var TextureCompressionFormat_TextureCompressionFormatAlias_value = map[string]int32{ + "UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT": 0, + "ETC1_RGB8": 1, + "PALETTED": 2, + "THREE_DC": 3, + "ATC": 4, + "LATC": 5, + "DXT1": 6, + "S3TC": 7, + "PVRTC": 8, + "ASTC": 9, + "ETC2": 10, +} + +func (x TextureCompressionFormat_TextureCompressionFormatAlias) String() string { + return proto.EnumName(TextureCompressionFormat_TextureCompressionFormatAlias_name, int32(x)) +} + +func (TextureCompressionFormat_TextureCompressionFormatAlias) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{10, 0} +} + +type Abi_AbiAlias int32 + +const ( + Abi_UNSPECIFIED_CPU_ARCHITECTURE Abi_AbiAlias = 0 + Abi_ARMEABI Abi_AbiAlias = 1 + Abi_ARMEABI_V7A Abi_AbiAlias = 2 + Abi_ARM64_V8A Abi_AbiAlias = 3 + Abi_X86 Abi_AbiAlias = 4 + Abi_X86_64 Abi_AbiAlias = 5 + Abi_MIPS Abi_AbiAlias = 6 + Abi_MIPS64 Abi_AbiAlias = 7 +) + +var Abi_AbiAlias_name = map[int32]string{ + 0: "UNSPECIFIED_CPU_ARCHITECTURE", + 1: "ARMEABI", + 2: "ARMEABI_V7A", + 3: "ARM64_V8A", + 4: "X86", + 5: "X86_64", + 6: "MIPS", + 7: "MIPS64", +} + +var Abi_AbiAlias_value = map[string]int32{ + "UNSPECIFIED_CPU_ARCHITECTURE": 0, + "ARMEABI": 1, + "ARMEABI_V7A": 2, + "ARM64_V8A": 3, + "X86": 4, + "X86_64": 5, + "MIPS": 6, + "MIPS64": 7, +} + +func (x Abi_AbiAlias) String() string { + return proto.EnumName(Abi_AbiAlias_name, int32(x)) +} + +func (Abi_AbiAlias) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{11, 0} +} + +type Sanitizer_SanitizerAlias int32 + +const ( + Sanitizer_NONE Sanitizer_SanitizerAlias = 0 + Sanitizer_HWADDRESS Sanitizer_SanitizerAlias = 1 +) + +var Sanitizer_SanitizerAlias_name = map[int32]string{ + 0: "NONE", + 1: "HWADDRESS", +} + +var Sanitizer_SanitizerAlias_value = map[string]int32{ + "NONE": 0, + "HWADDRESS": 1, +} + +func (x Sanitizer_SanitizerAlias) String() string { + return proto.EnumName(Sanitizer_SanitizerAlias_name, int32(x)) +} + +func (Sanitizer_SanitizerAlias) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{13, 0} +} + +// Targeting on the level of variants. +type VariantTargeting struct { + SdkVersionTargeting *SdkVersionTargeting `protobuf:"bytes,1,opt,name=sdk_version_targeting,json=sdkVersionTargeting,proto3" json:"sdk_version_targeting,omitempty"` + AbiTargeting *AbiTargeting `protobuf:"bytes,2,opt,name=abi_targeting,json=abiTargeting,proto3" json:"abi_targeting,omitempty"` + ScreenDensityTargeting *ScreenDensityTargeting `protobuf:"bytes,3,opt,name=screen_density_targeting,json=screenDensityTargeting,proto3" json:"screen_density_targeting,omitempty"` + MultiAbiTargeting *MultiAbiTargeting `protobuf:"bytes,4,opt,name=multi_abi_targeting,json=multiAbiTargeting,proto3" json:"multi_abi_targeting,omitempty"` + TextureCompressionFormatTargeting *TextureCompressionFormatTargeting `protobuf:"bytes,5,opt,name=texture_compression_format_targeting,json=textureCompressionFormatTargeting,proto3" json:"texture_compression_format_targeting,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VariantTargeting) Reset() { *m = VariantTargeting{} } +func (m *VariantTargeting) String() string { return proto.CompactTextString(m) } +func (*VariantTargeting) ProtoMessage() {} +func (*VariantTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{0} +} + +func (m *VariantTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VariantTargeting.Unmarshal(m, b) +} +func (m *VariantTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VariantTargeting.Marshal(b, m, deterministic) +} +func (m *VariantTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_VariantTargeting.Merge(m, src) +} +func (m *VariantTargeting) XXX_Size() int { + return xxx_messageInfo_VariantTargeting.Size(m) +} +func (m *VariantTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_VariantTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_VariantTargeting proto.InternalMessageInfo + +func (m *VariantTargeting) GetSdkVersionTargeting() *SdkVersionTargeting { + if m != nil { + return m.SdkVersionTargeting + } + return nil +} + +func (m *VariantTargeting) GetAbiTargeting() *AbiTargeting { + if m != nil { + return m.AbiTargeting + } + return nil +} + +func (m *VariantTargeting) GetScreenDensityTargeting() *ScreenDensityTargeting { + if m != nil { + return m.ScreenDensityTargeting + } + return nil +} + +func (m *VariantTargeting) GetMultiAbiTargeting() *MultiAbiTargeting { + if m != nil { + return m.MultiAbiTargeting + } + return nil +} + +func (m *VariantTargeting) GetTextureCompressionFormatTargeting() *TextureCompressionFormatTargeting { + if m != nil { + return m.TextureCompressionFormatTargeting + } + return nil +} + +// Targeting on the level of individual APKs. +type ApkTargeting struct { + AbiTargeting *AbiTargeting `protobuf:"bytes,1,opt,name=abi_targeting,json=abiTargeting,proto3" json:"abi_targeting,omitempty"` + GraphicsApiTargeting *GraphicsApiTargeting `protobuf:"bytes,2,opt,name=graphics_api_targeting,json=graphicsApiTargeting,proto3" json:"graphics_api_targeting,omitempty"` + LanguageTargeting *LanguageTargeting `protobuf:"bytes,3,opt,name=language_targeting,json=languageTargeting,proto3" json:"language_targeting,omitempty"` + ScreenDensityTargeting *ScreenDensityTargeting `protobuf:"bytes,4,opt,name=screen_density_targeting,json=screenDensityTargeting,proto3" json:"screen_density_targeting,omitempty"` + SdkVersionTargeting *SdkVersionTargeting `protobuf:"bytes,5,opt,name=sdk_version_targeting,json=sdkVersionTargeting,proto3" json:"sdk_version_targeting,omitempty"` + TextureCompressionFormatTargeting *TextureCompressionFormatTargeting `protobuf:"bytes,6,opt,name=texture_compression_format_targeting,json=textureCompressionFormatTargeting,proto3" json:"texture_compression_format_targeting,omitempty"` + MultiAbiTargeting *MultiAbiTargeting `protobuf:"bytes,7,opt,name=multi_abi_targeting,json=multiAbiTargeting,proto3" json:"multi_abi_targeting,omitempty"` + SanitizerTargeting *SanitizerTargeting `protobuf:"bytes,8,opt,name=sanitizer_targeting,json=sanitizerTargeting,proto3" json:"sanitizer_targeting,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApkTargeting) Reset() { *m = ApkTargeting{} } +func (m *ApkTargeting) String() string { return proto.CompactTextString(m) } +func (*ApkTargeting) ProtoMessage() {} +func (*ApkTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{1} +} + +func (m *ApkTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApkTargeting.Unmarshal(m, b) +} +func (m *ApkTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApkTargeting.Marshal(b, m, deterministic) +} +func (m *ApkTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApkTargeting.Merge(m, src) +} +func (m *ApkTargeting) XXX_Size() int { + return xxx_messageInfo_ApkTargeting.Size(m) +} +func (m *ApkTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_ApkTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_ApkTargeting proto.InternalMessageInfo + +func (m *ApkTargeting) GetAbiTargeting() *AbiTargeting { + if m != nil { + return m.AbiTargeting + } + return nil +} + +func (m *ApkTargeting) GetGraphicsApiTargeting() *GraphicsApiTargeting { + if m != nil { + return m.GraphicsApiTargeting + } + return nil +} + +func (m *ApkTargeting) GetLanguageTargeting() *LanguageTargeting { + if m != nil { + return m.LanguageTargeting + } + return nil +} + +func (m *ApkTargeting) GetScreenDensityTargeting() *ScreenDensityTargeting { + if m != nil { + return m.ScreenDensityTargeting + } + return nil +} + +func (m *ApkTargeting) GetSdkVersionTargeting() *SdkVersionTargeting { + if m != nil { + return m.SdkVersionTargeting + } + return nil +} + +func (m *ApkTargeting) GetTextureCompressionFormatTargeting() *TextureCompressionFormatTargeting { + if m != nil { + return m.TextureCompressionFormatTargeting + } + return nil +} + +func (m *ApkTargeting) GetMultiAbiTargeting() *MultiAbiTargeting { + if m != nil { + return m.MultiAbiTargeting + } + return nil +} + +func (m *ApkTargeting) GetSanitizerTargeting() *SanitizerTargeting { + if m != nil { + return m.SanitizerTargeting + } + return nil +} + +// Targeting on the module level. +// The semantic of the targeting is the "AND" rule on all immediate values. +type ModuleTargeting struct { + SdkVersionTargeting *SdkVersionTargeting `protobuf:"bytes,1,opt,name=sdk_version_targeting,json=sdkVersionTargeting,proto3" json:"sdk_version_targeting,omitempty"` + DeviceFeatureTargeting []*DeviceFeatureTargeting `protobuf:"bytes,2,rep,name=device_feature_targeting,json=deviceFeatureTargeting,proto3" json:"device_feature_targeting,omitempty"` + UserCountriesTargeting *UserCountriesTargeting `protobuf:"bytes,3,opt,name=user_countries_targeting,json=userCountriesTargeting,proto3" json:"user_countries_targeting,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ModuleTargeting) Reset() { *m = ModuleTargeting{} } +func (m *ModuleTargeting) String() string { return proto.CompactTextString(m) } +func (*ModuleTargeting) ProtoMessage() {} +func (*ModuleTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{2} +} + +func (m *ModuleTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ModuleTargeting.Unmarshal(m, b) +} +func (m *ModuleTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ModuleTargeting.Marshal(b, m, deterministic) +} +func (m *ModuleTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_ModuleTargeting.Merge(m, src) +} +func (m *ModuleTargeting) XXX_Size() int { + return xxx_messageInfo_ModuleTargeting.Size(m) +} +func (m *ModuleTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_ModuleTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_ModuleTargeting proto.InternalMessageInfo + +func (m *ModuleTargeting) GetSdkVersionTargeting() *SdkVersionTargeting { + if m != nil { + return m.SdkVersionTargeting + } + return nil +} + +func (m *ModuleTargeting) GetDeviceFeatureTargeting() []*DeviceFeatureTargeting { + if m != nil { + return m.DeviceFeatureTargeting + } + return nil +} + +func (m *ModuleTargeting) GetUserCountriesTargeting() *UserCountriesTargeting { + if m != nil { + return m.UserCountriesTargeting + } + return nil +} + +// User Countries targeting describing an inclusive/exclusive list of country +// codes that module targets. +type UserCountriesTargeting struct { + // List of country codes in the two-letter CLDR territory format. + CountryCodes []string `protobuf:"bytes,1,rep,name=country_codes,json=countryCodes,proto3" json:"country_codes,omitempty"` + // Indicates if the list above is exclusive. + Exclude bool `protobuf:"varint,2,opt,name=exclude,proto3" json:"exclude,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UserCountriesTargeting) Reset() { *m = UserCountriesTargeting{} } +func (m *UserCountriesTargeting) String() string { return proto.CompactTextString(m) } +func (*UserCountriesTargeting) ProtoMessage() {} +func (*UserCountriesTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{3} +} + +func (m *UserCountriesTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UserCountriesTargeting.Unmarshal(m, b) +} +func (m *UserCountriesTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UserCountriesTargeting.Marshal(b, m, deterministic) +} +func (m *UserCountriesTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_UserCountriesTargeting.Merge(m, src) +} +func (m *UserCountriesTargeting) XXX_Size() int { + return xxx_messageInfo_UserCountriesTargeting.Size(m) +} +func (m *UserCountriesTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_UserCountriesTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_UserCountriesTargeting proto.InternalMessageInfo + +func (m *UserCountriesTargeting) GetCountryCodes() []string { + if m != nil { + return m.CountryCodes + } + return nil +} + +func (m *UserCountriesTargeting) GetExclude() bool { + if m != nil { + return m.Exclude + } + return false +} + +type ScreenDensity struct { + // Types that are valid to be assigned to DensityOneof: + // *ScreenDensity_DensityAlias_ + // *ScreenDensity_DensityDpi + DensityOneof isScreenDensity_DensityOneof `protobuf_oneof:"density_oneof"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ScreenDensity) Reset() { *m = ScreenDensity{} } +func (m *ScreenDensity) String() string { return proto.CompactTextString(m) } +func (*ScreenDensity) ProtoMessage() {} +func (*ScreenDensity) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{4} +} + +func (m *ScreenDensity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ScreenDensity.Unmarshal(m, b) +} +func (m *ScreenDensity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ScreenDensity.Marshal(b, m, deterministic) +} +func (m *ScreenDensity) XXX_Merge(src proto.Message) { + xxx_messageInfo_ScreenDensity.Merge(m, src) +} +func (m *ScreenDensity) XXX_Size() int { + return xxx_messageInfo_ScreenDensity.Size(m) +} +func (m *ScreenDensity) XXX_DiscardUnknown() { + xxx_messageInfo_ScreenDensity.DiscardUnknown(m) +} + +var xxx_messageInfo_ScreenDensity proto.InternalMessageInfo + +type isScreenDensity_DensityOneof interface { + isScreenDensity_DensityOneof() +} + +type ScreenDensity_DensityAlias_ struct { + DensityAlias ScreenDensity_DensityAlias `protobuf:"varint,1,opt,name=density_alias,json=densityAlias,proto3,enum=android.bundle.ScreenDensity_DensityAlias,oneof"` +} + +type ScreenDensity_DensityDpi struct { + DensityDpi int32 `protobuf:"varint,2,opt,name=density_dpi,json=densityDpi,proto3,oneof"` +} + +func (*ScreenDensity_DensityAlias_) isScreenDensity_DensityOneof() {} + +func (*ScreenDensity_DensityDpi) isScreenDensity_DensityOneof() {} + +func (m *ScreenDensity) GetDensityOneof() isScreenDensity_DensityOneof { + if m != nil { + return m.DensityOneof + } + return nil +} + +func (m *ScreenDensity) GetDensityAlias() ScreenDensity_DensityAlias { + if x, ok := m.GetDensityOneof().(*ScreenDensity_DensityAlias_); ok { + return x.DensityAlias + } + return ScreenDensity_DENSITY_UNSPECIFIED +} + +func (m *ScreenDensity) GetDensityDpi() int32 { + if x, ok := m.GetDensityOneof().(*ScreenDensity_DensityDpi); ok { + return x.DensityDpi + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*ScreenDensity) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*ScreenDensity_DensityAlias_)(nil), + (*ScreenDensity_DensityDpi)(nil), + } +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +type Int32Value struct { + // The int32 value. + Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Int32Value) Reset() { *m = Int32Value{} } +func (m *Int32Value) String() string { return proto.CompactTextString(m) } +func (*Int32Value) ProtoMessage() {} +func (*Int32Value) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{5} +} + +func (m *Int32Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Int32Value.Unmarshal(m, b) +} +func (m *Int32Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Int32Value.Marshal(b, m, deterministic) +} +func (m *Int32Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Int32Value.Merge(m, src) +} +func (m *Int32Value) XXX_Size() int { + return xxx_messageInfo_Int32Value.Size(m) +} +func (m *Int32Value) XXX_DiscardUnknown() { + xxx_messageInfo_Int32Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Int32Value proto.InternalMessageInfo + +func (m *Int32Value) GetValue() int32 { + if m != nil { + return m.Value + } + return 0 +} + +type SdkVersion struct { + // Inclusive. + Min *Int32Value `protobuf:"bytes,1,opt,name=min,proto3" json:"min,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SdkVersion) Reset() { *m = SdkVersion{} } +func (m *SdkVersion) String() string { return proto.CompactTextString(m) } +func (*SdkVersion) ProtoMessage() {} +func (*SdkVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{6} +} + +func (m *SdkVersion) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SdkVersion.Unmarshal(m, b) +} +func (m *SdkVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SdkVersion.Marshal(b, m, deterministic) +} +func (m *SdkVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_SdkVersion.Merge(m, src) +} +func (m *SdkVersion) XXX_Size() int { + return xxx_messageInfo_SdkVersion.Size(m) +} +func (m *SdkVersion) XXX_DiscardUnknown() { + xxx_messageInfo_SdkVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_SdkVersion proto.InternalMessageInfo + +func (m *SdkVersion) GetMin() *Int32Value { + if m != nil { + return m.Min + } + return nil +} + +type GraphicsApi struct { + // Types that are valid to be assigned to ApiOneof: + // *GraphicsApi_MinOpenGlVersion + // *GraphicsApi_MinVulkanVersion + ApiOneof isGraphicsApi_ApiOneof `protobuf_oneof:"api_oneof"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GraphicsApi) Reset() { *m = GraphicsApi{} } +func (m *GraphicsApi) String() string { return proto.CompactTextString(m) } +func (*GraphicsApi) ProtoMessage() {} +func (*GraphicsApi) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{7} +} + +func (m *GraphicsApi) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GraphicsApi.Unmarshal(m, b) +} +func (m *GraphicsApi) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GraphicsApi.Marshal(b, m, deterministic) +} +func (m *GraphicsApi) XXX_Merge(src proto.Message) { + xxx_messageInfo_GraphicsApi.Merge(m, src) +} +func (m *GraphicsApi) XXX_Size() int { + return xxx_messageInfo_GraphicsApi.Size(m) +} +func (m *GraphicsApi) XXX_DiscardUnknown() { + xxx_messageInfo_GraphicsApi.DiscardUnknown(m) +} + +var xxx_messageInfo_GraphicsApi proto.InternalMessageInfo + +type isGraphicsApi_ApiOneof interface { + isGraphicsApi_ApiOneof() +} + +type GraphicsApi_MinOpenGlVersion struct { + MinOpenGlVersion *OpenGlVersion `protobuf:"bytes,1,opt,name=min_open_gl_version,json=minOpenGlVersion,proto3,oneof"` +} + +type GraphicsApi_MinVulkanVersion struct { + MinVulkanVersion *VulkanVersion `protobuf:"bytes,2,opt,name=min_vulkan_version,json=minVulkanVersion,proto3,oneof"` +} + +func (*GraphicsApi_MinOpenGlVersion) isGraphicsApi_ApiOneof() {} + +func (*GraphicsApi_MinVulkanVersion) isGraphicsApi_ApiOneof() {} + +func (m *GraphicsApi) GetApiOneof() isGraphicsApi_ApiOneof { + if m != nil { + return m.ApiOneof + } + return nil +} + +func (m *GraphicsApi) GetMinOpenGlVersion() *OpenGlVersion { + if x, ok := m.GetApiOneof().(*GraphicsApi_MinOpenGlVersion); ok { + return x.MinOpenGlVersion + } + return nil +} + +func (m *GraphicsApi) GetMinVulkanVersion() *VulkanVersion { + if x, ok := m.GetApiOneof().(*GraphicsApi_MinVulkanVersion); ok { + return x.MinVulkanVersion + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*GraphicsApi) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*GraphicsApi_MinOpenGlVersion)(nil), + (*GraphicsApi_MinVulkanVersion)(nil), + } +} + +type VulkanVersion struct { + Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"` + Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VulkanVersion) Reset() { *m = VulkanVersion{} } +func (m *VulkanVersion) String() string { return proto.CompactTextString(m) } +func (*VulkanVersion) ProtoMessage() {} +func (*VulkanVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{8} +} + +func (m *VulkanVersion) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VulkanVersion.Unmarshal(m, b) +} +func (m *VulkanVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VulkanVersion.Marshal(b, m, deterministic) +} +func (m *VulkanVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_VulkanVersion.Merge(m, src) +} +func (m *VulkanVersion) XXX_Size() int { + return xxx_messageInfo_VulkanVersion.Size(m) +} +func (m *VulkanVersion) XXX_DiscardUnknown() { + xxx_messageInfo_VulkanVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_VulkanVersion proto.InternalMessageInfo + +func (m *VulkanVersion) GetMajor() int32 { + if m != nil { + return m.Major + } + return 0 +} + +func (m *VulkanVersion) GetMinor() int32 { + if m != nil { + return m.Minor + } + return 0 +} + +type OpenGlVersion struct { + // e.g. OpenGL ES 3.2 is represented as { major: 3, minor: 2 } + Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"` + Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OpenGlVersion) Reset() { *m = OpenGlVersion{} } +func (m *OpenGlVersion) String() string { return proto.CompactTextString(m) } +func (*OpenGlVersion) ProtoMessage() {} +func (*OpenGlVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{9} +} + +func (m *OpenGlVersion) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OpenGlVersion.Unmarshal(m, b) +} +func (m *OpenGlVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OpenGlVersion.Marshal(b, m, deterministic) +} +func (m *OpenGlVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_OpenGlVersion.Merge(m, src) +} +func (m *OpenGlVersion) XXX_Size() int { + return xxx_messageInfo_OpenGlVersion.Size(m) +} +func (m *OpenGlVersion) XXX_DiscardUnknown() { + xxx_messageInfo_OpenGlVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_OpenGlVersion proto.InternalMessageInfo + +func (m *OpenGlVersion) GetMajor() int32 { + if m != nil { + return m.Major + } + return 0 +} + +func (m *OpenGlVersion) GetMinor() int32 { + if m != nil { + return m.Minor + } + return 0 +} + +type TextureCompressionFormat struct { + Alias TextureCompressionFormat_TextureCompressionFormatAlias `protobuf:"varint,1,opt,name=alias,proto3,enum=android.bundle.TextureCompressionFormat_TextureCompressionFormatAlias" json:"alias,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TextureCompressionFormat) Reset() { *m = TextureCompressionFormat{} } +func (m *TextureCompressionFormat) String() string { return proto.CompactTextString(m) } +func (*TextureCompressionFormat) ProtoMessage() {} +func (*TextureCompressionFormat) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{10} +} + +func (m *TextureCompressionFormat) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TextureCompressionFormat.Unmarshal(m, b) +} +func (m *TextureCompressionFormat) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TextureCompressionFormat.Marshal(b, m, deterministic) +} +func (m *TextureCompressionFormat) XXX_Merge(src proto.Message) { + xxx_messageInfo_TextureCompressionFormat.Merge(m, src) +} +func (m *TextureCompressionFormat) XXX_Size() int { + return xxx_messageInfo_TextureCompressionFormat.Size(m) +} +func (m *TextureCompressionFormat) XXX_DiscardUnknown() { + xxx_messageInfo_TextureCompressionFormat.DiscardUnknown(m) +} + +var xxx_messageInfo_TextureCompressionFormat proto.InternalMessageInfo + +func (m *TextureCompressionFormat) GetAlias() TextureCompressionFormat_TextureCompressionFormatAlias { + if m != nil { + return m.Alias + } + return TextureCompressionFormat_UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT +} + +type Abi struct { + Alias Abi_AbiAlias `protobuf:"varint,1,opt,name=alias,proto3,enum=android.bundle.Abi_AbiAlias" json:"alias,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Abi) Reset() { *m = Abi{} } +func (m *Abi) String() string { return proto.CompactTextString(m) } +func (*Abi) ProtoMessage() {} +func (*Abi) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{11} +} + +func (m *Abi) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Abi.Unmarshal(m, b) +} +func (m *Abi) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Abi.Marshal(b, m, deterministic) +} +func (m *Abi) XXX_Merge(src proto.Message) { + xxx_messageInfo_Abi.Merge(m, src) +} +func (m *Abi) XXX_Size() int { + return xxx_messageInfo_Abi.Size(m) +} +func (m *Abi) XXX_DiscardUnknown() { + xxx_messageInfo_Abi.DiscardUnknown(m) +} + +var xxx_messageInfo_Abi proto.InternalMessageInfo + +func (m *Abi) GetAlias() Abi_AbiAlias { + if m != nil { + return m.Alias + } + return Abi_UNSPECIFIED_CPU_ARCHITECTURE +} + +type MultiAbi struct { + Abi []*Abi `protobuf:"bytes,1,rep,name=abi,proto3" json:"abi,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MultiAbi) Reset() { *m = MultiAbi{} } +func (m *MultiAbi) String() string { return proto.CompactTextString(m) } +func (*MultiAbi) ProtoMessage() {} +func (*MultiAbi) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{12} +} + +func (m *MultiAbi) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MultiAbi.Unmarshal(m, b) +} +func (m *MultiAbi) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MultiAbi.Marshal(b, m, deterministic) +} +func (m *MultiAbi) XXX_Merge(src proto.Message) { + xxx_messageInfo_MultiAbi.Merge(m, src) +} +func (m *MultiAbi) XXX_Size() int { + return xxx_messageInfo_MultiAbi.Size(m) +} +func (m *MultiAbi) XXX_DiscardUnknown() { + xxx_messageInfo_MultiAbi.DiscardUnknown(m) +} + +var xxx_messageInfo_MultiAbi proto.InternalMessageInfo + +func (m *MultiAbi) GetAbi() []*Abi { + if m != nil { + return m.Abi + } + return nil +} + +type Sanitizer struct { + Alias Sanitizer_SanitizerAlias `protobuf:"varint,1,opt,name=alias,proto3,enum=android.bundle.Sanitizer_SanitizerAlias" json:"alias,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Sanitizer) Reset() { *m = Sanitizer{} } +func (m *Sanitizer) String() string { return proto.CompactTextString(m) } +func (*Sanitizer) ProtoMessage() {} +func (*Sanitizer) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{13} +} + +func (m *Sanitizer) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Sanitizer.Unmarshal(m, b) +} +func (m *Sanitizer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Sanitizer.Marshal(b, m, deterministic) +} +func (m *Sanitizer) XXX_Merge(src proto.Message) { + xxx_messageInfo_Sanitizer.Merge(m, src) +} +func (m *Sanitizer) XXX_Size() int { + return xxx_messageInfo_Sanitizer.Size(m) +} +func (m *Sanitizer) XXX_DiscardUnknown() { + xxx_messageInfo_Sanitizer.DiscardUnknown(m) +} + +var xxx_messageInfo_Sanitizer proto.InternalMessageInfo + +func (m *Sanitizer) GetAlias() Sanitizer_SanitizerAlias { + if m != nil { + return m.Alias + } + return Sanitizer_NONE +} + +type DeviceFeature struct { + FeatureName string `protobuf:"bytes,1,opt,name=feature_name,json=featureName,proto3" json:"feature_name,omitempty"` + // Equivalent of android:glEsVersion or android:version in <uses-feature>. + FeatureVersion int32 `protobuf:"varint,2,opt,name=feature_version,json=featureVersion,proto3" json:"feature_version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeviceFeature) Reset() { *m = DeviceFeature{} } +func (m *DeviceFeature) String() string { return proto.CompactTextString(m) } +func (*DeviceFeature) ProtoMessage() {} +func (*DeviceFeature) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{14} +} + +func (m *DeviceFeature) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeviceFeature.Unmarshal(m, b) +} +func (m *DeviceFeature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeviceFeature.Marshal(b, m, deterministic) +} +func (m *DeviceFeature) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeviceFeature.Merge(m, src) +} +func (m *DeviceFeature) XXX_Size() int { + return xxx_messageInfo_DeviceFeature.Size(m) +} +func (m *DeviceFeature) XXX_DiscardUnknown() { + xxx_messageInfo_DeviceFeature.DiscardUnknown(m) +} + +var xxx_messageInfo_DeviceFeature proto.InternalMessageInfo + +func (m *DeviceFeature) GetFeatureName() string { + if m != nil { + return m.FeatureName + } + return "" +} + +func (m *DeviceFeature) GetFeatureVersion() int32 { + if m != nil { + return m.FeatureVersion + } + return 0 +} + +// Targeting specific for directories under assets/. +type AssetsDirectoryTargeting struct { + Abi *AbiTargeting `protobuf:"bytes,1,opt,name=abi,proto3" json:"abi,omitempty"` + GraphicsApi *GraphicsApiTargeting `protobuf:"bytes,2,opt,name=graphics_api,json=graphicsApi,proto3" json:"graphics_api,omitempty"` + TextureCompressionFormat *TextureCompressionFormatTargeting `protobuf:"bytes,3,opt,name=texture_compression_format,json=textureCompressionFormat,proto3" json:"texture_compression_format,omitempty"` + Language *LanguageTargeting `protobuf:"bytes,4,opt,name=language,proto3" json:"language,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssetsDirectoryTargeting) Reset() { *m = AssetsDirectoryTargeting{} } +func (m *AssetsDirectoryTargeting) String() string { return proto.CompactTextString(m) } +func (*AssetsDirectoryTargeting) ProtoMessage() {} +func (*AssetsDirectoryTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{15} +} + +func (m *AssetsDirectoryTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AssetsDirectoryTargeting.Unmarshal(m, b) +} +func (m *AssetsDirectoryTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AssetsDirectoryTargeting.Marshal(b, m, deterministic) +} +func (m *AssetsDirectoryTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetsDirectoryTargeting.Merge(m, src) +} +func (m *AssetsDirectoryTargeting) XXX_Size() int { + return xxx_messageInfo_AssetsDirectoryTargeting.Size(m) +} +func (m *AssetsDirectoryTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_AssetsDirectoryTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetsDirectoryTargeting proto.InternalMessageInfo + +func (m *AssetsDirectoryTargeting) GetAbi() *AbiTargeting { + if m != nil { + return m.Abi + } + return nil +} + +func (m *AssetsDirectoryTargeting) GetGraphicsApi() *GraphicsApiTargeting { + if m != nil { + return m.GraphicsApi + } + return nil +} + +func (m *AssetsDirectoryTargeting) GetTextureCompressionFormat() *TextureCompressionFormatTargeting { + if m != nil { + return m.TextureCompressionFormat + } + return nil +} + +func (m *AssetsDirectoryTargeting) GetLanguage() *LanguageTargeting { + if m != nil { + return m.Language + } + return nil +} + +// Targeting specific for directories under lib/. +type NativeDirectoryTargeting struct { + Abi *Abi `protobuf:"bytes,1,opt,name=abi,proto3" json:"abi,omitempty"` + GraphicsApi *GraphicsApi `protobuf:"bytes,2,opt,name=graphics_api,json=graphicsApi,proto3" json:"graphics_api,omitempty"` + TextureCompressionFormat *TextureCompressionFormat `protobuf:"bytes,3,opt,name=texture_compression_format,json=textureCompressionFormat,proto3" json:"texture_compression_format,omitempty"` + Sanitizer *Sanitizer `protobuf:"bytes,4,opt,name=sanitizer,proto3" json:"sanitizer,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NativeDirectoryTargeting) Reset() { *m = NativeDirectoryTargeting{} } +func (m *NativeDirectoryTargeting) String() string { return proto.CompactTextString(m) } +func (*NativeDirectoryTargeting) ProtoMessage() {} +func (*NativeDirectoryTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{16} +} + +func (m *NativeDirectoryTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NativeDirectoryTargeting.Unmarshal(m, b) +} +func (m *NativeDirectoryTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NativeDirectoryTargeting.Marshal(b, m, deterministic) +} +func (m *NativeDirectoryTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_NativeDirectoryTargeting.Merge(m, src) +} +func (m *NativeDirectoryTargeting) XXX_Size() int { + return xxx_messageInfo_NativeDirectoryTargeting.Size(m) +} +func (m *NativeDirectoryTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_NativeDirectoryTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_NativeDirectoryTargeting proto.InternalMessageInfo + +func (m *NativeDirectoryTargeting) GetAbi() *Abi { + if m != nil { + return m.Abi + } + return nil +} + +func (m *NativeDirectoryTargeting) GetGraphicsApi() *GraphicsApi { + if m != nil { + return m.GraphicsApi + } + return nil +} + +func (m *NativeDirectoryTargeting) GetTextureCompressionFormat() *TextureCompressionFormat { + if m != nil { + return m.TextureCompressionFormat + } + return nil +} + +func (m *NativeDirectoryTargeting) GetSanitizer() *Sanitizer { + if m != nil { + return m.Sanitizer + } + return nil +} + +// Targeting specific for image files under apex/. +type ApexImageTargeting struct { + MultiAbi *MultiAbiTargeting `protobuf:"bytes,1,opt,name=multi_abi,json=multiAbi,proto3" json:"multi_abi,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApexImageTargeting) Reset() { *m = ApexImageTargeting{} } +func (m *ApexImageTargeting) String() string { return proto.CompactTextString(m) } +func (*ApexImageTargeting) ProtoMessage() {} +func (*ApexImageTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{17} +} + +func (m *ApexImageTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApexImageTargeting.Unmarshal(m, b) +} +func (m *ApexImageTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApexImageTargeting.Marshal(b, m, deterministic) +} +func (m *ApexImageTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApexImageTargeting.Merge(m, src) +} +func (m *ApexImageTargeting) XXX_Size() int { + return xxx_messageInfo_ApexImageTargeting.Size(m) +} +func (m *ApexImageTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_ApexImageTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_ApexImageTargeting proto.InternalMessageInfo + +func (m *ApexImageTargeting) GetMultiAbi() *MultiAbiTargeting { + if m != nil { + return m.MultiAbi + } + return nil +} + +type AbiTargeting struct { + Value []*Abi `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*Abi `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AbiTargeting) Reset() { *m = AbiTargeting{} } +func (m *AbiTargeting) String() string { return proto.CompactTextString(m) } +func (*AbiTargeting) ProtoMessage() {} +func (*AbiTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{18} +} + +func (m *AbiTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AbiTargeting.Unmarshal(m, b) +} +func (m *AbiTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AbiTargeting.Marshal(b, m, deterministic) +} +func (m *AbiTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_AbiTargeting.Merge(m, src) +} +func (m *AbiTargeting) XXX_Size() int { + return xxx_messageInfo_AbiTargeting.Size(m) +} +func (m *AbiTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_AbiTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_AbiTargeting proto.InternalMessageInfo + +func (m *AbiTargeting) GetValue() []*Abi { + if m != nil { + return m.Value + } + return nil +} + +func (m *AbiTargeting) GetAlternatives() []*Abi { + if m != nil { + return m.Alternatives + } + return nil +} + +type MultiAbiTargeting struct { + Value []*MultiAbi `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*MultiAbi `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MultiAbiTargeting) Reset() { *m = MultiAbiTargeting{} } +func (m *MultiAbiTargeting) String() string { return proto.CompactTextString(m) } +func (*MultiAbiTargeting) ProtoMessage() {} +func (*MultiAbiTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{19} +} + +func (m *MultiAbiTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MultiAbiTargeting.Unmarshal(m, b) +} +func (m *MultiAbiTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MultiAbiTargeting.Marshal(b, m, deterministic) +} +func (m *MultiAbiTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_MultiAbiTargeting.Merge(m, src) +} +func (m *MultiAbiTargeting) XXX_Size() int { + return xxx_messageInfo_MultiAbiTargeting.Size(m) +} +func (m *MultiAbiTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_MultiAbiTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_MultiAbiTargeting proto.InternalMessageInfo + +func (m *MultiAbiTargeting) GetValue() []*MultiAbi { + if m != nil { + return m.Value + } + return nil +} + +func (m *MultiAbiTargeting) GetAlternatives() []*MultiAbi { + if m != nil { + return m.Alternatives + } + return nil +} + +type ScreenDensityTargeting struct { + Value []*ScreenDensity `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*ScreenDensity `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ScreenDensityTargeting) Reset() { *m = ScreenDensityTargeting{} } +func (m *ScreenDensityTargeting) String() string { return proto.CompactTextString(m) } +func (*ScreenDensityTargeting) ProtoMessage() {} +func (*ScreenDensityTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{20} +} + +func (m *ScreenDensityTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ScreenDensityTargeting.Unmarshal(m, b) +} +func (m *ScreenDensityTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ScreenDensityTargeting.Marshal(b, m, deterministic) +} +func (m *ScreenDensityTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_ScreenDensityTargeting.Merge(m, src) +} +func (m *ScreenDensityTargeting) XXX_Size() int { + return xxx_messageInfo_ScreenDensityTargeting.Size(m) +} +func (m *ScreenDensityTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_ScreenDensityTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_ScreenDensityTargeting proto.InternalMessageInfo + +func (m *ScreenDensityTargeting) GetValue() []*ScreenDensity { + if m != nil { + return m.Value + } + return nil +} + +func (m *ScreenDensityTargeting) GetAlternatives() []*ScreenDensity { + if m != nil { + return m.Alternatives + } + return nil +} + +type LanguageTargeting struct { + // ISO-639: 2 or 3 letter language code. + Value []string `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []string `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LanguageTargeting) Reset() { *m = LanguageTargeting{} } +func (m *LanguageTargeting) String() string { return proto.CompactTextString(m) } +func (*LanguageTargeting) ProtoMessage() {} +func (*LanguageTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{21} +} + +func (m *LanguageTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LanguageTargeting.Unmarshal(m, b) +} +func (m *LanguageTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LanguageTargeting.Marshal(b, m, deterministic) +} +func (m *LanguageTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_LanguageTargeting.Merge(m, src) +} +func (m *LanguageTargeting) XXX_Size() int { + return xxx_messageInfo_LanguageTargeting.Size(m) +} +func (m *LanguageTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_LanguageTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_LanguageTargeting proto.InternalMessageInfo + +func (m *LanguageTargeting) GetValue() []string { + if m != nil { + return m.Value + } + return nil +} + +func (m *LanguageTargeting) GetAlternatives() []string { + if m != nil { + return m.Alternatives + } + return nil +} + +type GraphicsApiTargeting struct { + Value []*GraphicsApi `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*GraphicsApi `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GraphicsApiTargeting) Reset() { *m = GraphicsApiTargeting{} } +func (m *GraphicsApiTargeting) String() string { return proto.CompactTextString(m) } +func (*GraphicsApiTargeting) ProtoMessage() {} +func (*GraphicsApiTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{22} +} + +func (m *GraphicsApiTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GraphicsApiTargeting.Unmarshal(m, b) +} +func (m *GraphicsApiTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GraphicsApiTargeting.Marshal(b, m, deterministic) +} +func (m *GraphicsApiTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_GraphicsApiTargeting.Merge(m, src) +} +func (m *GraphicsApiTargeting) XXX_Size() int { + return xxx_messageInfo_GraphicsApiTargeting.Size(m) +} +func (m *GraphicsApiTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_GraphicsApiTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_GraphicsApiTargeting proto.InternalMessageInfo + +func (m *GraphicsApiTargeting) GetValue() []*GraphicsApi { + if m != nil { + return m.Value + } + return nil +} + +func (m *GraphicsApiTargeting) GetAlternatives() []*GraphicsApi { + if m != nil { + return m.Alternatives + } + return nil +} + +type SdkVersionTargeting struct { + Value []*SdkVersion `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*SdkVersion `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SdkVersionTargeting) Reset() { *m = SdkVersionTargeting{} } +func (m *SdkVersionTargeting) String() string { return proto.CompactTextString(m) } +func (*SdkVersionTargeting) ProtoMessage() {} +func (*SdkVersionTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{23} +} + +func (m *SdkVersionTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SdkVersionTargeting.Unmarshal(m, b) +} +func (m *SdkVersionTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SdkVersionTargeting.Marshal(b, m, deterministic) +} +func (m *SdkVersionTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_SdkVersionTargeting.Merge(m, src) +} +func (m *SdkVersionTargeting) XXX_Size() int { + return xxx_messageInfo_SdkVersionTargeting.Size(m) +} +func (m *SdkVersionTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_SdkVersionTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_SdkVersionTargeting proto.InternalMessageInfo + +func (m *SdkVersionTargeting) GetValue() []*SdkVersion { + if m != nil { + return m.Value + } + return nil +} + +func (m *SdkVersionTargeting) GetAlternatives() []*SdkVersion { + if m != nil { + return m.Alternatives + } + return nil +} + +type TextureCompressionFormatTargeting struct { + Value []*TextureCompressionFormat `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + Alternatives []*TextureCompressionFormat `protobuf:"bytes,2,rep,name=alternatives,proto3" json:"alternatives,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TextureCompressionFormatTargeting) Reset() { *m = TextureCompressionFormatTargeting{} } +func (m *TextureCompressionFormatTargeting) String() string { return proto.CompactTextString(m) } +func (*TextureCompressionFormatTargeting) ProtoMessage() {} +func (*TextureCompressionFormatTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{24} +} + +func (m *TextureCompressionFormatTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TextureCompressionFormatTargeting.Unmarshal(m, b) +} +func (m *TextureCompressionFormatTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TextureCompressionFormatTargeting.Marshal(b, m, deterministic) +} +func (m *TextureCompressionFormatTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_TextureCompressionFormatTargeting.Merge(m, src) +} +func (m *TextureCompressionFormatTargeting) XXX_Size() int { + return xxx_messageInfo_TextureCompressionFormatTargeting.Size(m) +} +func (m *TextureCompressionFormatTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_TextureCompressionFormatTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_TextureCompressionFormatTargeting proto.InternalMessageInfo + +func (m *TextureCompressionFormatTargeting) GetValue() []*TextureCompressionFormat { + if m != nil { + return m.Value + } + return nil +} + +func (m *TextureCompressionFormatTargeting) GetAlternatives() []*TextureCompressionFormat { + if m != nil { + return m.Alternatives + } + return nil +} + +type SanitizerTargeting struct { + Value []*Sanitizer `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SanitizerTargeting) Reset() { *m = SanitizerTargeting{} } +func (m *SanitizerTargeting) String() string { return proto.CompactTextString(m) } +func (*SanitizerTargeting) ProtoMessage() {} +func (*SanitizerTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{25} +} + +func (m *SanitizerTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SanitizerTargeting.Unmarshal(m, b) +} +func (m *SanitizerTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SanitizerTargeting.Marshal(b, m, deterministic) +} +func (m *SanitizerTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_SanitizerTargeting.Merge(m, src) +} +func (m *SanitizerTargeting) XXX_Size() int { + return xxx_messageInfo_SanitizerTargeting.Size(m) +} +func (m *SanitizerTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_SanitizerTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_SanitizerTargeting proto.InternalMessageInfo + +func (m *SanitizerTargeting) GetValue() []*Sanitizer { + if m != nil { + return m.Value + } + return nil +} + +// Since other atom targeting messages have the "OR" semantic on values +// the DeviceFeatureTargeting represents only one device feature to retain +// that convention. +type DeviceFeatureTargeting struct { + RequiredFeature *DeviceFeature `protobuf:"bytes,1,opt,name=required_feature,json=requiredFeature,proto3" json:"required_feature,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeviceFeatureTargeting) Reset() { *m = DeviceFeatureTargeting{} } +func (m *DeviceFeatureTargeting) String() string { return proto.CompactTextString(m) } +func (*DeviceFeatureTargeting) ProtoMessage() {} +func (*DeviceFeatureTargeting) Descriptor() ([]byte, []int) { + return fileDescriptor_df45b505afdf471e, []int{26} +} + +func (m *DeviceFeatureTargeting) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeviceFeatureTargeting.Unmarshal(m, b) +} +func (m *DeviceFeatureTargeting) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeviceFeatureTargeting.Marshal(b, m, deterministic) +} +func (m *DeviceFeatureTargeting) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeviceFeatureTargeting.Merge(m, src) +} +func (m *DeviceFeatureTargeting) XXX_Size() int { + return xxx_messageInfo_DeviceFeatureTargeting.Size(m) +} +func (m *DeviceFeatureTargeting) XXX_DiscardUnknown() { + xxx_messageInfo_DeviceFeatureTargeting.DiscardUnknown(m) +} + +var xxx_messageInfo_DeviceFeatureTargeting proto.InternalMessageInfo + +func (m *DeviceFeatureTargeting) GetRequiredFeature() *DeviceFeature { + if m != nil { + return m.RequiredFeature + } + return nil +} + +func init() { + proto.RegisterEnum("android.bundle.ScreenDensity_DensityAlias", ScreenDensity_DensityAlias_name, ScreenDensity_DensityAlias_value) + proto.RegisterEnum("android.bundle.TextureCompressionFormat_TextureCompressionFormatAlias", TextureCompressionFormat_TextureCompressionFormatAlias_name, TextureCompressionFormat_TextureCompressionFormatAlias_value) + proto.RegisterEnum("android.bundle.Abi_AbiAlias", Abi_AbiAlias_name, Abi_AbiAlias_value) + proto.RegisterEnum("android.bundle.Sanitizer_SanitizerAlias", Sanitizer_SanitizerAlias_name, Sanitizer_SanitizerAlias_value) + proto.RegisterType((*VariantTargeting)(nil), "android.bundle.VariantTargeting") + proto.RegisterType((*ApkTargeting)(nil), "android.bundle.ApkTargeting") + proto.RegisterType((*ModuleTargeting)(nil), "android.bundle.ModuleTargeting") + proto.RegisterType((*UserCountriesTargeting)(nil), "android.bundle.UserCountriesTargeting") + proto.RegisterType((*ScreenDensity)(nil), "android.bundle.ScreenDensity") + proto.RegisterType((*Int32Value)(nil), "android.bundle.Int32Value") + proto.RegisterType((*SdkVersion)(nil), "android.bundle.SdkVersion") + proto.RegisterType((*GraphicsApi)(nil), "android.bundle.GraphicsApi") + proto.RegisterType((*VulkanVersion)(nil), "android.bundle.VulkanVersion") + proto.RegisterType((*OpenGlVersion)(nil), "android.bundle.OpenGlVersion") + proto.RegisterType((*TextureCompressionFormat)(nil), "android.bundle.TextureCompressionFormat") + proto.RegisterType((*Abi)(nil), "android.bundle.Abi") + proto.RegisterType((*MultiAbi)(nil), "android.bundle.MultiAbi") + proto.RegisterType((*Sanitizer)(nil), "android.bundle.Sanitizer") + proto.RegisterType((*DeviceFeature)(nil), "android.bundle.DeviceFeature") + proto.RegisterType((*AssetsDirectoryTargeting)(nil), "android.bundle.AssetsDirectoryTargeting") + proto.RegisterType((*NativeDirectoryTargeting)(nil), "android.bundle.NativeDirectoryTargeting") + proto.RegisterType((*ApexImageTargeting)(nil), "android.bundle.ApexImageTargeting") + proto.RegisterType((*AbiTargeting)(nil), "android.bundle.AbiTargeting") + proto.RegisterType((*MultiAbiTargeting)(nil), "android.bundle.MultiAbiTargeting") + proto.RegisterType((*ScreenDensityTargeting)(nil), "android.bundle.ScreenDensityTargeting") + proto.RegisterType((*LanguageTargeting)(nil), "android.bundle.LanguageTargeting") + proto.RegisterType((*GraphicsApiTargeting)(nil), "android.bundle.GraphicsApiTargeting") + proto.RegisterType((*SdkVersionTargeting)(nil), "android.bundle.SdkVersionTargeting") + proto.RegisterType((*TextureCompressionFormatTargeting)(nil), "android.bundle.TextureCompressionFormatTargeting") + proto.RegisterType((*SanitizerTargeting)(nil), "android.bundle.SanitizerTargeting") + proto.RegisterType((*DeviceFeatureTargeting)(nil), "android.bundle.DeviceFeatureTargeting") +} + +func init() { + proto.RegisterFile("targeting.proto", fileDescriptor_df45b505afdf471e) +} + +var fileDescriptor_df45b505afdf471e = []byte{ + // 1504 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5b, 0x6f, 0xe3, 0xc4, + 0x17, 0xaf, 0x93, 0xa6, 0x4d, 0x4e, 0x92, 0xd6, 0x3b, 0xe9, 0xbf, 0xff, 0xb0, 0xec, 0x4a, 0x5b, + 0xef, 0x85, 0xee, 0x0a, 0x05, 0xda, 0xae, 0xba, 0x15, 0x97, 0x22, 0xd7, 0x71, 0x9b, 0x48, 0x4d, + 0x9a, 0x75, 0xdc, 0x6c, 0x59, 0x90, 0xbc, 0x4e, 0x3c, 0x0d, 0xa6, 0x89, 0x1d, 0x6c, 0xa7, 0xda, + 0xe5, 0x05, 0x81, 0x90, 0x90, 0x78, 0xe2, 0x8d, 0x77, 0x3e, 0x00, 0x12, 0x4f, 0x08, 0x89, 0x07, + 0x24, 0x3e, 0x0c, 0x7c, 0x0c, 0x34, 0xbe, 0x24, 0x9e, 0xc4, 0x4e, 0xb3, 0x2c, 0xf0, 0x50, 0xe5, + 0xcc, 0xf1, 0x39, 0xbf, 0x73, 0x99, 0x73, 0x66, 0xce, 0x14, 0x56, 0x1d, 0xd5, 0xea, 0x62, 0x47, + 0x37, 0xba, 0xa5, 0x81, 0x65, 0x3a, 0x26, 0x5a, 0x51, 0x0d, 0xcd, 0x32, 0x75, 0xad, 0xd4, 0x1e, + 0x1a, 0x5a, 0x0f, 0x73, 0x7f, 0x26, 0x81, 0x6d, 0xa9, 0x96, 0xae, 0x1a, 0x8e, 0x1c, 0x88, 0xa2, + 0x27, 0xf0, 0x3f, 0x5b, 0xbb, 0x50, 0x2e, 0xb1, 0x65, 0xeb, 0xa6, 0xa1, 0x8c, 0x30, 0x8a, 0xcc, + 0x2d, 0x66, 0x33, 0xbb, 0x7d, 0xbb, 0x44, 0x83, 0x94, 0x9a, 0xda, 0x45, 0xcb, 0x93, 0x1d, 0x61, + 0x48, 0x05, 0x7b, 0x9a, 0x89, 0x78, 0xc8, 0xab, 0x6d, 0x3d, 0x04, 0x98, 0x70, 0x01, 0x6f, 0x4c, + 0x02, 0xf2, 0x6d, 0x7d, 0x8c, 0x94, 0x53, 0x43, 0x2b, 0xf4, 0x0c, 0x8a, 0x76, 0xc7, 0xc2, 0xd8, + 0x50, 0x34, 0x6c, 0xd8, 0xba, 0xf3, 0x22, 0x84, 0x96, 0x74, 0xd1, 0xee, 0x4d, 0xb9, 0xe7, 0xca, + 0x97, 0x3d, 0xf1, 0x31, 0xee, 0xba, 0x1d, 0xc9, 0x47, 0x8f, 0xa1, 0xd0, 0x1f, 0xf6, 0x1c, 0x5d, + 0xa1, 0x5d, 0x5d, 0x74, 0xc1, 0x37, 0x26, 0xc1, 0x6b, 0x44, 0x94, 0xf2, 0xf7, 0x5a, 0x7f, 0x92, + 0x85, 0xbe, 0x62, 0xe0, 0x8e, 0x83, 0x9f, 0x3b, 0x43, 0x0b, 0x2b, 0x1d, 0xb3, 0x3f, 0xb0, 0xb0, + 0xed, 0x66, 0xf6, 0xdc, 0xb4, 0xfa, 0xaa, 0x13, 0x32, 0x92, 0x72, 0x8d, 0x6c, 0x4d, 0x1a, 0x91, + 0x3d, 0x5d, 0x61, 0xac, 0x7a, 0xe8, 0x6a, 0x8e, 0x8d, 0x6e, 0x38, 0x57, 0x89, 0x70, 0x7f, 0xa4, + 0x20, 0xc7, 0x0f, 0x2e, 0x66, 0xec, 0x06, 0xf3, 0xd2, 0xbb, 0xf1, 0x14, 0xd6, 0xbb, 0x96, 0x3a, + 0xf8, 0x44, 0xef, 0xd8, 0x8a, 0x3a, 0x98, 0xde, 0xd9, 0x3b, 0x93, 0x58, 0x47, 0xbe, 0x34, 0x3f, + 0x08, 0x61, 0xae, 0x75, 0x23, 0xb8, 0xa8, 0x01, 0xa8, 0xa7, 0x1a, 0xdd, 0xa1, 0xda, 0xc5, 0x53, + 0x7b, 0x3c, 0xb5, 0x0d, 0xc7, 0xbe, 0x64, 0x68, 0x1b, 0x7a, 0x93, 0xac, 0x99, 0xb5, 0xb3, 0xf8, + 0x8f, 0xd4, 0x4e, 0x6c, 0xe7, 0xa4, 0x5e, 0xb1, 0x73, 0xe6, 0xae, 0xa0, 0xa5, 0x7f, 0xaf, 0x82, + 0xe2, 0x3a, 0x63, 0xf9, 0x15, 0x3a, 0xa3, 0x09, 0x05, 0x5b, 0x35, 0x74, 0x47, 0xff, 0x1c, 0x5b, + 0x21, 0xc8, 0xb4, 0x0b, 0xc9, 0x4d, 0xa5, 0x2b, 0x10, 0x1d, 0x63, 0x22, 0x7b, 0x8a, 0xc7, 0xfd, + 0x98, 0x80, 0xd5, 0x9a, 0xa9, 0x0d, 0x7b, 0xf8, 0x3f, 0x38, 0xd3, 0x9e, 0x41, 0x51, 0xc3, 0x97, + 0x7a, 0x07, 0x2b, 0xe7, 0x58, 0x75, 0xf7, 0x27, 0xdc, 0x04, 0xc9, 0xa8, 0xa2, 0x2a, 0xbb, 0xf2, + 0x87, 0x9e, 0x78, 0xa8, 0xa8, 0xb4, 0x48, 0x3e, 0xb1, 0x30, 0xb4, 0xb1, 0xa5, 0x74, 0xcc, 0xa1, + 0xe1, 0x58, 0x3a, 0xb6, 0xaf, 0x3e, 0xf2, 0x4e, 0x6d, 0x6c, 0x09, 0x81, 0x78, 0xc8, 0xc2, 0x30, + 0x92, 0xcf, 0x3d, 0x81, 0xf5, 0x68, 0x0d, 0x74, 0x1b, 0xf2, 0x9e, 0xd9, 0x17, 0x4a, 0xc7, 0xd4, + 0xb0, 0x5d, 0x64, 0x6e, 0x25, 0x37, 0x33, 0x52, 0xce, 0x67, 0x0a, 0x84, 0x87, 0x8a, 0xb0, 0x8c, + 0x9f, 0x77, 0x7a, 0x43, 0x0d, 0xbb, 0x6d, 0x9f, 0x96, 0x82, 0x25, 0xf7, 0x7d, 0x02, 0xf2, 0x54, + 0x0b, 0xa1, 0xc7, 0x90, 0x0f, 0x9a, 0x4f, 0xed, 0xe9, 0xaa, 0xed, 0xe6, 0x7f, 0x65, 0xfb, 0xc1, + 0xcc, 0xc6, 0x2b, 0xf9, 0xbf, 0x3c, 0xd1, 0xa8, 0x2c, 0x48, 0x39, 0x2d, 0xb4, 0x46, 0x1b, 0x90, + 0x0d, 0x20, 0xb5, 0x81, 0xee, 0xba, 0x90, 0xaa, 0x2c, 0x48, 0xe0, 0x33, 0xcb, 0x03, 0x9d, 0xfb, + 0x02, 0x72, 0x61, 0x08, 0xf4, 0x7f, 0x28, 0x94, 0xc5, 0x7a, 0xb3, 0x2a, 0x7f, 0xa8, 0x9c, 0xd6, + 0x9b, 0x0d, 0x51, 0xa8, 0x1e, 0x56, 0xc5, 0x32, 0xbb, 0x80, 0x32, 0x90, 0xaa, 0x9f, 0x94, 0x1b, + 0x55, 0x96, 0x41, 0x69, 0x58, 0x3c, 0x26, 0x54, 0x82, 0x50, 0x35, 0x42, 0x25, 0xc9, 0x67, 0xb9, + 0x45, 0xc8, 0x45, 0xc2, 0xac, 0x10, 0x2a, 0x45, 0x98, 0x67, 0x2e, 0xb9, 0x84, 0x00, 0x96, 0xce, + 0x3c, 0x7a, 0x19, 0x65, 0x61, 0xf9, 0xcc, 0x5f, 0xa4, 0x0f, 0x56, 0xc7, 0x61, 0x9b, 0x06, 0x36, + 0xcf, 0x39, 0x0e, 0xa0, 0x6a, 0x38, 0x3b, 0xdb, 0x2d, 0xb5, 0x37, 0xc4, 0x68, 0x0d, 0x52, 0x97, + 0x84, 0x70, 0xb3, 0x91, 0x92, 0xbc, 0x05, 0xf7, 0x0e, 0xc0, 0xb8, 0x0c, 0xd1, 0x9b, 0x90, 0xec, + 0xeb, 0x86, 0x5f, 0xaf, 0xd7, 0x27, 0xf3, 0x35, 0x06, 0x93, 0x88, 0x18, 0xf7, 0x0b, 0x03, 0xd9, + 0xd0, 0x61, 0x8b, 0xea, 0x50, 0xe8, 0xeb, 0x86, 0x62, 0x0e, 0xb0, 0xa1, 0x74, 0x7b, 0x41, 0x1f, + 0xf8, 0x68, 0x37, 0x27, 0xd1, 0x4e, 0x06, 0xd8, 0x38, 0xea, 0xf9, 0x96, 0x2b, 0x0b, 0x12, 0xdb, + 0xd7, 0x0d, 0x8a, 0x87, 0x6a, 0x80, 0x08, 0xde, 0xe5, 0xb0, 0x77, 0xa1, 0x1a, 0x23, 0xb8, 0x44, + 0x34, 0x5c, 0xcb, 0x95, 0xa2, 0xe1, 0x28, 0xde, 0x41, 0x16, 0x32, 0xe4, 0xfe, 0xf0, 0x72, 0xf3, + 0x2e, 0xe4, 0xa9, 0xaf, 0x24, 0x3d, 0x7d, 0xf5, 0x53, 0xd3, 0x0a, 0xd2, 0xe3, 0x2e, 0x5c, 0xae, + 0x6e, 0x98, 0x96, 0xb7, 0xe3, 0x92, 0xb7, 0x20, 0xca, 0xb4, 0xa7, 0x2f, 0xa3, 0xfc, 0x73, 0x02, + 0x8a, 0x71, 0x47, 0x25, 0xfa, 0x18, 0x52, 0xe1, 0x92, 0x3d, 0x9c, 0xf7, 0x8c, 0x8d, 0xfd, 0xe0, + 0xd6, 0xa2, 0xe4, 0x81, 0x72, 0xbf, 0x32, 0x70, 0x73, 0xa6, 0x20, 0x7a, 0x00, 0xf7, 0x42, 0xc5, + 0xaa, 0xc8, 0xe2, 0x99, 0x7c, 0x2a, 0x89, 0x8a, 0x70, 0x52, 0x6b, 0x48, 0x62, 0xb3, 0x59, 0x3d, + 0xa9, 0x2b, 0x87, 0x27, 0x52, 0x8d, 0x97, 0xd9, 0x05, 0x94, 0x87, 0x8c, 0x28, 0x0b, 0x5b, 0x8a, + 0x74, 0x74, 0xb0, 0xc7, 0x32, 0x28, 0x07, 0xe9, 0x06, 0x7f, 0x2c, 0xca, 0xb2, 0x58, 0x66, 0x13, + 0x64, 0x25, 0x57, 0x24, 0x51, 0x54, 0xca, 0x02, 0x9b, 0x44, 0xcb, 0x90, 0xe4, 0x65, 0xc1, 0xab, + 0xe8, 0x63, 0x42, 0xa5, 0x08, 0x55, 0x3e, 0x93, 0xb7, 0xd8, 0x25, 0x42, 0x35, 0x77, 0x64, 0x81, + 0x5d, 0x26, 0x55, 0xde, 0x68, 0x49, 0xb2, 0xc0, 0xa6, 0x09, 0x93, 0x6f, 0xca, 0x02, 0x9b, 0x21, + 0x94, 0x28, 0x0b, 0xdb, 0x2c, 0x70, 0xbf, 0x31, 0x90, 0xe4, 0xdb, 0x3a, 0xda, 0xa6, 0x93, 0x14, + 0x35, 0x4c, 0x90, 0x3f, 0x2a, 0xf4, 0xaf, 0x19, 0x48, 0x07, 0x3c, 0x74, 0x0b, 0x6e, 0x84, 0xa3, + 0x14, 0x1a, 0xa7, 0x0a, 0x2f, 0x09, 0x95, 0xaa, 0x2c, 0x0a, 0x24, 0x5c, 0x76, 0x81, 0x34, 0x16, + 0x2f, 0xd5, 0x44, 0xfe, 0x80, 0x74, 0xe9, 0x2a, 0x64, 0xfd, 0x85, 0xd2, 0x7a, 0xc4, 0xb3, 0x09, + 0x12, 0x39, 0x2f, 0xd5, 0x76, 0x1f, 0x2a, 0xad, 0x3d, 0xde, 0x8b, 0xee, 0x6c, 0x6f, 0x97, 0x5d, + 0x74, 0x5b, 0x73, 0x6f, 0x57, 0xd9, 0x7d, 0xe8, 0xc5, 0x57, 0xab, 0x36, 0x9a, 0x5e, 0xc3, 0x12, + 0x6a, 0xf7, 0x21, 0xbb, 0xcc, 0x6d, 0x41, 0x3a, 0xb8, 0xb3, 0xd0, 0x5d, 0x48, 0xaa, 0x6d, 0xdd, + 0x3d, 0xed, 0xb2, 0xdb, 0x85, 0x88, 0x20, 0x24, 0xf2, 0x9d, 0xbb, 0x84, 0xcc, 0xe8, 0x4e, 0x42, + 0xfb, 0x74, 0xe8, 0x9b, 0xb1, 0xb7, 0xd7, 0x98, 0xa2, 0xd2, 0x70, 0x1f, 0x56, 0xe8, 0x0f, 0xc4, + 0xcf, 0xfa, 0x49, 0x5d, 0xf4, 0xf6, 0xb3, 0xf2, 0x84, 0x2f, 0x97, 0xc9, 0x46, 0xb3, 0x0c, 0xf7, + 0x11, 0xe4, 0xa9, 0x4b, 0x04, 0x6d, 0x40, 0x2e, 0xb8, 0x7e, 0x0c, 0xb5, 0xef, 0x9d, 0x23, 0x19, + 0x29, 0xeb, 0xf3, 0xea, 0x6a, 0x1f, 0xa3, 0x37, 0x60, 0x35, 0x10, 0x09, 0xb7, 0x6b, 0x4a, 0x5a, + 0xf1, 0xd9, 0x7e, 0xc3, 0x70, 0xbf, 0x27, 0xa0, 0xc8, 0xdb, 0x36, 0x76, 0xec, 0xb2, 0x6e, 0xe1, + 0x8e, 0x63, 0x5a, 0xa1, 0x09, 0xa7, 0x14, 0x24, 0xe6, 0xea, 0x51, 0x91, 0x08, 0xa2, 0x23, 0xc8, + 0x85, 0x27, 0xc4, 0x97, 0x9a, 0x0b, 0xb3, 0xa1, 0xb9, 0x10, 0x99, 0x70, 0x3d, 0x7e, 0x00, 0xf2, + 0xef, 0xc1, 0xbf, 0x31, 0xf6, 0x14, 0xe3, 0xc6, 0x1e, 0xf4, 0x3e, 0xa4, 0x83, 0x11, 0x32, 0x6e, + 0xf8, 0x9f, 0x9e, 0x3a, 0x47, 0x2a, 0xdc, 0x0f, 0x09, 0x28, 0xd6, 0x55, 0x47, 0xbf, 0xc4, 0x11, + 0x59, 0xbc, 0x1b, 0xce, 0x62, 0x6c, 0x79, 0xa1, 0xfd, 0xc8, 0xe4, 0xbd, 0x3e, 0x23, 0x79, 0x74, + 0xce, 0xce, 0xe7, 0xc8, 0xd9, 0xe6, 0xbc, 0x39, 0x9b, 0x91, 0xaa, 0x47, 0x90, 0x19, 0x8d, 0x61, + 0x7e, 0xae, 0x5e, 0x8b, 0xad, 0x7e, 0x69, 0x2c, 0xcb, 0xc9, 0x80, 0xf8, 0x01, 0x7e, 0x5e, 0xed, + 0x53, 0x73, 0xfa, 0x3e, 0x64, 0x46, 0x73, 0xa6, 0x9f, 0xa3, 0x39, 0xa6, 0xcb, 0x74, 0x30, 0x5d, + 0x72, 0x16, 0xe4, 0xa8, 0x21, 0xf3, 0xfe, 0xf8, 0x76, 0x8d, 0x6d, 0x67, 0x4f, 0x02, 0x3d, 0x82, + 0x9c, 0xda, 0x73, 0xb0, 0x65, 0xb8, 0x3b, 0x67, 0xfb, 0x13, 0x5c, 0xa4, 0x06, 0x25, 0xc8, 0x7d, + 0xc9, 0xc0, 0xb5, 0x29, 0x9f, 0x50, 0x89, 0xb6, 0x5c, 0x8c, 0x8b, 0x22, 0x30, 0xff, 0x5e, 0xa4, + 0xf9, 0x78, 0x35, 0xda, 0x87, 0xef, 0x18, 0x58, 0x8f, 0x7e, 0xb0, 0xa0, 0x1d, 0xda, 0x91, 0x9b, + 0x33, 0xc7, 0xad, 0xc0, 0x1b, 0x3e, 0xd2, 0x9b, 0x2b, 0x74, 0x69, 0x97, 0x6a, 0x70, 0x6d, 0xaa, + 0x49, 0xc2, 0xd3, 0x0e, 0x19, 0x26, 0x7d, 0x6b, 0x5c, 0x84, 0xb5, 0xcc, 0x04, 0xdc, 0xb7, 0x0c, + 0xac, 0x45, 0x1d, 0x15, 0x68, 0x8b, 0x8e, 0x6f, 0x66, 0x8b, 0xf8, 0xf6, 0x3e, 0x88, 0x8c, 0x6e, + 0xa6, 0x26, 0xed, 0xcc, 0x37, 0x0c, 0x14, 0x22, 0x9e, 0x09, 0xe8, 0x6d, 0xda, 0x97, 0xeb, 0xf1, + 0x4f, 0x8b, 0xc0, 0x95, 0xfd, 0x48, 0x57, 0x66, 0x29, 0xd2, 0x9e, 0xfc, 0xc4, 0xc0, 0xc6, 0x95, + 0x47, 0x1d, 0xb9, 0x9f, 0xc2, 0x7e, 0xcd, 0xdf, 0xf8, 0xbe, 0x97, 0xc7, 0x91, 0x5e, 0xce, 0x0f, + 0x43, 0xfb, 0x2c, 0x02, 0x9a, 0x7e, 0xce, 0xa1, 0xb7, 0x68, 0x1f, 0x67, 0x9c, 0x22, 0xfe, 0x8c, + 0xdc, 0x86, 0xf5, 0xe8, 0xe7, 0x14, 0xaa, 0x00, 0x6b, 0xe1, 0xcf, 0x86, 0xba, 0x85, 0xb5, 0xe0, + 0x69, 0x16, 0x37, 0xee, 0x52, 0x08, 0xd2, 0x6a, 0xa0, 0xe6, 0x33, 0x0e, 0x1e, 0x00, 0xea, 0x98, + 0xfd, 0x09, 0xa5, 0xa7, 0x6b, 0xfe, 0x5a, 0xf1, 0xd6, 0x8a, 0xfb, 0x0f, 0xb6, 0xf6, 0x92, 0xfb, + 0xb3, 0xf3, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x47, 0xe0, 0x85, 0xa8, 0x7a, 0x13, 0x00, 0x00, +} diff --git a/cmd/extract_apks/bundle_proto/targeting.proto b/cmd/extract_apks/bundle_proto/targeting.proto new file mode 100644 index 000000000..cdc910b9d --- /dev/null +++ b/cmd/extract_apks/bundle_proto/targeting.proto @@ -0,0 +1,232 @@ +// Messages describing APK Set's table of contents (toc.pb entry). +// Please be advised that the ultimate source is at +// https://github.com/google/bundletool/tree/master/src/main/proto +// so you have been warned. +syntax = "proto3"; + +package android.bundle; + +option go_package = "android_bundle_proto"; +option java_package = "com.android.bundle"; + +// Targeting on the level of variants. +message VariantTargeting { + SdkVersionTargeting sdk_version_targeting = 1; + AbiTargeting abi_targeting = 2; + ScreenDensityTargeting screen_density_targeting = 3; + MultiAbiTargeting multi_abi_targeting = 4; + TextureCompressionFormatTargeting texture_compression_format_targeting = 5; +} + +// Targeting on the level of individual APKs. +message ApkTargeting { + AbiTargeting abi_targeting = 1; + GraphicsApiTargeting graphics_api_targeting = 2; + LanguageTargeting language_targeting = 3; + ScreenDensityTargeting screen_density_targeting = 4; + SdkVersionTargeting sdk_version_targeting = 5; + TextureCompressionFormatTargeting texture_compression_format_targeting = 6; + MultiAbiTargeting multi_abi_targeting = 7; + SanitizerTargeting sanitizer_targeting = 8; +} + +// Targeting on the module level. +// The semantic of the targeting is the "AND" rule on all immediate values. +message ModuleTargeting { + SdkVersionTargeting sdk_version_targeting = 1; + repeated DeviceFeatureTargeting device_feature_targeting = 2; + UserCountriesTargeting user_countries_targeting = 3; +} + +// User Countries targeting describing an inclusive/exclusive list of country +// codes that module targets. +message UserCountriesTargeting { + // List of country codes in the two-letter CLDR territory format. + repeated string country_codes = 1; + + // Indicates if the list above is exclusive. + bool exclude = 2; +} + +message ScreenDensity { + enum DensityAlias { + DENSITY_UNSPECIFIED = 0; + NODPI = 1; + LDPI = 2; + MDPI = 3; + TVDPI = 4; + HDPI = 5; + XHDPI = 6; + XXHDPI = 7; + XXXHDPI = 8; + } + + oneof density_oneof { + DensityAlias density_alias = 1; + int32 density_dpi = 2; + } +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +message SdkVersion { + // Inclusive. + Int32Value min = 1; +} + +message GraphicsApi { + oneof api_oneof { + // Inclusive. + OpenGlVersion min_open_gl_version = 1; + // Inclusive. + VulkanVersion min_vulkan_version = 2; + } +} + +message VulkanVersion { + int32 major = 1; // VK_VERSION_MAJOR + int32 minor = 2; // VK_VERSION_MINOR +} + +message OpenGlVersion { + // e.g. OpenGL ES 3.2 is represented as { major: 3, minor: 2 } + int32 major = 1; // GL_MAJOR_VERSION + int32 minor = 2; // GL_MINOR_VERSION +} + +message TextureCompressionFormat { + enum TextureCompressionFormatAlias { + UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT = 0; + ETC1_RGB8 = 1; + PALETTED = 2; + THREE_DC = 3; + ATC = 4; + LATC = 5; + DXT1 = 6; + S3TC = 7; + PVRTC = 8; + ASTC = 9; + ETC2 = 10; + } + TextureCompressionFormatAlias alias = 1; +} + +message Abi { + enum AbiAlias { + UNSPECIFIED_CPU_ARCHITECTURE = 0; + ARMEABI = 1; + ARMEABI_V7A = 2; + ARM64_V8A = 3; + X86 = 4; + X86_64 = 5; + MIPS = 6; + MIPS64 = 7; + } + AbiAlias alias = 1; +} + +message MultiAbi { + repeated Abi abi = 1; +} + +message Sanitizer { + enum SanitizerAlias { + NONE = 0; + HWADDRESS = 1; + } + SanitizerAlias alias = 1; +} + +message DeviceFeature { + string feature_name = 1; + // Equivalent of android:glEsVersion or android:version in <uses-feature>. + int32 feature_version = 2; +} + +// Targeting specific for directories under assets/. +message AssetsDirectoryTargeting { + AbiTargeting abi = 1; + GraphicsApiTargeting graphics_api = 2; + TextureCompressionFormatTargeting texture_compression_format = 3; + LanguageTargeting language = 4; +} + +// Targeting specific for directories under lib/. +message NativeDirectoryTargeting { + Abi abi = 1; + GraphicsApi graphics_api = 2; + TextureCompressionFormat texture_compression_format = 3; + Sanitizer sanitizer = 4; +} + +// Targeting specific for image files under apex/. +message ApexImageTargeting { + MultiAbiTargeting multi_abi = 1; +} + +message AbiTargeting { + repeated Abi value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated Abi alternatives = 2; +} + +message MultiAbiTargeting { + repeated MultiAbi value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated MultiAbi alternatives = 2; +} + +message ScreenDensityTargeting { + repeated ScreenDensity value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated ScreenDensity alternatives = 2; +} + +message LanguageTargeting { + // ISO-639: 2 or 3 letter language code. + repeated string value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated string alternatives = 2; +} + +message GraphicsApiTargeting { + repeated GraphicsApi value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated GraphicsApi alternatives = 2; +} + +message SdkVersionTargeting { + repeated SdkVersion value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated SdkVersion alternatives = 2; +} + +message TextureCompressionFormatTargeting { + repeated TextureCompressionFormat value = 1; + // Targeting of other sibling directories that were in the Bundle. + // For master splits this is targeting of other master splits. + repeated TextureCompressionFormat alternatives = 2; +} + +message SanitizerTargeting { + repeated Sanitizer value = 1; +} + +// Since other atom targeting messages have the "OR" semantic on values +// the DeviceFeatureTargeting represents only one device feature to retain +// that convention. +message DeviceFeatureTargeting { + DeviceFeature required_feature = 1; +} diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go new file mode 100644 index 000000000..e9a850ee8 --- /dev/null +++ b/cmd/extract_apks/main.go @@ -0,0 +1,544 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copies all the entries (APKs/APEXes) matching the target configuration from the given +// APK set into a zip file. Run it without arguments to see usage details. +package main + +import ( + "flag" + "fmt" + "io" + "log" + "math" + "os" + "regexp" + "strings" + + "github.com/golang/protobuf/proto" + + "android/soong/cmd/extract_apks/bundle_proto" + "android/soong/third_party/zip" +) + +type TargetConfig struct { + sdkVersion int32 + screenDpi map[android_bundle_proto.ScreenDensity_DensityAlias]bool + // Map holding <ABI alias>:<its sequence number in the flag> info. + abis map[android_bundle_proto.Abi_AbiAlias]int + allowPrereleased bool + stem string +} + +// An APK set is a zip archive. An entry 'toc.pb' describes its contents. +// It is a protobuf message BuildApkResult. +type Toc *android_bundle_proto.BuildApksResult + +type ApkSet struct { + path string + reader *zip.ReadCloser + entries map[string]*zip.File +} + +func newApkSet(path string) (*ApkSet, error) { + apkSet := &ApkSet{path: path, entries: make(map[string]*zip.File)} + var err error + if apkSet.reader, err = zip.OpenReader(apkSet.path); err != nil { + return nil, err + } + for _, f := range apkSet.reader.File { + apkSet.entries[f.Name] = f + } + return apkSet, nil +} + +func (apkSet *ApkSet) getToc() (Toc, error) { + var err error + tocFile, ok := apkSet.entries["toc.pb"] + if !ok { + return nil, fmt.Errorf("%s: APK set should have toc.pb entry", apkSet.path) + } + rc, err := tocFile.Open() + if err != nil { + return nil, err + } + bytes := make([]byte, tocFile.FileHeader.UncompressedSize64) + if _, err := rc.Read(bytes); err != io.EOF { + return nil, err + } + rc.Close() + buildApksResult := new(android_bundle_proto.BuildApksResult) + if err = proto.Unmarshal(bytes, buildApksResult); err != nil { + return nil, err + } + return buildApksResult, nil +} + +func (apkSet *ApkSet) close() { + apkSet.reader.Close() +} + +// Matchers for selection criteria + +type abiTargetingMatcher struct { + *android_bundle_proto.AbiTargeting +} + +func (m abiTargetingMatcher) matches(config TargetConfig) bool { + if m.AbiTargeting == nil { + return true + } + if _, ok := config.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE]; ok { + return true + } + // Find the one that appears first in the abis flags. + abiIdx := math.MaxInt32 + for _, v := range m.GetValue() { + if i, ok := config.abis[v.Alias]; ok { + if i < abiIdx { + abiIdx = i + } + } + } + if abiIdx == math.MaxInt32 { + return false + } + // See if any alternatives appear before the above one. + for _, a := range m.GetAlternatives() { + if i, ok := config.abis[a.Alias]; ok { + if i < abiIdx { + // There is a better alternative. Skip this one. + return false + } + } + } + return true +} + +type apkDescriptionMatcher struct { + *android_bundle_proto.ApkDescription +} + +func (m apkDescriptionMatcher) matches(config TargetConfig) bool { + return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config) +} + +type apkTargetingMatcher struct { + *android_bundle_proto.ApkTargeting +} + +func (m apkTargetingMatcher) matches(config TargetConfig) bool { + return m.ApkTargeting == nil || + (abiTargetingMatcher{m.AbiTargeting}.matches(config) && + languageTargetingMatcher{m.LanguageTargeting}.matches(config) && + screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) && + sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) && + multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config)) +} + +type languageTargetingMatcher struct { + *android_bundle_proto.LanguageTargeting +} + +func (m languageTargetingMatcher) matches(_ TargetConfig) bool { + if m.LanguageTargeting == nil { + return true + } + log.Fatal("language based entry selection is not implemented") + return false +} + +type moduleMetadataMatcher struct { + *android_bundle_proto.ModuleMetadata +} + +func (m moduleMetadataMatcher) matches(config TargetConfig) bool { + return m.ModuleMetadata == nil || + (m.GetDeliveryType() == android_bundle_proto.DeliveryType_INSTALL_TIME && + moduleTargetingMatcher{m.Targeting}.matches(config) && + !m.IsInstant) +} + +type moduleTargetingMatcher struct { + *android_bundle_proto.ModuleTargeting +} + +func (m moduleTargetingMatcher) matches(config TargetConfig) bool { + return m.ModuleTargeting == nil || + (sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) && + userCountriesTargetingMatcher{m.UserCountriesTargeting}.matches(config)) +} + +// A higher number means a higher priority. +// This order must be kept identical to bundletool's. +var multiAbiPriorities = map[android_bundle_proto.Abi_AbiAlias]int{ + android_bundle_proto.Abi_ARMEABI: 1, + android_bundle_proto.Abi_ARMEABI_V7A: 2, + android_bundle_proto.Abi_ARM64_V8A: 3, + android_bundle_proto.Abi_X86: 4, + android_bundle_proto.Abi_X86_64: 5, + android_bundle_proto.Abi_MIPS: 6, + android_bundle_proto.Abi_MIPS64: 7, +} + +type multiAbiTargetingMatcher struct { + *android_bundle_proto.MultiAbiTargeting +} + +func (t multiAbiTargetingMatcher) matches(config TargetConfig) bool { + if t.MultiAbiTargeting == nil { + return true + } + if _, ok := config.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE]; ok { + return true + } + // Find the one with the highest priority. + highestPriority := 0 + for _, v := range t.GetValue() { + for _, a := range v.GetAbi() { + if _, ok := config.abis[a.Alias]; ok { + if highestPriority < multiAbiPriorities[a.Alias] { + highestPriority = multiAbiPriorities[a.Alias] + } + } + } + } + if highestPriority == 0 { + return false + } + // See if there are any matching alternatives with a higher priority. + for _, v := range t.GetAlternatives() { + for _, a := range v.GetAbi() { + if _, ok := config.abis[a.Alias]; ok { + if highestPriority < multiAbiPriorities[a.Alias] { + // There's a better one. Skip this one. + return false + } + } + } + } + return true +} + +type screenDensityTargetingMatcher struct { + *android_bundle_proto.ScreenDensityTargeting +} + +func (m screenDensityTargetingMatcher) matches(config TargetConfig) bool { + if m.ScreenDensityTargeting == nil { + return true + } + if _, ok := config.screenDpi[android_bundle_proto.ScreenDensity_DENSITY_UNSPECIFIED]; ok { + return true + } + for _, v := range m.GetValue() { + switch x := v.GetDensityOneof().(type) { + case *android_bundle_proto.ScreenDensity_DensityAlias_: + if _, ok := config.screenDpi[x.DensityAlias]; ok { + return true + } + default: + log.Fatal("For screen density, only DPI name based entry selection (e.g. HDPI, XHDPI) is implemented") + } + } + return false +} + +type sdkVersionTargetingMatcher struct { + *android_bundle_proto.SdkVersionTargeting +} + +func (m sdkVersionTargetingMatcher) matches(config TargetConfig) bool { + const preReleaseVersion = 10000 + if m.SdkVersionTargeting == nil { + return true + } + if len(m.Value) > 1 { + log.Fatal(fmt.Sprintf("sdk_version_targeting should not have multiple values:%#v", m.Value)) + } + // Inspect only sdkVersionTargeting.Value. + // Even though one of the SdkVersionTargeting.Alternatives values may be + // better matching, we will select all of them + return m.Value[0].Min == nil || + m.Value[0].Min.Value <= config.sdkVersion || + (config.allowPrereleased && m.Value[0].Min.Value == preReleaseVersion) +} + +type textureCompressionFormatTargetingMatcher struct { + *android_bundle_proto.TextureCompressionFormatTargeting +} + +func (m textureCompressionFormatTargetingMatcher) matches(_ TargetConfig) bool { + if m.TextureCompressionFormatTargeting == nil { + return true + } + log.Fatal("texture based entry selection is not implemented") + return false +} + +type userCountriesTargetingMatcher struct { + *android_bundle_proto.UserCountriesTargeting +} + +func (m userCountriesTargetingMatcher) matches(_ TargetConfig) bool { + if m.UserCountriesTargeting == nil { + return true + } + log.Fatal("country based entry selection is not implemented") + return false +} + +type variantTargetingMatcher struct { + *android_bundle_proto.VariantTargeting +} + +func (m variantTargetingMatcher) matches(config TargetConfig) bool { + if m.VariantTargeting == nil { + return true + } + return sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) && + abiTargetingMatcher{m.AbiTargeting}.matches(config) && + multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config) && + screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) && + textureCompressionFormatTargetingMatcher{m.TextureCompressionFormatTargeting}.matches(config) +} + +type SelectionResult struct { + moduleName string + entries []string +} + +// Return all entries matching target configuration +func selectApks(toc Toc, targetConfig TargetConfig) SelectionResult { + var result SelectionResult + for _, variant := range (*toc).GetVariant() { + if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig)) { + continue + } + for _, as := range variant.GetApkSet() { + if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) { + continue + } + for _, apkdesc := range as.GetApkDescription() { + if (apkDescriptionMatcher{apkdesc}).matches(targetConfig) { + result.entries = append(result.entries, apkdesc.GetPath()) + // TODO(asmundak): As it turns out, moduleName which we get from + // the ModuleMetadata matches the module names of the generated + // entry paths just by coincidence, only for the split APKs. We + // need to discuss this with bundletool folks. + result.moduleName = as.GetModuleMetadata().GetName() + } + } + // we allow only a single module, so bail out here if we found one + if result.moduleName != "" { + return result + } + } + } + return result +} + +type Zip2ZipWriter interface { + CopyFrom(file *zip.File, name string) error +} + +// Writes out selected entries, renaming them as needed +func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig, + writer Zip2ZipWriter) error { + // Renaming rules: + // splits/MODULE-master.apk to STEM.apk + // else + // splits/MODULE-*.apk to STEM>-$1.apk + // TODO(asmundak): + // add more rules, for .apex files + renameRules := []struct { + rex *regexp.Regexp + repl string + }{ + { + regexp.MustCompile(`^.*/` + selected.moduleName + `-master\.apk$`), + config.stem + `.apk`, + }, + { + regexp.MustCompile(`^.*/` + selected.moduleName + `(-.*\.apk)$`), + config.stem + `$1`, + }, + { + regexp.MustCompile(`^universal\.apk$`), + config.stem + ".apk", + }, + } + renamer := func(path string) (string, bool) { + for _, rr := range renameRules { + if rr.rex.MatchString(path) { + return rr.rex.ReplaceAllString(path, rr.repl), true + } + } + return "", false + } + + entryOrigin := make(map[string]string) // output entry to input entry + for _, apk := range selected.entries { + apkFile, ok := apkSet.entries[apk] + if !ok { + return fmt.Errorf("TOC refers to an entry %s which does not exist", apk) + } + inName := apkFile.Name + outName, ok := renamer(inName) + if !ok { + log.Fatalf("selected an entry with unexpected name %s", inName) + } + if origin, ok := entryOrigin[inName]; ok { + log.Fatalf("selected entries %s and %s will have the same output name %s", + origin, inName, outName) + } + entryOrigin[outName] = inName + if err := writer.CopyFrom(apkFile, outName); err != nil { + return err + } + } + return nil +} + +func (apkSet *ApkSet) extractAndCopySingle(selected SelectionResult, outFile *os.File) error { + if len(selected.entries) != 1 { + return fmt.Errorf("Too many matching entries for extract-single:\n%v", selected.entries) + } + apk, ok := apkSet.entries[selected.entries[0]] + if !ok { + return fmt.Errorf("Couldn't find apk path %s", selected.entries[0]) + } + inputReader, _ := apk.Open() + _, err := io.Copy(outFile, inputReader) + return err +} + +// Arguments parsing +var ( + outputFile = flag.String("o", "", "output file containing extracted entries") + targetConfig = TargetConfig{ + screenDpi: map[android_bundle_proto.ScreenDensity_DensityAlias]bool{}, + abis: map[android_bundle_proto.Abi_AbiAlias]int{}, + } + extractSingle = flag.Bool("extract-single", false, + "extract a single target and output it uncompressed. only available for standalone apks and apexes.") +) + +// Parse abi values +type abiFlagValue struct { + targetConfig *TargetConfig +} + +func (a abiFlagValue) String() string { + return "all" +} + +func (a abiFlagValue) Set(abiList string) error { + for i, abi := range strings.Split(abiList, ",") { + v, ok := android_bundle_proto.Abi_AbiAlias_value[abi] + if !ok { + return fmt.Errorf("bad ABI value: %q", abi) + } + targetConfig.abis[android_bundle_proto.Abi_AbiAlias(v)] = i + } + return nil +} + +// Parse screen density values +type screenDensityFlagValue struct { + targetConfig *TargetConfig +} + +func (s screenDensityFlagValue) String() string { + return "none" +} + +func (s screenDensityFlagValue) Set(densityList string) error { + if densityList == "none" { + return nil + } + if densityList == "all" { + targetConfig.screenDpi[android_bundle_proto.ScreenDensity_DENSITY_UNSPECIFIED] = true + return nil + } + for _, density := range strings.Split(densityList, ",") { + v, found := android_bundle_proto.ScreenDensity_DensityAlias_value[density] + if !found { + return fmt.Errorf("bad screen density value: %q", density) + } + targetConfig.screenDpi[android_bundle_proto.ScreenDensity_DensityAlias(v)] = true + } + return nil +} + +func processArgs() { + flag.Usage = func() { + fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> -sdk-version value -abis value `+ + `-screen-densities value {-stem value | -extract-single} [-allow-prereleased] <APK set>`) + flag.PrintDefaults() + os.Exit(2) + } + version := flag.Uint("sdk-version", 0, "SDK version") + flag.Var(abiFlagValue{&targetConfig}, "abis", + "comma-separated ABIs list of ARMEABI ARMEABI_V7A ARM64_V8A X86 X86_64 MIPS MIPS64") + flag.Var(screenDensityFlagValue{&targetConfig}, "screen-densities", + "'all' or comma-separated list of screen density names (NODPI LDPI MDPI TVDPI HDPI XHDPI XXHDPI XXXHDPI)") + flag.BoolVar(&targetConfig.allowPrereleased, "allow-prereleased", false, + "allow prereleased") + flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name in the output zip file") + flag.Parse() + if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 || (targetConfig.stem == "" && !*extractSingle) { + flag.Usage() + } + targetConfig.sdkVersion = int32(*version) + +} + +func main() { + processArgs() + var toc Toc + apkSet, err := newApkSet(flag.Arg(0)) + if err == nil { + defer apkSet.close() + toc, err = apkSet.getToc() + } + if err != nil { + log.Fatal(err) + } + sel := selectApks(toc, targetConfig) + if len(sel.entries) == 0 { + log.Fatalf("there are no entries for the target configuration: %#v", targetConfig) + } + + outFile, err := os.Create(*outputFile) + if err != nil { + log.Fatal(err) + } + defer outFile.Close() + + if *extractSingle { + err = apkSet.extractAndCopySingle(sel, outFile) + } else { + writer := zip.NewWriter(outFile) + defer func() { + if err := writer.Close(); err != nil { + log.Fatal(err) + } + }() + err = apkSet.writeApks(sel, targetConfig, writer) + } + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go new file mode 100644 index 000000000..bdd4becce --- /dev/null +++ b/cmd/extract_apks/main_test.go @@ -0,0 +1,477 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "reflect" + "testing" + + bp "android/soong/cmd/extract_apks/bundle_proto" + "android/soong/third_party/zip" +) + +type testConfigDesc struct { + name string + targetConfig TargetConfig + expected SelectionResult +} + +type testDesc struct { + protoText string + configs []testConfigDesc +} + +func TestSelectApks_ApkSet(t *testing.T) { + testCases := []testDesc{ + { + protoText: ` +variant { + targeting { + sdk_version_targeting { + value { min { value: 29 } } } } + apk_set { + module_metadata { + name: "base" targeting {} delivery_type: INSTALL_TIME } + apk_description { + targeting { + screen_density_targeting { + value { density_alias: LDPI } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-ldpi.apk" + split_apk_metadata { split_id: "config.ldpi" } } + apk_description { + targeting { + screen_density_targeting { + value { density_alias: MDPI } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-mdpi.apk" + split_apk_metadata { split_id: "config.mdpi" } } + apk_description { + targeting { + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-master.apk" + split_apk_metadata { is_master_split: true } } + apk_description { + targeting { + abi_targeting { + value { alias: ARMEABI_V7A } + alternatives { alias: ARM64_V8A } + alternatives { alias: X86 } + alternatives { alias: X86_64 } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-armeabi_v7a.apk" + split_apk_metadata { split_id: "config.armeabi_v7a" } } + apk_description { + targeting { + abi_targeting { + value { alias: ARM64_V8A } + alternatives { alias: ARMEABI_V7A } + alternatives { alias: X86 } + alternatives { alias: X86_64 } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-arm64_v8a.apk" + split_apk_metadata { split_id: "config.arm64_v8a" } } + apk_description { + targeting { + abi_targeting { + value { alias: X86 } + alternatives { alias: ARMEABI_V7A } + alternatives { alias: ARM64_V8A } + alternatives { alias: X86_64 } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-x86.apk" + split_apk_metadata { split_id: "config.x86" } } + apk_description { + targeting { + abi_targeting { + value { alias: X86_64 } + alternatives { alias: ARMEABI_V7A } + alternatives { alias: ARM64_V8A } + alternatives { alias: X86 } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-x86_64.apk" + split_apk_metadata { split_id: "config.x86_64" } } } +} +bundletool { + version: "0.10.3" } + +`, + configs: []testConfigDesc{ + { + name: "one", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_DENSITY_UNSPECIFIED: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARMEABI_V7A: 0, + bp.Abi_ARM64_V8A: 1, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "splits/base-ldpi.apk", + "splits/base-mdpi.apk", + "splits/base-master.apk", + "splits/base-armeabi_v7a.apk", + }, + }, + }, + { + name: "two", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_LDPI: true, + }, + abis: map[bp.Abi_AbiAlias]int{}, + }, + expected: SelectionResult{ + "base", + []string{ + "splits/base-ldpi.apk", + "splits/base-master.apk", + }, + }, + }, + { + name: "three", + targetConfig: TargetConfig{ + sdkVersion: 20, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_LDPI: true, + }, + abis: map[bp.Abi_AbiAlias]int{}, + }, + expected: SelectionResult{ + "", + nil, + }, + }, + { + name: "four", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_MDPI: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARM64_V8A: 0, + bp.Abi_ARMEABI_V7A: 1, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "splits/base-mdpi.apk", + "splits/base-master.apk", + "splits/base-arm64_v8a.apk", + }, + }, + }, + }, + }, + { + protoText: ` +variant { + targeting { + sdk_version_targeting { + value { min { value: 10000 } } } } + apk_set { + module_metadata { + name: "base" targeting {} delivery_type: INSTALL_TIME } + apk_description { + targeting { + sdk_version_targeting { + value { min { value: 21 } } } } + path: "splits/base-master.apk" + split_apk_metadata { is_master_split: true } } } }`, + configs: []testConfigDesc{ + { + name: "Prerelease", + targetConfig: TargetConfig{ + sdkVersion: 30, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{}, + abis: map[bp.Abi_AbiAlias]int{}, + allowPrereleased: true, + }, + expected: SelectionResult{ + "base", + []string{"splits/base-master.apk"}, + }, + }, + }, + }, + { + protoText: ` +variant { + targeting { + sdk_version_targeting { + value { min { value: 29 } } } } + apk_set { + module_metadata { + name: "base" targeting {} delivery_type: INSTALL_TIME } + apk_description { + targeting {} + path: "universal.apk" + standalone_apk_metadata { fused_module_name: "base" } } } }`, + configs: []testConfigDesc{ + { + name: "Universal", + targetConfig: TargetConfig{sdkVersion: 30}, + expected: SelectionResult{ + "base", + []string{"universal.apk"}, + }, + }, + }, + }, + } + for _, testCase := range testCases { + var toc bp.BuildApksResult + if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil { + t.Fatal(err) + } + for _, config := range testCase.configs { + actual := selectApks(&toc, config.targetConfig) + if !reflect.DeepEqual(config.expected, actual) { + t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual) + } + } + } +} + +func TestSelectApks_ApexSet(t *testing.T) { + testCases := []testDesc{ + { + protoText: ` +variant { + targeting { + sdk_version_targeting { + value { min { value: 29 } } } } + apk_set { + module_metadata { + name: "base" targeting {} delivery_type: INSTALL_TIME } + apk_description { + targeting { + multi_abi_targeting { + value { abi { alias: ARMEABI_V7A } } + alternatives { abi { alias: ARM64_V8A } } + alternatives { abi { alias: X86 } } + alternatives { abi { alias: X86_64 } } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "standalones/standalone-armeabi_v7a.apex" + apex_apk_metadata { } } + apk_description { + targeting { + multi_abi_targeting { + value { abi { alias: ARM64_V8A } } + alternatives { abi { alias: ARMEABI_V7A } } + alternatives { abi { alias: X86 } } + alternatives { abi { alias: X86_64 } } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "standalones/standalone-arm64_v8a.apex" + apex_apk_metadata { } } + apk_description { + targeting { + multi_abi_targeting { + value { abi { alias: X86 } } + alternatives { abi { alias: ARMEABI_V7A } } + alternatives { abi { alias: ARM64_V8A } } + alternatives { abi { alias: X86_64 } } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "standalones/standalone-x86.apex" + apex_apk_metadata { } } + apk_description { + targeting { + multi_abi_targeting { + value { abi { alias: X86_64 } } + alternatives { abi { alias: ARMEABI_V7A } } + alternatives { abi { alias: ARM64_V8A } } + alternatives { abi { alias: X86 } } } + sdk_version_targeting { + value { min { value: 21 } } } } + path: "standalones/standalone-x86_64.apex" + apex_apk_metadata { } } } +} +bundletool { + version: "0.10.3" } + +`, + configs: []testConfigDesc{ + { + name: "order matches priorities", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_DENSITY_UNSPECIFIED: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARM64_V8A: 0, + bp.Abi_ARMEABI_V7A: 1, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "standalones/standalone-arm64_v8a.apex", + }, + }, + }, + { + name: "order doesn't match priorities", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_DENSITY_UNSPECIFIED: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARMEABI_V7A: 0, + bp.Abi_ARM64_V8A: 1, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "standalones/standalone-arm64_v8a.apex", + }, + }, + }, + { + name: "single choice", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_DENSITY_UNSPECIFIED: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARMEABI_V7A: 0, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "standalones/standalone-armeabi_v7a.apex", + }, + }, + }, + { + name: "cross platform", + targetConfig: TargetConfig{ + sdkVersion: 29, + screenDpi: map[bp.ScreenDensity_DensityAlias]bool{ + bp.ScreenDensity_DENSITY_UNSPECIFIED: true, + }, + abis: map[bp.Abi_AbiAlias]int{ + bp.Abi_ARM64_V8A: 0, + bp.Abi_MIPS64: 1, + bp.Abi_X86: 2, + }, + }, + expected: SelectionResult{ + "base", + []string{ + "standalones/standalone-x86.apex", + }, + }, + }, + }, + }, + } + for _, testCase := range testCases { + var toc bp.BuildApksResult + if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil { + t.Fatal(err) + } + for _, config := range testCase.configs { + actual := selectApks(&toc, config.targetConfig) + if !reflect.DeepEqual(config.expected, actual) { + t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual) + } + } + } +} + +type testZip2ZipWriter struct { + entries map[string]string +} + +func (w testZip2ZipWriter) CopyFrom(file *zip.File, out string) error { + if x, ok := w.entries[out]; ok { + return fmt.Errorf("%s and %s both write to %s", x, file.Name, out) + } + w.entries[out] = file.Name + return nil +} + +type testCaseWriteZip struct { + name string + moduleName string + stem string + // what we write from what + expected map[string]string +} + +func TestWriteZip(t *testing.T) { + testCases := []testCaseWriteZip{ + { + name: "splits", + moduleName: "mybase", + stem: "Foo", + expected: map[string]string{ + "Foo.apk": "splits/mybase-master.apk", + "Foo-xhdpi.apk": "splits/mybase-xhdpi.apk", + }, + }, + { + name: "universal", + moduleName: "base", + stem: "Bar", + expected: map[string]string{ + "Bar.apk": "universal.apk", + }, + }, + } + for _, testCase := range testCases { + apkSet := ApkSet{entries: make(map[string]*zip.File)} + sel := SelectionResult{moduleName: testCase.moduleName} + for _, in := range testCase.expected { + apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}} + sel.entries = append(sel.entries, in) + } + writer := testZip2ZipWriter{make(map[string]string)} + config := TargetConfig{stem: testCase.stem} + if err := apkSet.writeApks(sel, config, writer); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(testCase.expected, writer.entries) { + t.Errorf("expected %v, got %v", testCase.expected, writer.entries) + } + } +} diff --git a/cmd/host_bionic_inject/host_bionic_inject.go b/cmd/host_bionic_inject/host_bionic_inject.go index f7163d7e3..629f6cc14 100644 --- a/cmd/host_bionic_inject/host_bionic_inject.go +++ b/cmd/host_bionic_inject/host_bionic_inject.go @@ -105,7 +105,9 @@ func parseElf(r io.ReaderAt, linker *elf.File) (uint64, error) { err = checkLinker(file, linker, symbols) if err != nil { - return 0, err + return 0, fmt.Errorf("Linker executable failed verification against app embedded linker: %s\n"+ + "linker might not be in sync with crtbegin_dynamic.o.", + err) } start, err := findSymbol(symbols, "_start") diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go index 191b919e9..d341b8c10 100644 --- a/cmd/pom2bp/pom2bp.go +++ b/cmd/pom2bp/pom2bp.go @@ -213,10 +213,14 @@ func (p Pom) IsHostAndDeviceModule() bool { return hostAndDeviceModuleNames.IsHostAndDeviceModule(p.GroupId, p.ArtifactId) } +func (p Pom) IsHostOnly() bool { + return p.IsHostModule() && !p.IsHostAndDeviceModule() +} + func (p Pom) ModuleType() string { if p.IsAar() { return "android_library" - } else if p.IsHostModule() && !p.IsHostAndDeviceModule() { + } else if p.IsHostOnly() { return "java_library_host" } else { return "java_library_static" @@ -226,7 +230,7 @@ func (p Pom) ModuleType() string { func (p Pom) ImportModuleType() string { if p.IsAar() { return "android_library_import" - } else if p.IsHostModule() && !p.IsHostAndDeviceModule() { + } else if p.IsHostOnly() { return "java_import_host" } else { return "java_import" @@ -366,6 +370,12 @@ var bpTemplate = template.Must(template.New("bp").Parse(` {{- if .IsHostAndDeviceModule}} host_supported: true, {{- end}} + {{- if not .IsHostOnly}} + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + {{- end}} {{- if .IsAar}} min_sdk_version: "{{.MinSdkVersion}}", static_libs: [ @@ -401,6 +411,12 @@ var bpDepsTemplate = template.Must(template.New("bp").Parse(` {{- if .IsHostAndDeviceModule}} host_supported: true, {{- end}} + {{- if not .IsHostOnly}} + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + {{- end}} {{- if .IsAar}} min_sdk_version: "{{.MinSdkVersion}}", static_libs: [ @@ -431,9 +447,17 @@ var bpDepsTemplate = template.Must(template.New("bp").Parse(` {{- if .IsHostAndDeviceModule}} host_supported: true, {{- end}} + {{- if not .IsHostOnly}} + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + {{- end}} {{- if .IsAar}} min_sdk_version: "{{.MinSdkVersion}}", manifest: "manifests/{{.BpName}}/AndroidManifest.xml", + {{- else if not .IsHostOnly}} + min_sdk_version: "24", {{- end}} {{- end}} static_libs: [ diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index bd1a9edfa..905f2068b 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -18,12 +18,7 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" - "strconv" - "strings" - "syscall" - "time" "github.com/google/blueprint/bootstrap" @@ -55,42 +50,7 @@ func newNameResolver(config android.Config) *android.NameResolver { } func main() { - if android.SoongDelveListen != "" { - if android.SoongDelvePath == "" { - fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") - os.Exit(1) - } - pid := strconv.Itoa(os.Getpid()) - cmd := []string{android.SoongDelvePath, - "attach", pid, - "--headless", - "-l", android.SoongDelveListen, - "--api-version=2", - "--accept-multiclient", - "--log", - } - - fmt.Println("Starting", strings.Join(cmd, " ")) - dlv := exec.Command(cmd[0], cmd[1:]...) - dlv.Stdout = os.Stdout - dlv.Stderr = os.Stderr - dlv.Stdin = nil - - // Put dlv into its own process group so we can kill it and the child process it starts. - dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - - err := dlv.Start() - if err != nil { - // Print the error starting dlv and continue. - fmt.Println(err) - } else { - // Kill the process group for dlv when soong_build exits. - defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL) - // Wait to give dlv a chance to connect and pause the process. - time.Sleep(time.Second) - } - } - + android.ReexecWithDelveMaybe() flag.Parse() // The top-level Blueprints file is passed as the first argument. diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index f1dde9c22..de696da10 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -82,7 +82,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(global.BootJars), module.Name) { + if !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) { appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) && !module.NoCreateAppImage @@ -104,7 +104,7 @@ 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(p); jar == module.Name { + if _, jar := android.SplitApexJarPair(ctx, p); jar == module.Name { return true } } @@ -113,7 +113,7 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo // 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(global.BootJars), module.Name) && + if global.OnlyPreoptBootImageAndSystemServer && !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) && !contains(global.SystemServerJars, module.Name) && !module.PreoptExtractedApk { return true } @@ -241,6 +241,10 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g var conditionalClassLoaderContextHost29 android.Paths var conditionalClassLoaderContextTarget29 []string + // Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 30 + var conditionalClassLoaderContextHost30 android.Paths + var conditionalClassLoaderContextTarget30 []string + // A flag indicating if the '&' class loader context is used. unknownClassLoaderContext := false @@ -256,28 +260,22 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g filepath.Join("/system/framework", l+".jar")) } + // org.apache.http.legacy contains classes that were in the default classpath until API 28. + // If the targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly + // depend on org.apache.http.legacy, then implicitly add it to the classpath for dexpreopt. const httpLegacy = "org.apache.http.legacy" - const httpLegacyImpl = "org.apache.http.legacy.impl" - - // org.apache.http.legacy contains classes that were in the default classpath until API 28. If the - // targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly depend on - // org.apache.http.legacy, then implicitly add the classes to the classpath for dexpreopt. One the - // device the classes will be in a file called org.apache.http.legacy.impl.jar. - module.LibraryPaths[httpLegacyImpl] = module.LibraryPaths[httpLegacy] - - if !contains(module.UsesLibraries, httpLegacy) && !contains(module.PresentOptionalUsesLibraries, httpLegacy) { + if !contains(usesLibs, httpLegacy) { conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28, - pathForLibrary(module, httpLegacyImpl)) + pathForLibrary(module, httpLegacy)) conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28, - filepath.Join("/system/framework", httpLegacyImpl+".jar")) + filepath.Join("/system/framework", httpLegacy+".jar")) } - const hidlBase = "android.hidl.base-V1.0-java" - const hidlManager = "android.hidl.manager-V1.0-java" - // android.hidl.base-V1.0-java and android.hidl.manager-V1.0 contain classes that were in the default // classpath until API 29. If the targetSdkVersion in the manifest or APK is < 29 then implicitly add // the classes to the classpath for dexpreopt. + const hidlBase = "android.hidl.base-V1.0-java" + const hidlManager = "android.hidl.manager-V1.0-java" conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29, pathForLibrary(module, hidlManager)) conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29, @@ -286,6 +284,17 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g pathForLibrary(module, hidlBase)) conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29, filepath.Join("/system/framework", hidlBase+".jar")) + + // android.test.base contains classes that were in the default classpath until API 30. + // If the targetSdkVersion in the manifest or APK is < 30 then implicitly add it to the + // classpath for dexpreopt. + const testBase = "android.test.base" + if !contains(usesLibs, testBase) { + conditionalClassLoaderContextHost30 = append(conditionalClassLoaderContextHost30, + pathForLibrary(module, testBase)) + conditionalClassLoaderContextTarget30 = append(conditionalClassLoaderContextTarget30, + filepath.Join("/system/framework", testBase+".jar")) + } } else if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 { // System server jars should be dexpreopted together: class loader context of each jar // should include all preceding jars on the system server classpath. @@ -351,6 +360,11 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g Implicits(conditionalClassLoaderContextHost29) rule.Command().Textf(`conditional_target_libs_29="%s"`, strings.Join(conditionalClassLoaderContextTarget29, " ")) + rule.Command().Textf(`conditional_host_libs_30="%s"`, + strings.Join(conditionalClassLoaderContextHost30.Strings(), " ")). + Implicits(conditionalClassLoaderContextHost30) + rule.Command().Textf(`conditional_target_libs_30="%s"`, + strings.Join(conditionalClassLoaderContextTarget30, " ")) rule.Command().Text("source").Tool(globalSoong.ConstructContext).Input(module.DexPath) } @@ -561,8 +575,8 @@ func makefileMatch(pattern, s string) bool { } // Expected format for apexJarValue = <apex name>:<jar name> -func GetJarLocationFromApexJarPair(apexJarValue string) string { - apex, jar := android.SplitApexJarPair(apexJarValue) +func GetJarLocationFromApexJarPair(ctx android.PathContext, apexJarValue string) string { + apex, jar := android.SplitApexJarPair(ctx, apexJarValue) return filepath.Join("/apex", apex, "javalib", jar+".jar") } @@ -573,7 +587,7 @@ var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServ func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string { return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} { return android.RemoveListFromList(global.SystemServerJars, - android.GetJarsFromApexJarPairs(global.UpdatableSystemServerJars)) + android.GetJarsFromApexJarPairs(ctx, global.UpdatableSystemServerJars)) }).([]string) } diff --git a/genrule/genrule.go b/genrule/genrule.go index fe877fe8d..f6904f195 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -144,6 +144,9 @@ type Module struct { subName string subDir string + + // Collect the module directory for IDE info in java/jdeps.go. + modulePaths []string } type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask @@ -190,6 +193,9 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { g.subName = ctx.ModuleSubDir() + // Collect the module directory for IDE info in java/jdeps.go. + g.modulePaths = append(g.modulePaths, ctx.ModuleDir()) + if len(g.properties.Export_include_dirs) > 0 { for _, dir := range g.properties.Export_include_dirs { g.exportedIncludeDirs = append(g.exportedIncludeDirs, @@ -529,6 +535,7 @@ func (g *Module) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Deps = append(dpInfo.Deps, src) } } + dpInfo.Paths = append(dpInfo.Paths, g.modulePaths...) } func (g *Module) AndroidMk() android.AndroidMkData { diff --git a/java/aar.go b/java/aar.go index 6e3b9e6d3..c8daf835b 100644 --- a/java/aar.go +++ b/java/aar.go @@ -379,8 +379,11 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati sharedLibs = append(sharedLibs, exportPackage) } - if _, ok := module.(SdkLibraryDependency); ok { - sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module)) + // If the module is (or possibly could be) a component of a java_sdk_library + // (including the java_sdk_library) itself then append any implicit sdk library + // names to the list of sdk libraries to be added to the manifest. + if component, ok := module.(SdkLibraryComponentDependency); ok { + sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) } case frameworkResTag: @@ -513,6 +516,7 @@ func AndroidLibraryFactory() android.Module { module.androidLibraryProperties.BuildAAR = true + android.InitApexModule(module) InitJavaModule(module, android.DeviceSupported) return module } @@ -537,8 +541,12 @@ type AARImportProperties struct { type AARImport struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase prebuilt android.Prebuilt + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties AARImportProperties classpathFile android.WritablePath @@ -742,6 +750,10 @@ func (a *AARImport) SrcJarArgs() ([]string, android.Paths) { return nil, nil } +func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { + return a.depIsInSameApex(ctx, dep) +} + var _ android.PrebuiltInterface = (*Import)(nil) // android_library_import imports an `.aar` file into the build graph as if it was built with android_library. @@ -754,6 +766,7 @@ func AARImportFactory() android.Module { module.AddProperties(&module.properties) android.InitPrebuiltModule(module, &module.properties.Aars) + android.InitApexModule(module) InitJavaModule(module, android.DeviceSupported) return module } diff --git a/java/androidmk.go b/java/androidmk.go index 2c2919218..62cf169fa 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -69,7 +69,26 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) { hideFromMake = true } - if !hideFromMake { + if hideFromMake { + // May still need to add some additional dependencies. This will be called + // once for the platform variant (even if it is not being used) and once each + // for the APEX specific variants. In order to avoid adding the dependency + // multiple times only add it for the platform variant. + checkedModulePaths := library.additionalCheckedModules + if library.IsForPlatform() && len(checkedModulePaths) != 0 { + mainEntries = android.AndroidMkEntries{ + Class: "FAKE", + // Need at least one output file in order for this to take effect. + OutputFile: android.OptionalPathForPath(checkedModulePaths[0]), + Include: "$(BUILD_PHONY_PACKAGE)", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...) + }, + }, + } + } + } else { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", DistFile: android.OptionalPathForPath(library.distFile), @@ -211,6 +230,11 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries { } func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries { + if !prebuilt.IsForPlatform() { + return []android.AndroidMkEntries{{ + Disabled: true, + }} + } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", OutputFile: android.OptionalPathForPath(prebuilt.classpathFile), @@ -416,6 +440,11 @@ func (a *AndroidTestHelperApp) AndroidMkEntries() []android.AndroidMkEntries { } func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries { + if !a.IsForPlatform() { + return []android.AndroidMkEntries{{ + Disabled: true, + }} + } entriesList := a.Library.AndroidMkEntries() entries := &entriesList[0] @@ -502,14 +531,12 @@ func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries { fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:", ddoc.checkLastReleasedApiTimestamp.String()) - if ddoc.Name() == "api-stubs-docs" || ddoc.Name() == "system-api-stubs-docs" { - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - ddoc.checkLastReleasedApiTimestamp.String()) + fmt.Fprintln(w, ".PHONY: checkapi") + fmt.Fprintln(w, "checkapi:", + ddoc.checkLastReleasedApiTimestamp.String()) - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - } + fmt.Fprintln(w, ".PHONY: droidcore") + fmt.Fprintln(w, "droidcore: checkapi") } }, }, @@ -681,3 +708,20 @@ func (r *RuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEntries { }, }} } + +func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{ + android.AndroidMkEntries{ + Class: "APPS", + OutputFile: android.OptionalPathForPath(apkSet.packedOutput), + Include: "$(BUILD_SYSTEM)/soong_android_app_set.mk", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged()) + entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile) + entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...) + }, + }, + }, + } +} diff --git a/java/app.go b/java/app.go index f1af2adf4..a45ab6f99 100755 --- a/java/app.go +++ b/java/app.go @@ -20,6 +20,7 @@ import ( "path/filepath" "reflect" "sort" + "strconv" "strings" "github.com/google/blueprint" @@ -49,6 +50,127 @@ func RegisterAppBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory) ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory) ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory) + ctx.RegisterModuleType("android_app_set", AndroidApkSetFactory) +} + +type AndroidAppSetProperties struct { + // APK Set path + Set *string + + // Specifies that this app should be installed to the priv-app directory, + // where the system will grant it additional privileges not available to + // normal apps. + Privileged *bool + + // APKs in this set use prerelease SDK version + Prerelease *bool + + // Names of modules to be overridden. Listed modules can only be other apps + // (in Make or Soong). + Overrides []string +} + +type AndroidAppSet struct { + android.ModuleBase + android.DefaultableModuleBase + prebuilt android.Prebuilt + + properties AndroidAppSetProperties + packedOutput android.WritablePath + masterFile string +} + +func (as *AndroidAppSet) Name() string { + return as.prebuilt.Name(as.ModuleBase.Name()) +} + +func (as *AndroidAppSet) IsInstallable() bool { + return true +} + +func (as *AndroidAppSet) Prebuilt() *android.Prebuilt { + return &as.prebuilt +} + +func (as *AndroidAppSet) Privileged() bool { + return Bool(as.properties.Privileged) +} + +var TargetCpuAbi = map[string]string{ + "arm": "ARMEABI_V7A", + "arm64": "ARM64_V8A", + "x86": "X86", + "x86_64": "X86_64", +} + +func SupportedAbis(ctx android.ModuleContext) []string { + abiName := func(archVar string, deviceArch string) string { + if abi, found := TargetCpuAbi[deviceArch]; found { + return abi + } + ctx.ModuleErrorf("Invalid %s: %s", archVar, deviceArch) + return "BAD_ABI" + } + + result := []string{abiName("TARGET_ARCH", ctx.DeviceConfig().DeviceArch())} + if s := ctx.DeviceConfig().DeviceSecondaryArch(); s != "" { + result = append(result, abiName("TARGET_2ND_ARCH", s)) + } + return result +} + +func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { + as.packedOutput = android.PathForModuleOut(ctx, "extracted.zip") + // We are assuming here that the master file in the APK + // set has `.apk` suffix. If it doesn't the build will fail. + // APK sets containing APEX files are handled elsewhere. + as.masterFile = ctx.ModuleName() + ".apk" + screenDensities := "all" + if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 { + screenDensities = strings.ToUpper(strings.Join(dpis, ",")) + } + // TODO(asmundak): handle locales. + // TODO(asmundak): do we support device features + ctx.Build(pctx, + android.BuildParams{ + Rule: extractMatchingApks, + Description: "Extract APKs from APK set", + Output: as.packedOutput, + Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)}, + Args: map[string]string{ + "abis": strings.Join(SupportedAbis(ctx), ","), + "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)), + "screen-densities": screenDensities, + "sdk-version": ctx.Config().PlatformSdkVersion(), + "stem": ctx.ModuleName(), + }, + }) + // TODO(asmundak): add this (it's wrong now, will cause copying extracted.zip) + /* + var installDir android.InstallPath + if Bool(as.properties.Privileged) { + installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName()) + } else if ctx.InstallInTestcases() { + installDir = android.PathForModuleInstall(ctx, as.BaseModuleName(), ctx.DeviceConfig().DeviceArch()) + } else { + installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName()) + } + ctx.InstallFile(installDir, as.masterFile", as.packedOutput) + */ +} + +// android_app_set extracts a set of APKs based on the target device +// configuration and installs this set as "split APKs". +// The set will always contain `base-master.apk` and every APK built +// to the target device. All density-specific APK will be included, too, +// unless PRODUCT_APPT_PREBUILT_DPI is defined (should contain comma-sepearated +// list of density names (LDPI, MDPI, HDPI, etc.) +func AndroidApkSetFactory() android.Module { + module := &AndroidAppSet{} + module.AddProperties(&module.properties) + InitJavaModule(module, android.DeviceSupported) + android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set") + return module } // AndroidManifest.xml merging @@ -129,6 +251,9 @@ type overridableAppProperties struct { // or an android_app_certificate module name in the form ":module". Certificate *string + // Name of the signing certificate lineage file. + Lineage *string + // the package name of this app. The package name in the manifest file is used if one was not given. Package_name *string @@ -249,7 +374,10 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { // If the app builds against an Android SDK use the SDK variant of JNI dependencies // unless jni_uses_platform_apis is set. - if (usesSDK && !Bool(a.appProperties.Jni_uses_platform_apis)) || + // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already + // have stable APIs through the VNDK. + if (usesSDK && !a.RequiresStableAPIs(ctx) && + !Bool(a.appProperties.Jni_uses_platform_apis)) || Bool(a.appProperties.Jni_uses_sdk_apis) { variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) } @@ -286,19 +414,47 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { - if Bool(a.appProperties.Updatable) { + if a.Updatable() { if !a.sdkVersion().stable() { ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion()) } if String(a.deviceProperties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") } + if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { + a.checkJniLibsSdkVersion(ctx, minSdkVersion) + } else { + ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) + } } a.checkPlatformAPI(ctx) a.checkSdkVersions(ctx) } +// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. +// This check is enforced for "updatable" APKs (including APK-in-APEX). +// b/155209650: until min_sdk_version is properly supported, use sdk_version instead. +// because, sdk_version is overridden by min_sdk_version (if set as smaller) +// and linkType is checked with dependencies so we can be sure that the whole dependency tree +// will meet the requirements. +func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) { + // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() + ctx.VisitDirectDeps(func(m android.Module) { + if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { + return + } + dep, _ := m.(*cc.Module) + jniSdkVersion, err := android.ApiStrToNum(ctx, dep.SdkVersion()) + if err != nil || int(minSdkVersion) < jniSdkVersion { + ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", + dep.SdkVersion(), minSdkVersion, ctx.ModuleName()) + return + } + + }) +} + // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { @@ -412,16 +568,17 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { installDir = filepath.Join("app", a.installApkName) } a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") - a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx) - + if a.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) + } + a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries() a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx) a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx) a.dexpreopter.manifestFile = a.mergedManifestFile - a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex - if ctx.ModuleName() != "framework-res" { a.Module.compile(ctx, a.aaptSrcJar) } @@ -584,7 +741,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile := a.dexBuildActions(ctx) - jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) + jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) jniJarFile := a.jniBuildActions(jniLibs, ctx) if ctx.Failed() { @@ -596,13 +753,17 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { // Build a final signed app package. packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk") - CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps) + var lineageFile android.Path + if lineage := String(a.overridableAppProperties.Lineage); lineage != "" { + lineageFile = android.PathForModuleSrc(ctx, lineage) + } + CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, lineageFile) a.outputFile = packageFile for _, split := range a.aapt.splits { // Sign the split APKs packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk") - CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps) + CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, lineageFile) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) } @@ -622,12 +783,25 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.buildAppDependencyInfo(ctx) } -func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool, +type appDepsInterface interface { + sdkVersion() sdkSpec + minSdkVersion() sdkSpec + RequiresStableAPIs(ctx android.BaseModuleContext) bool +} + +func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, + shouldCollectRecursiveNativeDeps bool, checkNativeSdkVersion bool) ([]jniLib, []Certificate) { + var jniLibs []jniLib var certificates []Certificate seenModulePaths := make(map[string]bool) + if checkNativeSdkVersion { + checkNativeSdkVersion = app.sdkVersion().specified() && + app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx) + } + ctx.WalkDeps(func(module android.Module, parent android.Module) bool { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -645,16 +819,9 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps } seenModulePaths[path.String()] = true - if checkNativeSdkVersion { - if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok { - if app.sdkVersion().specified() && - app.sdkVersion().kind != sdkCorePlatform && - dep.SdkVersion() == "" { - ctx.PropertyErrorf("jni_libs", - "JNI dependency %q uses platform APIs, but this module does not", - otherName) - } - } + if checkNativeSdkVersion && dep.SdkVersion() == "" { + ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", + otherName) } if lib.Valid() { @@ -731,6 +898,10 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo) } +func (a *AndroidApp) Updatable() bool { + return Bool(a.appProperties.Updatable) || a.ApexModuleBase.Updatable() +} + func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string { certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName()) if overridden { @@ -835,6 +1006,7 @@ func (a *AndroidTest) InstallInTestcases() bool { } func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { + var configs []tradefed.Config if a.appTestProperties.Instrumentation_target_package != nil { a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+*a.appTestProperties.Instrumentation_target_package) @@ -847,8 +1019,12 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } a.generateAndroidBuildActions(ctx) + for _, module := range a.testProperties.Test_mainline_modules { + configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) + } + testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, - a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config) + a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config, configs) a.testConfig = a.FixTestConfig(ctx, testConfig) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) } @@ -1086,6 +1262,8 @@ type AndroidAppImport struct { usesLibrary usesLibrary + preprocessed bool + installPath android.InstallPath } @@ -1101,6 +1279,9 @@ type AndroidAppImportProperties struct { // be set for presigned modules. Presigned *bool + // Name of the signing certificate lineage file. + Lineage *string + // Sign with the default system dev certificate. Must be used judiciously. Most imported apps // need to either specify a specific certificate or be presigned. Default_dev_cert *bool @@ -1175,7 +1356,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) { // Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing // with them may invalidate pre-existing signature data. - if ctx.InstallInTestcases() && Bool(a.properties.Presigned) { + if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || a.preprocessed) { ctx.Build(pctx, android.BuildParams{ Rule: android.Cp, Output: outputPath, @@ -1196,7 +1377,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( // Returns whether this module should have the dex file stored uncompressed in the APK. func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool { - if ctx.Config().UnbundledBuild() { + if ctx.Config().UnbundledBuild() || a.preprocessed { return false } @@ -1244,7 +1425,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set") } - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, a, false, false) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_PACKAGE_SPLITS @@ -1288,9 +1469,13 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk") - // Sign or align the package // TODO: Handle EXTERNAL - if !Bool(a.properties.Presigned) { + + // Sign or align the package if package has not been preprocessed + if a.preprocessed { + a.outputFile = srcApk + a.certificate = presignedCertificate + } else if !Bool(a.properties.Presigned) { // If the certificate property is empty at this point, default_dev_cert must be set to true. // Which makes processMainCert's behavior for the empty cert string WAI. certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx) @@ -1299,7 +1484,11 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } a.certificate = certificates[0] signed := android.PathForModuleOut(ctx, "signed", apkFilename) - SignAppPackage(ctx, signed, dexOutput, certificates) + var lineageFile android.Path + if lineage := String(a.properties.Lineage); lineage != "" { + lineageFile = android.PathForModuleSrc(ctx, lineage) + } + SignAppPackage(ctx, signed, dexOutput, certificates, lineageFile) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename) @@ -1370,6 +1559,14 @@ func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep an return false } +func (a *AndroidAppImport) sdkVersion() sdkSpec { + return sdkSpecFrom("") +} + +func (a *AndroidAppImport) minSdkVersion() sdkSpec { + return sdkSpecFrom("") +} + func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { props := reflect.TypeOf((*AndroidAppImportProperties)(nil)) @@ -1417,21 +1614,31 @@ func AndroidAppImportFactory() android.Module { }) android.InitApexModule(module) - InitJavaModule(module, android.DeviceSupported) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk") return module } +type androidTestImportProperties struct { + // Whether the prebuilt apk can be installed without additional processing. Default is false. + Preprocessed *bool +} + type AndroidTestImport struct { AndroidAppImport testProperties testProperties + testImportProperties androidTestImportProperties + data android.Paths } func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { + a.preprocessed = Bool(a.testImportProperties.Preprocessed) + a.generateAndroidBuildActions(ctx) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) @@ -1449,6 +1656,7 @@ func AndroidTestImportFactory() android.Module { module.AddProperties(&module.dexpreoptProperties) module.AddProperties(&module.usesLibrary.usesLibraryProperties) module.AddProperties(&module.testProperties) + module.AddProperties(&module.testImportProperties) module.populateAllVariantStructs() android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.processVariants(ctx) @@ -1484,6 +1692,9 @@ type RuntimeResourceOverlayProperties struct { // module name in the form ":module". Certificate *string + // Name of the signing certificate lineage file. + Lineage *string + // optional theme name. If specified, the overlay package will be applied // only when the ro.boot.vendor.overlay.theme system property is set to the same value. Theme *string @@ -1555,10 +1766,14 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC r.aapt.buildActions(ctx, r, aaptLinkFlags...) // Sign the built package - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, r, false, false) certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") - SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates) + var lineageFile android.Path + if lineage := String(r.properties.Lineage); lineage != "" { + lineageFile = android.PathForModuleSrc(ctx, lineage) + } + SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, lineageFile) r.certificate = certificates[0] r.outputFile = signed @@ -1648,6 +1863,7 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs "org.apache.http.legacy", "android.hidl.base-V1.0-java", "android.hidl.manager-V1.0-java") + ctx.AddVariationDependencies(nil, usesLibTag, optionalUsesLibs...) } } } diff --git a/java/app_builder.go b/java/app_builder.go index 5e7fbe6de..014bd54f1 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -26,16 +26,23 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/remoteexec" ) var ( - Signapk = pctx.AndroidStaticRule("signapk", + Signapk, SignapkRE = remoteexec.StaticRules(pctx, "signapk", blueprint.RuleParams{ - Command: `${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` + + Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` + `-jar ${config.SignapkCmd} $flags $certificates $in $out`, CommandDeps: []string{"${config.SignapkCmd}", "${config.SignapkJniLibrary}"}, }, - "flags", "certificates") + &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "signapk"}, + ExecStrategy: "${config.RESignApkExecStrategy}", + Inputs: []string{"${config.SignapkCmd}", "$in", "$$(dirname ${config.SignapkJniLibrary})", "$implicits"}, + OutputFiles: []string{"$outCommaList"}, + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"flags", "certificates"}, []string{"implicits", "outCommaList"}) ) var combineApk = pctx.AndroidStaticRule("combineApk", @@ -45,7 +52,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk", }) func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, - packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) { + packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, lineageFile android.Path) { unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" unsignedApk := android.PathForModuleOut(ctx, unsignedApkName) @@ -66,10 +73,10 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa Implicits: deps, }) - SignAppPackage(ctx, outputFile, unsignedApk, certificates) + SignAppPackage(ctx, outputFile, unsignedApk, certificates, lineageFile) } -func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) { +func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, lineageFile android.Path) { var certificateArgs []string var deps android.Paths @@ -78,15 +85,30 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u deps = append(deps, c.Pem, c.Key) } + outputFiles := android.WritablePaths{signedApk} + var flags []string + if lineageFile != nil { + flags = append(flags, "--lineage", lineageFile.String()) + deps = append(deps, lineageFile) + } + + rule := Signapk + args := map[string]string{ + "certificates": strings.Join(certificateArgs, " "), + "flags": strings.Join(flags, " "), + } + if ctx.Config().IsEnvTrue("RBE_SIGNAPK") { + rule = SignapkRE + args["implicits"] = strings.Join(deps.Strings(), ",") + args["outCommaList"] = strings.Join(outputFiles.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: Signapk, + Rule: rule, Description: "signapk", - Output: signedApk, + Outputs: outputFiles, Input: unsignedApk, Implicits: deps, - Args: map[string]string{ - "certificates": strings.Join(certificateArgs, " "), - }, + Args: args, }) } @@ -210,14 +232,20 @@ func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.Writabl "-f", j.path.String()) } + rule := zip + args := map[string]string{ + "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), + } + if ctx.Config().IsEnvTrue("RBE_ZIP") { + rule = zipRE + args["implicits"] = strings.Join(deps.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: zip, + Rule: rule, Description: "zip jni libs", Output: outputFile, Implicits: deps, - Args: map[string]string{ - "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), - }, + Args: args, }) } diff --git a/java/app_test.go b/java/app_test.go index 4bcfa5a81..eb583bea6 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -141,6 +141,94 @@ func TestAppSplits(t *testing.T) { } } +func TestAndroidAppSet(t *testing.T) { + ctx, config := testJava(t, ` + android_app_set { + name: "foo", + set: "prebuilts/apks/app.apks", + prerelease: true, + }`) + module := ctx.ModuleForTests("foo", "android_common") + const packedSplitApks = "extracted.zip" + params := module.Output(packedSplitApks) + if params.Rule == nil { + t.Errorf("expected output %s is missing", packedSplitApks) + } + if s := params.Args["allow-prereleased"]; s != "true" { + t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s) + } + mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0] + actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"] + expectedMaster := []string{"foo.apk"} + if !reflect.DeepEqual(actualMaster, expectedMaster) { + t.Errorf("Unexpected LOCAL_APK_SET_MASTER_FILE value: '%s', expected: '%s',", + actualMaster, expectedMaster) + } +} + +func TestAndroidAppSet_Variants(t *testing.T) { + bp := ` + android_app_set { + name: "foo", + set: "prebuilts/apks/app.apks", + }` + testCases := []struct { + name string + deviceArch *string + deviceSecondaryArch *string + aaptPrebuiltDPI []string + sdkVersion int + expected map[string]string + }{ + { + name: "One", + deviceArch: proptools.StringPtr("x86"), + aaptPrebuiltDPI: []string{"ldpi", "xxhdpi"}, + sdkVersion: 29, + expected: map[string]string{ + "abis": "X86", + "allow-prereleased": "false", + "screen-densities": "LDPI,XXHDPI", + "sdk-version": "29", + "stem": "foo", + }, + }, + { + name: "Two", + deviceArch: proptools.StringPtr("x86_64"), + deviceSecondaryArch: proptools.StringPtr("x86"), + aaptPrebuiltDPI: nil, + sdkVersion: 30, + expected: map[string]string{ + "abis": "X86_64,X86", + "allow-prereleased": "false", + "screen-densities": "all", + "sdk-version": "30", + "stem": "foo", + }, + }, + } + + for _, test := range testCases { + config := testAppConfig(nil, bp, nil) + config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI + config.TestProductVariables.Platform_sdk_version = &test.sdkVersion + config.TestProductVariables.DeviceArch = test.deviceArch + config.TestProductVariables.DeviceSecondaryArch = test.deviceSecondaryArch + ctx := testContext() + run(t, ctx, config) + module := ctx.ModuleForTests("foo", "android_common") + const packedSplitApks = "extracted.zip" + params := module.Output(packedSplitApks) + for k, v := range test.expected { + if actual := params.Args[k]; actual != v { + t.Errorf("%s: bad build arg value for '%s': '%s', expected '%s'", + test.name, k, actual, v) + } + } + } +} + func TestPlatformAPIs(t *testing.T) { testJava(t, ` android_app { @@ -385,6 +473,127 @@ func TestUpdatableApps(t *testing.T) { } } +func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { + testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "current", + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + system_shared_libs: [], + sdk_version: "current", + } + `) +} + +func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + system_shared_libs: [], + sdk_version: "29", + } + + ndk_prebuilt_object { + name: "ndk_crtbegin_so.29", + sdk_version: "29", + } + + ndk_prebuilt_object { + name: "ndk_crtend_so.29", + sdk_version: "29", + } + ` + fs := map[string][]byte{ + "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil, + "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil, + } + + ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs)) + + inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits + var crtbeginFound, crtendFound bool + for _, input := range inputs { + switch input.String() { + case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": + crtbeginFound = true + case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": + crtendFound = true + } + } + if !crtbeginFound || !crtendFound { + t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29") + } +} + +func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", // this APK should support 29 + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + sdk_version: "current", + } + ` + testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp) +} + +func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) { + bp := cc.GatherRequiredDepsForTest(android.Android) + ` + android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + sdk_version: "current", + min_sdk_version: "29", // this APK should support 29 + jni_libs: ["libjni"], + } + + cc_library { + name: "libjni", + stl: "none", + shared_libs: ["libbar"], + system_shared_libs: [], + sdk_version: "27", + } + + cc_library { + name: "libbar", + stl: "none", + system_shared_libs: [], + sdk_version: "current", + } + ` + testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp) +} + func TestResourceDirs(t *testing.T) { testCases := []struct { name string @@ -1144,25 +1353,44 @@ func TestJNISDK(t *testing.T) { platform_apis: true, jni_uses_sdk_apis: true, } + + cc_library { + name: "libvendorjni", + system_shared_libs: [], + stl: "none", + vendor: true, + } + + android_test { + name: "app_vendor", + jni_libs: ["libvendorjni"], + sdk_version: "current", + vendor: true, + } `) testCases := []struct { - name string - sdkJNI bool + name string + sdkJNI bool + vendorJNI bool }{ - {"app_platform", false}, - {"app_sdk", true}, - {"app_force_platform", false}, - {"app_force_sdk", true}, + {name: "app_platform"}, + {name: "app_sdk", sdkJNI: true}, + {name: "app_force_platform"}, + {name: "app_force_sdk", sdkJNI: true}, + {name: "app_vendor", vendorJNI: true}, } + platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). + Output("libjni.so").Output.String() + sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). + Output("libjni.so").Output.String() + vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared"). + Output("libvendorjni.so").Output.String() + for _, test := range testCases { t.Run(test.name, func(t *testing.T) { app := ctx.ModuleForTests(test.name, "android_common") - platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). - Output("libjni.so").Output.String() - sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). - Output("libjni.so").Output.String() jniLibZip := app.MaybeOutput("jnilibs.zip") if len(jniLibZip.Implicits) != 1 { @@ -1174,6 +1402,10 @@ func TestJNISDK(t *testing.T) { if gotJNI != sdkJNI { t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI) } + } else if test.vendorJNI { + if gotJNI != vendorJNI { + t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI) + } } else { if gotJNI != platformJNI { t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI) @@ -1209,7 +1441,8 @@ func TestCertificates(t *testing.T) { name string bp string certificateOverride string - expected string + expectedLineage string + expectedCertificate string }{ { name: "default", @@ -1221,7 +1454,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8", + expectedLineage: "", + expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8", }, { name: "module certificate property", @@ -1239,7 +1473,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "cert/new_cert.x509.pem cert/new_cert.pk8", + expectedLineage: "", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", }, { name: "path certificate property", @@ -1252,7 +1487,8 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "", - expected: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + expectedLineage: "", + expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", }, { name: "certificate overrides", @@ -1270,7 +1506,28 @@ func TestCertificates(t *testing.T) { } `, certificateOverride: "foo:new_certificate", - expected: "cert/new_cert.x509.pem cert/new_cert.pk8", + expectedLineage: "", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", + }, + { + name: "certificate lineage", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + certificate: ":new_certificate", + lineage: "lineage.bin", + sdk_version: "current", + } + + android_app_certificate { + name: "new_certificate", + certificate: "cert/new_cert", + } + `, + certificateOverride: "", + expectedLineage: "--lineage lineage.bin", + expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", }, } @@ -1286,9 +1543,14 @@ func TestCertificates(t *testing.T) { foo := ctx.ModuleForTests("foo", "android_common") signapk := foo.Output("foo.apk") - signFlags := signapk.Args["certificates"] - if test.expected != signFlags { - t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags) + signCertificateFlags := signapk.Args["certificates"] + if test.expectedCertificate != signCertificateFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedCertificate, signCertificateFlags) + } + + signFlags := signapk.Args["flags"] + if test.expectedLineage != signFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedLineage, signFlags) } }) } @@ -1402,6 +1664,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "bar", base: "foo", certificate: ":new_certificate", + lineage: "lineage.bin", logging_parent: "bah", } @@ -1422,7 +1685,8 @@ func TestOverrideAndroidApp(t *testing.T) { variantName string apkName string apkPath string - signFlag string + certFlag string + lineageFlag string overrides []string aaptFlag string logging_parent string @@ -1431,7 +1695,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "foo", variantName: "android_common", apkPath: "/target/product/test_device/system/app/foo/foo.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", overrides: []string{"qux"}, aaptFlag: "", logging_parent: "", @@ -1440,7 +1705,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "bar", variantName: "android_common_bar", apkPath: "/target/product/test_device/system/app/bar/bar.apk", - signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + lineageFlag: "--lineage lineage.bin", overrides: []string{"qux", "foo"}, aaptFlag: "", logging_parent: "bah", @@ -1449,7 +1715,8 @@ func TestOverrideAndroidApp(t *testing.T) { moduleName: "baz", variantName: "android_common_baz", apkPath: "/target/product/test_device/system/app/baz/baz.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", overrides: []string{"qux", "foo"}, aaptFlag: "--rename-manifest-package org.dandroid.bp", logging_parent: "", @@ -1474,9 +1741,15 @@ func TestOverrideAndroidApp(t *testing.T) { // Check the certificate paths signapk := variant.Output(expected.moduleName + ".apk") - signFlag := signapk.Args["certificates"] - if expected.signFlag != signFlag { - t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag) + certFlag := signapk.Args["certificates"] + if expected.certFlag != certFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.certFlag, certFlag) + } + + // Check the lineage flags + lineageFlag := signapk.Args["flags"] + if expected.lineageFlag != lineageFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.lineageFlag, lineageFlag) } // Check if the overrides field values are correctly aggregated. @@ -1798,6 +2071,27 @@ func TestAndroidAppImport_Presigned(t *testing.T) { } } +func TestAndroidAppImport_SigningLineage(t *testing.T) { + ctx, _ := testJava(t, ` + android_app_import { + name: "foo", + apk: "prebuilts/apk/app.apk", + certificate: "platform", + lineage: "lineage.bin", + } + `) + + variant := ctx.ModuleForTests("foo", "android_common") + + // Check cert signing lineage flag. + signedApk := variant.Output("signed/foo.apk") + signingFlag := signedApk.Args["flags"] + expected := "--lineage lineage.bin" + if expected != signingFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) + } +} + func TestAndroidAppImport_DefaultDevCert(t *testing.T) { ctx, _ := testJava(t, ` android_app_import { @@ -2075,6 +2369,45 @@ func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { if jniRule != android.Cp.String() { t.Errorf("Unexpected JNI uncompress rule: " + jniRule) } + if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil { + t.Errorf("Presigned test apk should be aligned") + } +} + +func TestAndroidTestImport_Preprocessed(t *testing.T) { + ctx, _ := testJava(t, ` + android_test_import { + name: "foo", + apk: "prebuilts/apk/app.apk", + presigned: true, + preprocessed: true, + } + + android_test_import { + name: "foo_cert", + apk: "prebuilts/apk/app.apk", + certificate: "cert/new_cert", + preprocessed: true, + } + `) + + testModules := []string{"foo", "foo_cert"} + for _, m := range testModules { + apkName := m + ".apk" + variant := ctx.ModuleForTests(m, "android_common") + jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String() + if jniRule != android.Cp.String() { + t.Errorf("Unexpected JNI uncompress rule: " + jniRule) + } + + // Make sure signing and aligning were skipped. + if variant.MaybeOutput("signed/"+apkName).Rule != nil { + t.Errorf("signing rule shouldn't be included for preprocessed.") + } + if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil { + t.Errorf("aligning rule shouldn't be for preprocessed") + } + } } func TestStl(t *testing.T) { @@ -2150,6 +2483,20 @@ func TestUsesLibraries(t *testing.T) { } java_sdk_library { + name: "qux", + srcs: ["a.java"], + api_packages: ["qux"], + sdk_version: "current", + } + + java_sdk_library { + name: "quuz", + srcs: ["a.java"], + api_packages: ["quuz"], + sdk_version: "current", + } + + java_sdk_library { name: "bar", srcs: ["a.java"], api_packages: ["bar"], @@ -2159,6 +2506,7 @@ func TestUsesLibraries(t *testing.T) { android_app { name: "app", srcs: ["a.java"], + libs: ["qux", "quuz.stubs"], uses_libs: ["foo"], sdk_version: "current", optional_uses_libs: [ @@ -2189,6 +2537,15 @@ func TestUsesLibraries(t *testing.T) { app := ctx.ModuleForTests("app", "android_common") prebuilt := ctx.ModuleForTests("prebuilt", "android_common") + // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. + manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + // Test that all libraries are verified cmd := app.Rule("verify_uses_libraries").RuleParams.Command if w := "--uses-library foo"; !strings.Contains(cmd, w) { @@ -2449,6 +2806,32 @@ func TestUncompressDex(t *testing.T) { uncompressedPlatform: true, uncompressedUnbundled: true, }, + { + name: "normal_uncompress_dex_true", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: true, + } + `, + uncompressedPlatform: true, + uncompressedUnbundled: true, + }, + { + name: "normal_uncompress_dex_false", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: false, + } + `, + uncompressedPlatform: false, + uncompressedUnbundled: false, + }, } test := func(t *testing.T, bp string, want bool, unbundled bool) { @@ -2512,6 +2895,7 @@ func TestRuntimeResourceOverlay(t *testing.T) { runtime_resource_overlay { name: "foo", certificate: "platform", + lineage: "lineage.bin", product_specific: true, static_libs: ["bar"], resource_libs: ["baz"], @@ -2566,6 +2950,11 @@ func TestRuntimeResourceOverlay(t *testing.T) { // Check cert signing flag. signedApk := m.Output("signed/foo.apk") + lineageFlag := signedApk.Args["flags"] + expectedLineageFlag := "--lineage lineage.bin" + if expectedLineageFlag != lineageFlag { + t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag) + } signingFlag := signedApk.Args["certificates"] expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" if expected != signingFlag { diff --git a/java/builder.go b/java/builder.go index 3a4a10d3c..a27e5c390 100644 --- a/java/builder.go +++ b/java/builder.go @@ -40,17 +40,17 @@ var ( // (if the rule produces .class files) or a .srcjar file (if the rule produces .java files). // .srcjar files are unzipped into a temporary directory when compiled with javac. // TODO(b/143658984): goma can't handle the --system argument to javac. - javac, javacRE = remoteexec.StaticRules(pctx, "javac", + javac, javacRE = remoteexec.MultiCommandStaticRules(pctx, "javac", blueprint.RuleParams{ Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + `(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` + - `${config.SoongJavacWrapper} $reTemplate${config.JavacCmd} ` + + `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` + `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` + `$processorpath $processor $javacFlags $bootClasspath $classpath ` + `-source $javaVersion -target $javaVersion ` + `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` + - `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` + + `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ "${config.JavacCmd}", @@ -60,10 +60,19 @@ var ( CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, Rspfile: "$out.rsp", RspfileContent: "$in", - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"}, - ExecStrategy: "${config.REJavacExecStrategy}", - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$javaTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"}, + ExecStrategy: "${config.REJavacExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$out"}, + ExecStrategy: "${config.REJavacExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", "outDir", "annoDir", "javaVersion"}, nil) @@ -104,10 +113,22 @@ var ( "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", "outDir", "annoDir", "javaVersion") - turbine = pctx.AndroidStaticRule("turbine", + extractMatchingApks = pctx.StaticRule( + "extractMatchingApks", + blueprint.RuleParams{ + Command: `rm -rf "$out" && ` + + `${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` + + `-sdk-version=${sdk-version} -abis=${abis} ` + + `--screen-densities=${screen-densities} --stem=${stem} ` + + `${in}`, + CommandDeps: []string{"${config.ExtractApksCmd}"}, + }, + "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem") + + turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + + `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` + `--javacopts ${config.CommonJdkFlags} ` + `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` + @@ -122,25 +143,45 @@ var ( RspfileContent: "$in", Restat: true, }, - "javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion") - - jar = pctx.AndroidStaticRule("jar", + &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"}, + ExecStrategy: "${config.RETurbineExecStrategy}", + Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out.tmp"}, + OutputDirectories: []string{"$outDir"}, + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"}) + + jar, jarRE = remoteexec.StaticRules(pctx, "jar", blueprint.RuleParams{ - Command: `${config.SoongZipCmd} -jar -o $out @$out.rsp`, + Command: `$reTemplate${config.SoongZipCmd} -jar -o $out @$out.rsp`, CommandDeps: []string{"${config.SoongZipCmd}"}, Rspfile: "$out.rsp", RspfileContent: "$jarArgs", }, - "jarArgs") + &remoteexec.REParams{ + ExecStrategy: "${config.REJarExecStrategy}", + Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"jarArgs"}, nil) - zip = pctx.AndroidStaticRule("zip", + zip, zipRE = remoteexec.StaticRules(pctx, "zip", blueprint.RuleParams{ Command: `${config.SoongZipCmd} -o $out @$out.rsp`, CommandDeps: []string{"${config.SoongZipCmd}"}, Rspfile: "$out.rsp", RspfileContent: "$jarArgs", }, - "jarArgs") + &remoteexec.REParams{ + ExecStrategy: "${config.REZipExecStrategy}", + Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp", "$implicits"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"jarArgs"}, []string{"implicits"}) combineJar = pctx.AndroidStaticRule("combineJar", blueprint.RuleParams{ @@ -334,20 +375,26 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android. deps = append(deps, classpath...) deps = append(deps, flags.processorPath...) + rule := turbine + args := map[string]string{ + "javacFlags": flags.javacFlags, + "bootClasspath": bootClasspath, + "srcJars": strings.Join(srcJars.Strings(), " "), + "classpath": classpath.FormTurbineClassPath("--classpath "), + "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), + "javaVersion": flags.javaVersion.String(), + } + if ctx.Config().IsEnvTrue("RBE_TURBINE") { + rule = turbineRE + args["implicits"] = strings.Join(deps.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: turbine, + Rule: rule, Description: "turbine", Output: outputFile, Inputs: srcFiles, Implicits: deps, - Args: map[string]string{ - "javacFlags": flags.javacFlags, - "bootClasspath": bootClasspath, - "srcJars": strings.Join(srcJars.Strings(), " "), - "classpath": classpath.FormTurbineClassPath("--classpath "), - "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), - "javaVersion": flags.javaVersion.String(), - }, + Args: args, }) } @@ -431,8 +478,12 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath, jarArgs []string, deps android.Paths) { + rule := jar + if ctx.Config().IsEnvTrue("RBE_JAR") { + rule = jarRE + } ctx.Build(pctx, android.BuildParams{ - Rule: jar, + Rule: rule, Description: "jar", Output: outputFile, Implicits: deps, diff --git a/java/config/config.go b/java/config/config.go index c4f236346..edaed2a10 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -122,7 +122,7 @@ func init() { pctx.HostBinToolVariable("D8Cmd", "d8") pctx.HostBinToolVariable("R8Cmd", "r8-compat-proguard") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") - + pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string { turbine := "turbine.jar" if ctx.Config().UnbundledBuild() { @@ -148,6 +148,10 @@ func init() { pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("REZipExecStrategy", remoteexec.EnvOverrideFunc("RBE_ZIP_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar") diff --git a/java/dex.go b/java/dex.go index 27ec6ee41..9e61e95ad 100644 --- a/java/dex.go +++ b/java/dex.go @@ -18,53 +18,72 @@ import ( "strings" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/remoteexec" ) -var d8, d8RE = remoteexec.StaticRules(pctx, "d8", +var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `$reTemplate${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` + - `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + + `$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` + + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.D8Cmd}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "compiler": "d8"}, - Inputs: []string{"${config.D8Jar}"}, - ExecStrategy: "${config.RED8ExecStrategy}", - ToolchainInputs: []string{"${config.JavaCmd}"}, - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$d8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "d8"}, + Inputs: []string{"${config.D8Jar}"}, + ExecStrategy: "${config.RED8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RED8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"outDir", "d8Flags", "zipFlags"}, nil) -var r8, r8RE = remoteexec.StaticRules(pctx, "r8", +var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + `rm -f "$outDict" && ` + - `$reTemplate${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` + + `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` + `--force-proguard-compatibility ` + `--no-data-resources ` + `-printmapping $outDict ` + `$r8Flags && ` + `touch "$outDict" && ` + - `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.R8Cmd}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "compiler": "r8"}, - Inputs: []string{"$implicits", "${config.R8Jar}"}, - ExecStrategy: "${config.RER8ExecStrategy}", - ToolchainInputs: []string{"${config.JavaCmd}"}, - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$r8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "r8"}, + Inputs: []string{"$implicits", "${config.R8Jar}"}, + ExecStrategy: "${config.RER8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RER8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"}) func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string { @@ -188,7 +207,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, outDir := android.PathForModuleOut(ctx, "dex") zipFlags := "--ignore_missing_files" - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { zipFlags += " -L 0" } @@ -235,7 +254,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, }, }) } - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName) TransformZipAlign(ctx, alignedJavalibJar, javalibJar) javalibJar = alignedJavalibJar diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index dffdc248f..ed61d4bd3 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -109,11 +109,11 @@ func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant { return nil } -func (image bootImageConfig) moduleName(idx int) string { +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(image.modules[idx]) + _, m := android.SplitApexJarPair(ctx, image.modules[idx]) name := image.stem if idx != 0 || image.extends != nil { name += "-" + stemOf(m) @@ -121,9 +121,9 @@ func (image bootImageConfig) moduleName(idx int) string { return name } -func (image bootImageConfig) firstModuleNameOrStem() string { +func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string { if len(image.modules) > 0 { - return image.moduleName(0) + return image.moduleName(ctx, 0) } else { return image.stem } @@ -132,7 +132,7 @@ func (image bootImageConfig) firstModuleNameOrStem() string { 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 { - name := image.moduleName(i) + name := image.moduleName(ctx, i) for _, ext := range exts { ret = append(ret, dir.Join(ctx, name+ext)) } @@ -261,7 +261,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul } name := ctx.ModuleName(module) - index := android.IndexList(name, android.GetJarsFromApexJarPairs(image.modules)) + index := android.IndexList(name, android.GetJarsFromApexJarPairs(ctx, image.modules)) if index == -1 { return -1, nil } @@ -314,7 +314,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(image.modules[i]) + _, m := android.SplitApexJarPair(ctx, image.modules[i]) if ctx.Config().AllowMissingDependencies() { missingDeps = append(missingDeps, m) bootDexJars[i] = android.PathForOutput(ctx, "missing") @@ -614,15 +614,15 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} { global := dexpreopt.GetGlobalConfig(ctx) - updatableModules := android.GetJarsFromApexJarPairs(global.UpdatableBootJars) + updatableModules := android.GetJarsFromApexJarPairs(ctx, global.UpdatableBootJars) // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string ctx.VisitAllModules(func(module android.Module) { - if j, ok := module.(*Library); ok { + if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok { name := ctx.ModuleName(module) if i := android.IndexList(name, updatableModules); i != -1 { - pp := j.properties.Permitted_packages + pp := j.PermittedPackagesForUpdatableBootJars() if len(pp) > 0 { updatablePackages = append(updatablePackages, pp...) } else { diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index 0946bf0a3..e9704dc2a 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -24,7 +24,7 @@ import ( "android/soong/dexpreopt" ) -func TestDexpreoptBootJars(t *testing.T) { +func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOutputs []string) { bp := ` java_sdk_library { name: "foo", @@ -52,63 +52,84 @@ func TestDexpreoptBootJars(t *testing.T) { dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig) ctx := testContext() - RegisterDexpreoptBootJarsComponents(ctx) - run(t, ctx, config) dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars") - - bootArt := dexpreoptBootJars.Output("boot-foo.art") - - expectedInputs := []string{ - "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art", - "dex_bootjars_input/foo.jar", - "dex_bootjars_input/bar.jar", - "dex_bootjars_input/baz.jar", - } + rule := dexpreoptBootJars.Output(ruleFile) for i := range expectedInputs { expectedInputs[i] = filepath.Join(buildDir, "test_device", expectedInputs[i]) } - inputs := bootArt.Implicits.Strings() + for i := range expectedOutputs { + expectedOutputs[i] = filepath.Join(buildDir, "test_device", expectedOutputs[i]) + } + + inputs := rule.Implicits.Strings() sort.Strings(inputs) sort.Strings(expectedInputs) + outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Strings() + sort.Strings(outputs) + sort.Strings(expectedOutputs) + if !reflect.DeepEqual(inputs, expectedInputs) { t.Errorf("want inputs %q\n got inputs %q", expectedInputs, inputs) } + if !reflect.DeepEqual(outputs, expectedOutputs) { + t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs) + } +} + +func TestDexpreoptBootJars(t *testing.T) { + ruleFile := "boot-foo.art" + + expectedInputs := []string{ + "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art", + "dex_bootjars_input/foo.jar", + "dex_bootjars_input/bar.jar", + "dex_bootjars_input/baz.jar", + } + expectedOutputs := []string{ "dex_bootjars/android/system/framework/arm64/boot.invocation", - "dex_bootjars/android/system/framework/arm64/boot-foo.art", "dex_bootjars/android/system/framework/arm64/boot-bar.art", "dex_bootjars/android/system/framework/arm64/boot-baz.art", - "dex_bootjars/android/system/framework/arm64/boot-foo.oat", "dex_bootjars/android/system/framework/arm64/boot-bar.oat", "dex_bootjars/android/system/framework/arm64/boot-baz.oat", - "dex_bootjars/android/system/framework/arm64/boot-foo.vdex", "dex_bootjars/android/system/framework/arm64/boot-bar.vdex", "dex_bootjars/android/system/framework/arm64/boot-baz.vdex", - "dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat", "dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat", "dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat", } - for i := range expectedOutputs { - expectedOutputs[i] = filepath.Join(buildDir, "test_device", expectedOutputs[i]) - } + testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs) +} - outputs := append(android.WritablePaths{bootArt.Output}, bootArt.ImplicitOutputs...).Strings() - sort.Strings(outputs) - sort.Strings(expectedOutputs) +// Changes to the boot.zip structure may break the ART APK scanner. +func TestDexpreoptBootZip(t *testing.T) { + ruleFile := "boot.zip" + + ctx := android.PathContextForTesting(testConfig(nil, "", nil)) + expectedInputs := []string{} + for _, target := range dexpreoptTargets(ctx) { + for _, ext := range []string{".art", ".oat", ".vdex"} { + for _, jar := range []string{"foo", "bar", "baz"} { + expectedInputs = append(expectedInputs, + filepath.Join("dex_bootjars", target.Os.String(), "system/framework", target.Arch.ArchType.String(), "boot-"+jar+ext)) + } + } + } - if !reflect.DeepEqual(outputs, expectedOutputs) { - t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs) + expectedOutputs := []string{ + "dex_bootjars/boot.zip", } + + testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs) } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 41a2ca794..f13d9f210 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -39,7 +39,7 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string { // 2) The jars that are from an updatable apex. for _, m := range global.UpdatableSystemServerJars { systemServerClasspathLocations = append(systemServerClasspathLocations, - dexpreopt.GetJarLocationFromApexJarPair(m)) + dexpreopt.GetJarLocationFromApexJarPair(ctx, m)) } if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) { panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d", @@ -80,7 +80,7 @@ func stemOf(moduleName string) string { } func getDexLocation(ctx android.PathContext, target android.Target, module string) string { - apex, jar := android.SplitApexJarPair(module) + apex, jar := android.SplitApexJarPair(ctx, module) name := stemOf(jar) + ".jar" @@ -156,7 +156,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped") // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension - imageName := c.firstModuleNameOrStem() + ".art" + imageName := c.firstModuleNameOrStem(ctx) + ".art" // The path to bootclasspath dex files needs to be known at module // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. @@ -164,7 +164,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { // TODO(b/143682396): use module dependencies instead inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") for _, m := range c.modules { - _, jar := android.SplitApexJarPair(m) + _, jar := android.SplitApexJarPair(ctx, m) c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(jar)+".jar")) } c.dexPathsDeps = c.dexPaths @@ -215,7 +215,7 @@ func defaultBootclasspath(ctx android.PathContext) []string { updatableBootclasspath := make([]string, len(global.UpdatableBootJars)) for i, p := range global.UpdatableBootJars { - updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p) + updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(ctx, p) } bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...) diff --git a/java/droiddoc.go b/java/droiddoc.go index 78ecb09e3..b16c9cd72 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -222,8 +222,22 @@ type DroidstubsProperties struct { Current ApiToCheck - // do not perform API check against Last_released, in the case that both two specified API - // files by Last_released are modules which don't exist. + // The java_sdk_library module generates references to modules (i.e. filegroups) + // from which information about the latest API version can be obtained. As those + // modules may not exist (e.g. because a previous version has not been released) it + // sets ignore_missing_latest_api=true on the droidstubs modules it creates so + // that droidstubs can ignore those references if the modules do not yet exist. + // + // If true then this will ignore module references for modules that do not exist + // in properties that supply the previous version of the API. + // + // There are two sets of those: + // * Api_file, Removed_api_file in check_api.last_released + // * New_since in check_api.api_lint.new_since + // + // The first two must be set as a pair, so either they should both exist or neither + // should exist - in which case when this property is true they are ignored. If one + // exists and the other does not then it is an error. Ignore_missing_latest_api *bool `blueprint:"mutated"` Api_lint struct { @@ -337,11 +351,16 @@ type ApiFilePath interface { ApiFilePath() android.Path } +type ApiStubsSrcProvider interface { + StubsSrcJar() android.Path +} + // Provider of information about API stubs, used by java_sdk_library. type ApiStubsProvider interface { ApiFilePath RemovedApiFilePath() android.Path - StubsSrcJar() android.Path + + ApiStubsSrcProvider } // @@ -357,6 +376,7 @@ type Javadoc struct { srcFiles android.Paths sourcepaths android.Paths argFiles android.Paths + implicits android.Paths args string @@ -527,7 +547,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { case libTag: switch dep := module.(type) { case SdkLibraryDependency: - deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...) + deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) case Dependency: deps.classpath = append(deps.classpath, dep.HeaderJars()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) @@ -556,6 +576,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs // may contain filegroup or genrule. srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) + j.implicits = append(j.implicits, srcFiles...) filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path { if filterPackages == nil { @@ -581,6 +602,24 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { } srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages) + // While metalava needs package html files, it does not need them to be explicit on the command + // line. More importantly, the metalava rsp file is also used by the subsequent jdiff action if + // jdiff_enabled=true. javadoc complains if it receives html files on the command line. The filter + // below excludes html files from the rsp file for both metalava and jdiff. Note that the html + // files are still included as implicit inputs for successful remote execution and correct + // incremental builds. + filterHtml := func(srcs []android.Path) []android.Path { + filtered := []android.Path{} + for _, src := range srcs { + if src.Ext() == ".html" { + continue + } + filtered = append(filtered, src) + } + return filtered + } + srcFiles = filterHtml(srcFiles) + flags := j.collectAidlFlags(ctx, deps) srcFiles = j.genSources(ctx, srcFiles, flags) @@ -1200,8 +1239,18 @@ func (d *Droidstubs) StubsSrcJar() android.Path { func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) { d.Javadoc.addDeps(ctx) + // If requested clear any properties that provide information about the latest version + // of an API and which reference non-existent modules. if Bool(d.properties.Check_api.Ignore_missing_latest_api) { ignoreMissingModules(ctx, &d.properties.Check_api.Last_released) + + // If the new_since references a module, e.g. :module-latest-api and the module + // does not exist then clear it. + newSinceSrc := d.properties.Check_api.Api_lint.New_since + newSinceSrcModule := android.SrcIsModule(proptools.String(newSinceSrc)) + if newSinceSrcModule != "" && !ctx.OtherModuleExists(newSinceSrcModule) { + d.properties.Check_api.Api_lint.New_since = nil + } } if len(d.properties.Merge_annotations_dirs) != 0 { @@ -1373,10 +1422,26 @@ func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleB } func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths, - srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand { + srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicits android.Paths) *android.RuleBuilderCommand { // Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel. rule.HighMem() cmd := rule.Command() + + rspFile := "" + if len(implicits) > 0 { + implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp") + rspFile = implicitsRsp.String() + impRule := android.NewRuleBuilder() + impCmd := impRule.Command() + // A dummy action that copies the ninja generated rsp file to a new location. This allows us to + // add a large number of inputs to a file without exceeding bash command length limits (which + // would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the + // rsp file to be ${output}.rsp. + impCmd.Text("cp").FlagWithRspFileInputList("", implicits).Output(implicitsRsp) + impRule.Build(pctx, ctx, "implicitsGen", "implicits generation") + cmd.Implicits(implicits) + cmd.Implicit(implicitsRsp) + } if ctx.Config().IsEnvTrue("RBE_METALAVA") { rule.Remoteable(android.RemoteRuleSupports{RBE: true}) execStrategy := remoteexec.LocalExecStrategy @@ -1388,7 +1453,6 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi pool = v } inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()} - inputs = append(inputs, sourcepaths.Strings()...) if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" { inputs = append(inputs, strings.Split(v, ",")...) } @@ -1396,6 +1460,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "metalava"}, ExecStrategy: execStrategy, Inputs: inputs, + RSPFile: rspFile, ToolchainInputs: []string{config.JavaCmd(ctx).String()}, Platform: map[string]string{remoteexec.PoolKey: pool}, }).NoVarTemplate(ctx.Config())) @@ -1453,7 +1518,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList, - deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths) + deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, d.Javadoc.implicits) d.stubsFlags(ctx, cmd, stubsDir) @@ -1908,6 +1973,10 @@ func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) { } } +func (d *PrebuiltStubsSources) StubsSrcJar() android.Path { + return d.stubsSrcJar +} + func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) { p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") diff --git a/java/hiddenapi.go b/java/hiddenapi.go index 884a757e2..ce624bfc1 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -180,7 +180,9 @@ func hiddenAPIEncodeDex(ctx android.ModuleContext, output android.WritablePath, // b/149353192: when a module is instrumented, jacoco adds synthetic members // $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags, // don't complain when we don't find hidden API flags for the synthetic members. - if j, ok := ctx.Module().(*Library); ok && j.shouldInstrument(ctx) { + if j, ok := ctx.Module().(interface { + shouldInstrument(android.BaseModuleContext) bool + }); ok && j.shouldInstrument(ctx) { enforceHiddenApiFlagsToAllMembers = false } diff --git a/java/java.go b/java/java.go index 9d75c74c7..76bfa86d6 100644 --- a/java/java.go +++ b/java/java.go @@ -95,8 +95,7 @@ func (j *Module) CheckStableSdkVersion() error { } func (j *Module) checkSdkVersions(ctx android.ModuleContext) { - if j.SocSpecific() || j.DeviceSpecific() || - (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { + if j.RequiresStableAPIs(ctx) { if sc, ok := ctx.Module().(sdkContext); ok { if !sc.sdkVersion().specified() { ctx.PropertyErrorf("sdk_version", @@ -343,14 +342,45 @@ type CompilerDeviceProperties struct { // set the name of the output Stem *string - UncompressDex bool `blueprint:"mutated"` - IsSDKLibrary bool `blueprint:"mutated"` + // Keep the data uncompressed. We always need uncompressed dex for execution, + // so this might actually save space by avoiding storing the same data twice. + // This defaults to reasonable value based on module and should not be set. + // It exists only to support ART tests. + Uncompress_dex *bool + + IsSDKLibrary bool `blueprint:"mutated"` } func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault) } +// Functionality common to Module and Import +// +// It is embedded in Module so its functionality can be used by methods in Module +// but it is currently only initialized by Import and Library. +type embeddableInModuleAndImport struct { + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent +} + +func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) { + e.initSdkLibraryComponent(moduleBase) +} + +// Module/Import's DepIsInSameApex(...) delegates to this method. +// +// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with +// the one provided by ApexModuleBase. +func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { + // dependencies other than the static linkage are all considered crossing APEX boundary + if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + return true + } + return false +} + // Module contains the properties and members used by all java module types type Module struct { android.ModuleBase @@ -358,6 +388,9 @@ type Module struct { android.ApexModuleBase android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties CompilerProperties protoProperties android.ProtoProperties deviceProperties CompilerDeviceProperties @@ -443,6 +476,9 @@ type Module struct { kytheFiles android.Paths distFile android.Path + + // Collect the module directory for IDE info in java/jdeps.go. + modulePaths []string } func (j *Module) OutputFiles(tag string) (android.Paths, error) { @@ -474,11 +510,6 @@ type Dependency interface { JacocoReportClassesFile() android.Path } -type SdkLibraryDependency interface { - SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths - SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths -} - type xref interface { XrefJavaFiles() android.Paths } @@ -625,13 +656,15 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } } else if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) - ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) } } + if sdkDep.systemModules != "" { + ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) + } if ctx.ModuleName() == "android_stubs_current" || ctx.ModuleName() == "android_system_stubs_current" || @@ -906,6 +939,12 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } } + // If this is a component library (stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a <uses-library> element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -925,7 +964,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported - j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) + j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -1034,19 +1073,10 @@ func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) { } func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion { - sdk, err := sdkContext.sdkVersion().effectiveVersion(ctx) - if err != nil { - ctx.PropertyErrorf("sdk_version", "%s", err) - } if javaVersion != "" { return normalizeJavaVersion(ctx, javaVersion) - } else if ctx.Device() && sdk <= 23 { - return JAVA_VERSION_7 - } else if ctx.Device() && sdk <= 29 { - return JAVA_VERSION_8 - } else if ctx.Device() && ctx.Config().UnbundledBuildUsePrebuiltSdks() { - // TODO(b/142896162): once we have prebuilt system modules we can use 1.9 for unbundled builds - return JAVA_VERSION_8 + } else if ctx.Device() { + return sdkContext.sdkVersion().defaultJavaLanguageVersion(ctx) } else { return JAVA_VERSION_9 } @@ -1426,13 +1456,19 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { serviceFile := file.String() zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile) } + rule := zip + args := map[string]string{ + "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "), + } + if ctx.Config().IsEnvTrue("RBE_ZIP") { + rule = zipRE + args["implicits"] = strings.Join(services.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: zip, + Rule: rule, Output: servicesJar, Implicits: services, - Args: map[string]string{ - "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "), - }, + Args: args, }) jars = append(jars, servicesJar) } @@ -1545,7 +1581,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Hidden API CSV generation and dex encoding dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, - j.deviceProperties.UncompressDex) + proptools.Bool(j.deviceProperties.Uncompress_dex)) // merge dex jar with resources if necessary if j.resourceJar != nil { @@ -1553,7 +1589,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName) TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, false, nil, nil) - if j.deviceProperties.UncompressDex { + if *j.deviceProperties.Uncompress_dex { combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName) TransformZipAlign(ctx, combinedAlignedJar, combinedJar) dexOutputFile = combinedAlignedJar @@ -1754,6 +1790,7 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { if j.expandJarjarRules != nil { dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) } + dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...) } func (j *Module) CompilerDeps() []string { @@ -1769,11 +1806,7 @@ func (j *Module) hasCode(ctx android.ModuleContext) bool { } func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // Dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } func (j *Module) Stem() string { @@ -1807,6 +1840,17 @@ type Library struct { InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } +// Provides access to the list of permitted packages from updatable boot jars. +type PermittedPackagesForUpdatableBootJars interface { + PermittedPackagesForUpdatableBootJars() []string +} + +var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil) + +func (j *Library) PermittedPackagesForUpdatableBootJars() []string { + return j.properties.Permitted_packages +} + func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool { // Store uncompressed (and aligned) any dex files from jars in APEXes. if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() { @@ -1834,10 +1878,16 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) - j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex + if j.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) + } + j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex j.compile(ctx, nil) + // Collect the module directory for IDE info in java/jdeps.go. + j.modulePaths = append(j.modulePaths, ctx.ModuleDir()) + exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { var extraInstallDeps android.Paths @@ -1845,7 +1895,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { extraInstallDeps = j.InstallMixin(ctx, j.outputFile) } j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), - ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...) + j.Stem()+".jar", j.outputFile, extraInstallDeps...) } // Verify Dist.Tag is set to a supported output @@ -1979,6 +2029,8 @@ func LibraryFactory() android.Module { &module.Module.protoProperties, &module.libraryProperties) + module.initModuleAndImport(&module.ModuleBase) + android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -2033,6 +2085,10 @@ type testProperties struct { // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. Auto_gen_config *bool + + // Add parameterized mainline modules to auto generated test config. The options will be + // handled by TradeFed to do downloading and installing the specified modules on the device. + Test_mainline_modules []string } type testHelperLibraryProperties struct { @@ -2387,6 +2443,9 @@ type Import struct { prebuilt android.Prebuilt android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties ImportProperties combinedClasspathFile android.Path @@ -2444,6 +2503,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.combinedClasspathFile = outputFile + // If this is a component library (impl, stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a <uses-library> element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2521,11 +2586,7 @@ func (j *Import) SrcJarArgs() ([]string, android.Paths) { } func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } // Add compile time check for interface implementation @@ -2566,6 +2627,8 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) + module.initModuleAndImport(&module.ModuleBase) + android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) @@ -2682,7 +2745,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.maybeStrippedDexJarFile = dexOutputFile ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), - ctx.ModuleName()+".jar", dexOutputFile) + j.Stem()+".jar", dexOutputFile) } func (j *DexImport) DexJar() android.Path { @@ -2764,6 +2827,7 @@ func DefaultsFactory() android.Module { &ImportProperties{}, &AARImportProperties{}, &sdkLibraryProperties{}, + &commonToSdkLibraryAndImportProperties{}, &DexImportProperties{}, &android.ApexProperties{}, &RuntimeResourceOverlayProperties{}, diff --git a/java/java_test.go b/java/java_test.go index 0033f319d..8ea34d975 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,6 +19,8 @@ import ( "os" "path/filepath" "reflect" + "regexp" + "sort" "strconv" "strings" "testing" @@ -575,6 +577,7 @@ func TestJavaSdkLibraryImport(t *testing.T) { }, test: { jars: ["c.jar"], + stub_srcs: ["c.java"], }, } `) @@ -1035,7 +1038,7 @@ func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, m for _, i := range metalavaRule.Implicits { systemJars = append(systemJars, i.Base()) } - if len(systemJars) != 1 || systemJars[0] != systemJar { + if len(systemJars) < 1 || systemJars[0] != systemJar { t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars) } } @@ -1152,13 +1155,42 @@ func TestJavaSdkLibrary(t *testing.T) { java_library { name: "baz", srcs: ["c.java"], - libs: ["foo", "bar"], + libs: ["foo", "bar.stubs"], sdk_version: "system_current", } + java_sdk_library { + name: "barney", + srcs: ["c.java"], + api_only: true, + } + java_sdk_library { + name: "betty", + srcs: ["c.java"], + shared_library: false, + } + java_sdk_library_import { + name: "quuz", + public: { + jars: ["c.jar"], + }, + } + java_sdk_library_import { + name: "fred", + public: { + jars: ["b.jar"], + }, + } + java_sdk_library_import { + name: "wilma", + public: { + jars: ["b.jar"], + }, + shared_library: false, + } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz"], + libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"], sdk_version: "system_current", } java_library { @@ -1177,12 +1209,12 @@ func TestJavaSdkLibrary(t *testing.T) { // check the existence of the internal modules ctx.ModuleForTests("foo", "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkTestApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkSystemApiSuffix, "android_common") - ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkTestApiSuffix, "android_common") + ctx.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common") + ctx.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common") ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common") ctx.ModuleForTests("foo.api.public.28", "") ctx.ModuleForTests("foo.api.system.28", "") @@ -1223,12 +1255,145 @@ func TestJavaSdkLibrary(t *testing.T) { qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { sdkLibs := quxLib.ExportedSdkLibs() - if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { - t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) + sort.Strings(sdkLibs) + if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { + t.Errorf("qux should export %q but exports %q", w, sdkLibs) + } + } +} + +func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_only: true, + public: { + enabled: true, + }, } + + java_library { + name: "bar", + srcs: ["b.java"], + libs: ["foo"], + } + `) + + // The bar library should depend on the stubs jar. + barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac") + if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) } } +func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { + testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + public: { + enabled: true, + }, + } + + java_library { + name: "bar", + srcs: ["b.java", ":foo{.public.stubs.source}"], + } + `) +} + +func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { + testJavaError(t, `"foo" does not provide api scope system`, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + public: { + enabled: true, + }, + } + + java_library { + name: "bar", + srcs: ["b.java", ":foo{.system.stubs.source}"], + } + `) +} + +func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { + testJava(t, ` + java_sdk_library_import { + name: "foo", + public: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "api/current.txt", + removed_api: "api/removed.txt", + }, + } + + java_library { + name: "bar", + srcs: [":foo{.public.stubs.source}"], + java_resources: [ + ":foo{.public.api.txt}", + ":foo{.public.removed-api.txt}", + ], + } + `) +} + +func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { + bp := ` + java_sdk_library_import { + name: "foo", + public: { + jars: ["a.jar"], + }, + } + ` + + t.Run("stubs.source", func(t *testing.T) { + testJavaError(t, `stubs.source not available for api scope public`, bp+` + java_library { + name: "bar", + srcs: [":foo{.public.stubs.source}"], + java_resources: [ + ":foo{.public.api.txt}", + ":foo{.public.removed-api.txt}", + ], + } + `) + }) + + t.Run("api.txt", func(t *testing.T) { + testJavaError(t, `api.txt not available for api scope public`, bp+` + java_library { + name: "bar", + srcs: ["a.java"], + java_resources: [ + ":foo{.public.api.txt}", + ], + } + `) + }) + + t.Run("removed-api.txt", func(t *testing.T) { + testJavaError(t, `removed-api.txt not available for api scope public`, bp+` + java_library { + name: "bar", + srcs: ["a.java"], + java_resources: [ + ":foo{.public.removed-api.txt}", + ], + } + `) + }) +} + func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { testJavaError(t, `module "foo": enabled api scope "system" depends on disabled scope "public"`, ` java_sdk_library { @@ -1247,6 +1412,86 @@ func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { `) } +func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { + testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java", "b.java"], + api_packages: ["foo"], + system: { + enabled: true, + sdk_version: "module_current", + }, + } + `) +} + +func TestJavaSdkLibrary_MissingScope(t *testing.T) { + testJavaError(t, `requires api scope module-lib from foo but it only has \[\] available`, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + public: { + enabled: false, + }, + } + + java_library { + name: "baz", + srcs: ["a.java"], + libs: ["foo"], + sdk_version: "module_current", + } + `) +} + +func TestJavaSdkLibrary_FallbackScope(t *testing.T) { + testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + system: { + enabled: true, + }, + } + + java_library { + name: "baz", + srcs: ["a.java"], + libs: ["foo"], + // foo does not have module-lib scope so it should fallback to system + sdk_version: "module_current", + } + `) +} + +func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + system: { + enabled: true, + }, + default_to_stubs: true, + } + + java_library { + name: "baz", + srcs: ["a.java"], + libs: ["foo"], + // does not have sdk_version set, should fallback to module, + // which will then fallback to system because the module scope + // is not enabled. + } + `) + // The baz library should depend on the system stubs jar. + bazLibrary := ctx.ModuleForTests("baz", "android_common").Rule("javac") + if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + var compilerFlagsTestCases = []struct { in string out bool diff --git a/java/jdeps.go b/java/jdeps.go index 49e3de3cc..9f4388733 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -72,6 +72,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules) dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars) dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars) + dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths) moduleInfos[name] = dpInfo mkProvider, ok := module.(android.AndroidMkDataProvider) diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 03bc76bf2..999c72f3c 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -15,11 +15,12 @@ package java import ( - "android/soong/android" "sort" "strings" "github.com/google/blueprint/proptools" + + "android/soong/android" ) func init() { @@ -69,6 +70,10 @@ func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, return } +func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope string, apiver string) string { + return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module +} + func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) { props := struct { Name *string @@ -76,7 +81,7 @@ func createImport(mctx android.LoadHookContext, module string, scope string, api Sdk_version *string Installable *bool }{} - props.Name = proptools.StringPtr(mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module) + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver)) props.Jars = append(props.Jars, path) // TODO(hansson): change to scope after migration is done. props.Sdk_version = proptools.StringPtr("current") @@ -124,6 +129,27 @@ func prebuiltSdkStubs(mctx android.LoadHookContext) { } } +func createSystemModules(mctx android.LoadHookContext, apiver string) { + props := struct { + Name *string + Libs []string + }{} + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver)) + props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver)) + + mctx.CreateModule(SystemModulesFactory, &props) +} + +func prebuiltSdkSystemModules(mctx android.LoadHookContext) { + for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs { + jar := android.ExistentPathForSource(mctx, + mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar") + if jar.Valid() { + createSystemModules(mctx, apiver) + } + } +} + func prebuiltApiFiles(mctx android.LoadHookContext) { mydir := mctx.ModuleDir() + "/" // <apiver>/<scope>/api/<module>.txt @@ -178,6 +204,7 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { if _, ok := mctx.Module().(*prebuiltApis); ok { prebuiltApiFiles(mctx) prebuiltSdkStubs(mctx) + prebuiltSdkSystemModules(mctx) } } @@ -191,7 +218,9 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { // Similarly, it generates a java_import for all API .jar files found under the // directory where the Android.bp is located. Specifically, an API file located // at ./<ver>/<scope>/api/<module>.jar generates a java_import module named -// <prebuilt-api-module>.<scope>.<ver>.<module>. +// <prebuilt-api-module>_<scope>_<ver>_<module>, and for SDK versions >= 30 +// a java_system_modules module named +// <prebuilt-api-module>_public_<ver>_system_modules func PrebuiltApisFactory() android.Module { module := &prebuiltApis{} module.AddProperties(&module.properties) diff --git a/java/sdk.go b/java/sdk.go index 690451c60..9310f7846 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -252,6 +252,20 @@ func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, return ver.String(), err } +func (s sdkSpec) defaultJavaLanguageVersion(ctx android.EarlyModuleContext) javaVersion { + sdk, err := s.effectiveVersion(ctx) + if err != nil { + ctx.PropertyErrorf("sdk_version", "%s", err) + } + if sdk <= 23 { + return JAVA_VERSION_7 + } else if sdk <= 29 { + return JAVA_VERSION_8 + } else { + return JAVA_VERSION_9 + } +} + func sdkSpecFrom(str string) sdkSpec { switch str { // special cases first @@ -370,10 +384,16 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep return sdkDep{} } + var systemModules string + if sdkVersion.defaultJavaLanguageVersion(ctx).usesJavaModules() { + systemModules = "sdk_public_" + sdkVersion.version.String() + "_system_modules" + } + return sdkDep{ - useFiles: true, - jars: android.Paths{jarPath.Path(), lambdaStubsPath}, - aidl: android.OptionalPathForPath(aidlPath.Path()), + useFiles: true, + jars: android.Paths{jarPath.Path(), lambdaStubsPath}, + aidl: android.OptionalPathForPath(aidlPath.Path()), + systemModules: systemModules, } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 2c85c8c09..c4d257f20 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -19,6 +19,7 @@ import ( "path" "path/filepath" "reflect" + "regexp" "sort" "strings" "sync" @@ -30,12 +31,8 @@ import ( ) const ( - sdkStubsLibrarySuffix = ".stubs" - sdkSystemApiSuffix = ".system" - sdkTestApiSuffix = ".test" - sdkStubsSourceSuffix = ".stubs.source" - sdkXmlFileSuffix = ".xml" - permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` + + sdkXmlFileSuffix = ".xml" + permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` + `<!-- Copyright (C) 2018 The Android Open Source Project\n` + `\n` + ` Licensed under the Apache License, Version 2.0 (the \"License\");\n` + @@ -96,9 +93,18 @@ type apiScope struct { // The name of the field in the dynamically created structure. fieldName string + // The name of the property in the java_sdk_library_import + propertyName string + // The tag to use to depend on the stubs library module. stubsTag scopeDependencyTag + // The tag to use to depend on the stubs source module (if separate from the API module). + stubsSourceTag scopeDependencyTag + + // The tag to use to depend on the API file generating module (if separate from the stubs source module). + apiFileTag scopeDependencyTag + // The tag to use to depend on the stubs source and API module. stubsSourceAndApiTag scopeDependencyTag @@ -117,6 +123,22 @@ type apiScope struct { // Extra arguments to pass to droidstubs for this scope. droidstubsArgs []string + // The args that must be passed to droidstubs to generate the stubs source + // for this scope. + // + // The stubs source must include the definitions of everything that is in this + // api scope and all the scopes that this one extends. + droidstubsArgsForGeneratingStubsSource []string + + // The args that must be passed to droidstubs to generate the API for this scope. + // + // The API only includes the additional members that this scope adds over the scope + // that it extends. + droidstubsArgsForGeneratingApi []string + + // True if the stubs source and api can be created by the same metalava invocation. + createStubsSourceAndApiTogether bool + // Whether the api scope can be treated as unstable, and should skip compat checks. unstable bool } @@ -124,26 +146,63 @@ type apiScope struct { // Initialize a scope, creating and adding appropriate dependency tags func initApiScope(scope *apiScope) *apiScope { name := scope.name - scope.fieldName = proptools.FieldNameForProperty(name) + scopeByName[name] = scope + allScopeNames = append(allScopeNames, name) + scope.propertyName = strings.ReplaceAll(name, "-", "_") + scope.fieldName = proptools.FieldNameForProperty(scope.propertyName) scope.stubsTag = scopeDependencyTag{ name: name + "-stubs", apiScope: scope, depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency, } + scope.stubsSourceTag = scopeDependencyTag{ + name: name + "-stubs-source", + apiScope: scope, + depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep, + } + scope.apiFileTag = scopeDependencyTag{ + name: name + "-api", + apiScope: scope, + depInfoExtractor: (*scopePaths).extractApiInfoFromDep, + } scope.stubsSourceAndApiTag = scopeDependencyTag{ name: name + "-stubs-source-and-api", apiScope: scope, depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider, } + + // To get the args needed to generate the stubs source append all the args from + // this scope and all the scopes it extends as each set of args adds additional + // members to the stubs. + var stubsSourceArgs []string + for s := scope; s != nil; s = s.extends { + stubsSourceArgs = append(stubsSourceArgs, s.droidstubsArgs...) + } + scope.droidstubsArgsForGeneratingStubsSource = stubsSourceArgs + + // Currently the args needed to generate the API are the same as the args + // needed to add additional members. + apiArgs := scope.droidstubsArgs + scope.droidstubsArgsForGeneratingApi = apiArgs + + // If the args needed to generate the stubs and API are the same then they + // can be generated in a single invocation of metalava, otherwise they will + // need separate invocations. + scope.createStubsSourceAndApiTogether = reflect.DeepEqual(stubsSourceArgs, apiArgs) + return scope } -func (scope *apiScope) stubsModuleName(baseName string) string { - return baseName + sdkStubsLibrarySuffix + scope.moduleSuffix +func (scope *apiScope) stubsLibraryModuleName(baseName string) string { + return baseName + ".stubs" + scope.moduleSuffix } func (scope *apiScope) stubsSourceModuleName(baseName string) string { - return baseName + sdkStubsSourceSuffix + scope.moduleSuffix + return baseName + ".stubs.source" + scope.moduleSuffix +} + +func (scope *apiScope) apiModuleName(baseName string) string { + return baseName + ".api" + scope.moduleSuffix } func (scope *apiScope) String() string { @@ -161,6 +220,8 @@ func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string { } var ( + scopeByName = make(map[string]*apiScope) + allScopeNames []string apiScopePublic = initApiScope(&apiScope{ name: "public", @@ -183,7 +244,7 @@ var ( return &module.sdkLibraryProperties.System }, apiFilePrefix: "system-", - moduleSuffix: sdkSystemApiSuffix, + moduleSuffix: ".system", sdkVersion: "system_current", droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"}, }) @@ -195,13 +256,13 @@ var ( return &module.sdkLibraryProperties.Test }, apiFilePrefix: "test-", - moduleSuffix: sdkTestApiSuffix, + moduleSuffix: ".test", sdkVersion: "test_current", droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"}, unstable: true, }) apiScopeModuleLib = initApiScope(&apiScope{ - name: "module_lib", + name: "module-lib", extends: apiScopeSystem, // Module_lib scope is disabled by default in legacy mode. // @@ -268,9 +329,29 @@ type ApiScopeProperties struct { // Otherwise, if this is not set for any scope then the default behavior is // scope specific so please refer to the scope specific property documentation. Enabled *bool + + // The sdk_version to use for building the stubs. + // + // If not specified then it will use an sdk_version determined as follows: + // 1) If the sdk_version specified on the java_sdk_library is none then this + // will be none. This is used for java_sdk_library instances that are used + // to create stubs that contribute to the core_current sdk version. + // 2) Otherwise, it is assumed that this library extends but does not contribute + // directly to a specific sdk_version and so this uses the sdk_version appropriate + // for the api scope. e.g. public will use sdk_version: current, system will use + // sdk_version: system_current, etc. + // + // This does not affect the sdk_version used for either generating the stubs source + // or the API file. They both have to use the same sdk_version as is used for + // compiling the implementation library. + Sdk_version *string } type sdkLibraryProperties struct { + // Visibility for impl library module. If not specified then defaults to the + // visibility property. + Impl_library_visibility []string + // Visibility for stubs library modules. If not specified then defaults to the // visibility property. Stubs_library_visibility []string @@ -295,7 +376,10 @@ type sdkLibraryProperties struct { // Defaults to "api". Api_dir *string - // If set to true there is no runtime library. + // Determines whether a runtime implementation library is built; defaults to false. + // + // If true then it also prevents the module from being used as a shared module, i.e. + // it is as is shared_library: false, was set. Api_only *bool // local files that are used within user customized droiddoc options. @@ -351,16 +435,48 @@ type sdkLibraryProperties struct { // disabled by default. Module_lib ApiScopeProperties + // Determines if the stubs are preferred over the implementation library + // for linking, even when the client doesn't specify sdk_version. When this + // is set to true, such clients are provided with the widest API surface that + // this lib provides. Note however that this option doesn't affect the clients + // that are in the same APEX as this library. In that case, the clients are + // always linked with the implementation library. Default is false. + Default_to_stubs *bool + + // Properties related to api linting. + Api_lint struct { + // Enable api linting. + Enabled *bool + } + // TODO: determines whether to create HTML doc or not //Html_doc *bool } +// Paths to outputs from java_sdk_library and java_sdk_library_import. +// +// Fields that are android.Paths are always set (during GenerateAndroidBuildActions). +// OptionalPaths are always set by java_sdk_library but may not be set by +// java_sdk_library_import as not all instances provide that information. type scopePaths struct { - stubsHeaderPath android.Paths - stubsImplPath android.Paths - currentApiFilePath android.Path - removedApiFilePath android.Path - stubsSrcJar android.Path + // The path (represented as Paths for convenience when returning) to the stubs header jar. + // + // That is the jar that is created by turbine. + stubsHeaderPath android.Paths + + // The path (represented as Paths for convenience when returning) to the stubs implementation jar. + // + // This is not the implementation jar, it still only contains stubs. + stubsImplPath android.Paths + + // The API specification file, e.g. system_current.txt. + currentApiFilePath android.OptionalPath + + // The specification of API elements removed since the last release. + removedApiFilePath android.OptionalPath + + // The stubs source jar. + stubsSrcJar android.OptionalPath } func (paths *scopePaths) extractStubsLibraryInfoFromDependency(dep android.Module) error { @@ -373,23 +489,211 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(dep android.Modul } } -func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep android.Module) error { - if provider, ok := dep.(ApiStubsProvider); ok { - paths.currentApiFilePath = provider.ApiFilePath() - paths.removedApiFilePath = provider.RemovedApiFilePath() - paths.stubsSrcJar = provider.StubsSrcJar() +func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider)) error { + if apiStubsProvider, ok := dep.(ApiStubsProvider); ok { + action(apiStubsProvider) return nil } else { return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs") } } +func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider)) error { + if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok { + action(apiStubsProvider) + return nil + } else { + return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs") + } +} + +func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) { + paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath()) + paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath()) +} + +func (paths *scopePaths) extractApiInfoFromDep(dep android.Module) error { + return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) { + paths.extractApiInfoFromApiStubsProvider(provider) + }) +} + +func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider) { + paths.stubsSrcJar = android.OptionalPathForPath(provider.StubsSrcJar()) +} + +func (paths *scopePaths) extractStubsSourceInfoFromDep(dep android.Module) error { + return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) { + paths.extractStubsSourceInfoFromApiStubsProviders(provider) + }) +} + +func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep android.Module) error { + return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) { + paths.extractApiInfoFromApiStubsProvider(provider) + paths.extractStubsSourceInfoFromApiStubsProviders(provider) + }) +} + +type commonToSdkLibraryAndImportProperties struct { + // The naming scheme to use for the components that this module creates. + // + // If not specified then it defaults to "default". The other allowable value is + // "framework-modules" which matches the scheme currently used by framework modules + // for the equivalent components represented as separate Soong modules. + // + // This is a temporary mechanism to simplify conversion from separate modules for each + // component that follow a different naming pattern to the default one. + // + // TODO(b/155480189) - Remove once naming inconsistencies have been resolved. + Naming_scheme *string + + // Specifies whether this module can be used as an Android shared library; defaults + // to true. + // + // An Android shared library is one that can be referenced in a <uses-library> element + // in an AndroidManifest.xml. + Shared_library *bool +} + // Common code between sdk library and sdk library import type commonToSdkLibraryAndImport struct { + moduleBase *android.ModuleBase + scopePaths map[*apiScope]*scopePaths + + namingScheme sdkLibraryComponentNamingScheme + + commonSdkLibraryProperties commonToSdkLibraryAndImportProperties + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent +} + +func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { + c.moduleBase = moduleBase + + moduleBase.AddProperties(&c.commonSdkLibraryProperties) + + // Initialize this as an sdk library component. + c.initSdkLibraryComponent(moduleBase) +} + +func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { + schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default") + switch schemeProperty { + case "default": + c.namingScheme = &defaultNamingScheme{} + case "framework-modules": + c.namingScheme = &frameworkModulesNamingScheme{} + default: + ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty) + return false + } + + // Only track this sdk library if this can be used as a shared library. + if c.sharedLibrary() { + // Use the name specified in the module definition as the owner. + c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + } + + return true +} + +// Name of the java_library module that compiles the stubs source. +func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string { + return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName()) +} + +// Name of the droidstubs module that generates the stubs source and may also +// generate/check the API. +func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string { + return c.namingScheme.stubsSourceModuleName(apiScope, c.moduleBase.BaseModuleName()) +} + +// Name of the droidstubs module that generates/checks the API. Only used if it +// requires different arts to the stubs source generating module. +func (c *commonToSdkLibraryAndImport) apiModuleName(apiScope *apiScope) string { + return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName()) } -func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths { +// The component names for different outputs of the java_sdk_library. +// +// They are similar to the names used for the child modules it creates +const ( + stubsSourceComponentName = "stubs.source" + + apiTxtComponentName = "api.txt" + + removedApiTxtComponentName = "removed-api.txt" +) + +// A regular expression to match tags that reference a specific stubs component. +// +// It will only match if given a valid scope and a valid component. It is verfy strict +// to ensure it does not accidentally match a similar looking tag that should be processed +// by the embedded Library. +var tagSplitter = func() *regexp.Regexp { + // Given a list of literal string items returns a regular expression that will + // match any one of the items. + choice := func(items ...string) string { + return `\Q` + strings.Join(items, `\E|\Q`) + `\E` + } + + // Regular expression to match one of the scopes. + scopesRegexp := choice(allScopeNames...) + + // Regular expression to match one of the components. + componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName) + + // Regular expression to match any combination of one scope and one component. + return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp)) +}() + +// For OutputFileProducer interface +// +// .<scope>.stubs.source +// .<scope>.api.txt +// .<scope>.removed-api.txt +func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) { + if groups := tagSplitter.FindStringSubmatch(tag); groups != nil { + scopeName := groups[1] + component := groups[2] + + if scope, ok := scopeByName[scopeName]; ok { + paths := c.findScopePaths(scope) + if paths == nil { + return nil, fmt.Errorf("%q does not provide api scope %s", c.moduleBase.BaseModuleName(), scopeName) + } + + switch component { + case stubsSourceComponentName: + if paths.stubsSrcJar.Valid() { + return android.Paths{paths.stubsSrcJar.Path()}, nil + } + + case apiTxtComponentName: + if paths.currentApiFilePath.Valid() { + return android.Paths{paths.currentApiFilePath.Path()}, nil + } + + case removedApiTxtComponentName: + if paths.removedApiFilePath.Valid() { + return android.Paths{paths.removedApiFilePath.Path()}, nil + } + } + + return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName) + } else { + return nil, fmt.Errorf("unknown scope %s in %s", scope, tag) + } + + } else { + return nil, nil + } +} + +func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths { if c.scopePaths == nil { c.scopePaths = make(map[*apiScope]*scopePaths) } @@ -402,6 +706,147 @@ func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths return paths } +func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths { + if c.scopePaths == nil { + return nil + } + + return c.scopePaths[scope] +} + +// If this does not support the requested api scope then find the closest available +// scope it does support. Returns nil if no such scope is available. +func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths { + for s := scope; s != nil; s = s.extends { + if paths := c.findScopePaths(s); paths != nil { + return paths + } + } + + // This should never happen outside tests as public should be the base scope for every + // scope and is enabled by default. + return nil +} + +func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths { + + // If a specific numeric version has been requested then use prebuilt versions of the sdk. + if sdkVersion.version.isNumbered() { + return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion) + } + + var apiScope *apiScope + switch sdkVersion.kind { + case sdkSystem: + apiScope = apiScopeSystem + case sdkModule: + apiScope = apiScopeModuleLib + case sdkTest: + apiScope = apiScopeTest + default: + apiScope = apiScopePublic + } + + paths := c.findClosestScopePath(apiScope) + if paths == nil { + var scopes []string + for _, s := range allApiScopes { + if c.findScopePaths(s) != nil { + scopes = append(scopes, s.name) + } + } + ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.moduleBase.BaseModuleName(), scopes) + return nil + } + + return paths.stubsHeaderPath +} + +func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { + componentProps := &struct { + SdkLibraryToImplicitlyTrack *string + }{} + + if c.sharedLibrary() { + // Mark the stubs library as being components of this java_sdk_library so that + // any app that includes code which depends (directly or indirectly) on the stubs + // library will have the appropriate <uses-library> invocation inserted into its + // manifest if necessary. + componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + } + + return componentProps +} + +// Check if this can be used as a shared library. +func (c *commonToSdkLibraryAndImport) sharedLibrary() bool { + return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true) +} + +// Properties related to the use of a module as an component of a java_sdk_library. +type SdkLibraryComponentProperties struct { + + // The name of the java_sdk_library/_import to add to a <uses-library> entry + // in the AndroidManifest.xml of any Android app that includes code that references + // this module. If not set then no java_sdk_library/_import is tracked. + SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` +} + +// Structure to be embedded in a module struct that needs to support the +// SdkLibraryComponentDependency interface. +type EmbeddableSdkLibraryComponent struct { + sdkLibraryComponentProperties SdkLibraryComponentProperties +} + +func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) { + moduleBase.AddProperties(&e.sdkLibraryComponentProperties) +} + +// to satisfy SdkLibraryComponentDependency +func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string { + if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil { + return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack} + } + return nil +} + +// Implemented by modules that are (or possibly could be) a component of a java_sdk_library +// (including the java_sdk_library) itself. +type SdkLibraryComponentDependency interface { + // The optional name of the sdk library that should be implicitly added to the + // AndroidManifest of an app that contains code which references the sdk library. + // + // Returns an array containing 0 or 1 items rather than a *string to make it easier + // to append this to the list of exported sdk libraries. + OptionalImplicitSdkLibrary() []string +} + +// Make sure that all the module types that are components of java_sdk_library/_import +// and which can be referenced (directly or indirectly) from an android app implement +// the SdkLibraryComponentDependency interface. +var _ SdkLibraryComponentDependency = (*Library)(nil) +var _ SdkLibraryComponentDependency = (*Import)(nil) +var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) +var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil) + +// Provides access to sdk_version related header and implentation jars. +type SdkLibraryDependency interface { + SdkLibraryComponentDependency + + // Get the header jars appropriate for the supplied sdk_version. + // + // These are turbine generated jars so they only change if the externals of the + // class changes but it does not contain and implementation or JavaDoc. + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths + + // Get the implementation jars appropriate for the supplied sdk version. + // + // These are either the implementation jar for the whole sdk library or the implementation + // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise + // they are identical to the corresponding header jars. + SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths +} + type SdkLibrary struct { Library @@ -477,26 +922,51 @@ func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { return false } +var implLibraryTag = dependencyTag{name: "impl-library"} + func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { for _, apiScope := range module.getGeneratedApiScopes(ctx) { // Add dependencies to the stubs library - ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) - // And the stubs source and api files - ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceName(apiScope)) + // If the stubs source and API cannot be generated together then add an additional dependency on + // the API module. + if apiScope.createStubsSourceAndApiTogether { + // Add a dependency on the stubs source in order to access both stubs source and api information. + ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope)) + } else { + // Add separate dependencies on the creators of the stubs source files and the API. + ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope)) + ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.apiModuleName(apiScope)) + } } - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { - // Add dependency to the rule for generating the xml permissions file - ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName()) + if module.requiresRuntimeImplementationLibrary() { + // Add dependency to the rule for generating the implementation library. + ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName()) + + if module.sharedLibrary() { + // Add dependency to the rule for generating the xml permissions file + ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName()) + } + + // Only add the deps for the library if it is actually going to be built. + module.Library.deps(ctx) } +} - module.Library.deps(ctx) +func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { + paths, err := module.commonOutputFiles(tag) + if paths == nil && err == nil { + return module.Library.OutputFiles(tag) + } else { + return paths, err + } } func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Don't build an implementation library if this is api only. - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { + // Only build an implementation library if required. + if module.requiresRuntimeImplementationLibrary() { module.Library.GenerateAndroidBuildActions(ctx) } @@ -509,7 +979,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) // Extract information from any of the scope specific dependencies. if scopeTag, ok := tag.(scopeDependencyTag); ok { apiScope := scopeTag.apiScope - scopePaths := module.getScopePaths(apiScope) + scopePaths := module.getScopePathsCreateIfNeeded(apiScope) // Extract information from the dependency. The exact information extracted // is determined by the nature of the dependency which is determined by the tag. @@ -519,7 +989,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { - if proptools.Bool(module.sdkLibraryProperties.Api_only) { + if !module.requiresRuntimeImplementationLibrary() { return nil } entriesList := module.Library.AndroidMkEntries() @@ -528,20 +998,9 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { return entriesList } -// Name of the java_library module that compiles the stubs source. -func (module *SdkLibrary) stubsName(apiScope *apiScope) string { - return apiScope.stubsModuleName(module.BaseModuleName()) -} - -// // Name of the droidstubs module that generates the stubs source and -// generates/checks the API. -func (module *SdkLibrary) stubsSourceName(apiScope *apiScope) string { - return apiScope.stubsSourceModuleName(module.BaseModuleName()) -} - // Module name of the runtime implementation library -func (module *SdkLibrary) implName() string { - return module.BaseModuleName() +func (module *SdkLibrary) implLibraryModuleName() string { + return module.BaseModuleName() + ".impl" } // Module name of the XML file for the lib @@ -561,7 +1020,12 @@ func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string { } // Get the sdk version for use when compiling the stubs library. -func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) string { +func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string { + scopeProperties := module.scopeToProperties[apiScope] + if scopeProperties.Sdk_version != nil { + return proptools.String(scopeProperties.Sdk_version) + } + sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library)) if sdkDep.hasStandardLibs() { // If building against a standard sdk then use the sdk version appropriate for the scope. @@ -580,24 +1044,41 @@ func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) stri return ":" + module.BaseModuleName() + "-removed.api." + apiScope.name + ".latest" } +// Creates the implementation java library +func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) { + props := struct { + Name *string + Visibility []string + }{ + Name: proptools.StringPtr(module.implLibraryModuleName()), + Visibility: module.sdkLibraryProperties.Impl_library_visibility, + } + + properties := []interface{}{ + &module.properties, + &module.protoProperties, + &module.deviceProperties, + &module.dexpreoptProperties, + &props, + module.sdkComponentPropertiesForChildLibrary(), + } + mctx.CreateModule(LibraryFactory, properties...) +} + // Creates a static java library that has API stubs func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { props := struct { - Name *string - Visibility []string - Srcs []string - Installable *bool - Sdk_version *string - System_modules *string - Patch_module *string - Libs []string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Compile_dex *bool - Java_version *string - Product_variables struct { + Name *string + Visibility []string + Srcs []string + Installable *bool + Sdk_version *string + System_modules *string + Patch_module *string + Libs []string + Compile_dex *bool + Java_version *string + Product_variables struct { Pdk struct { Enabled *bool } @@ -614,7 +1095,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext } }{} - props.Name = proptools.StringPtr(module.stubsName(apiScope)) + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) // If stubs_library_visibility is not set then the created module will use the // visibility of this module. @@ -622,30 +1103,21 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Visibility = visibility // sources are generated from the droiddoc - props.Srcs = []string{":" + module.stubsSourceName(apiScope)} + props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) props.Sdk_version = proptools.StringPtr(sdkVersion) - props.System_modules = module.Library.Module.deviceProperties.System_modules - props.Patch_module = module.Library.Module.properties.Patch_module + props.System_modules = module.deviceProperties.System_modules + props.Patch_module = module.properties.Patch_module props.Installable = proptools.BoolPtr(false) props.Libs = module.sdkLibraryProperties.Stub_only_libs props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false) - props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs - props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags - props.Java_version = module.Library.Module.properties.Java_version - if module.Library.Module.deviceProperties.Compile_dex != nil { - props.Compile_dex = module.Library.Module.deviceProperties.Compile_dex + props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs + props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags + props.Java_version = module.properties.Java_version + if module.deviceProperties.Compile_dex != nil { + props.Compile_dex = module.deviceProperties.Compile_dex } - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } else if module.SystemExtSpecific() { - props.System_ext_specific = proptools.BoolPtr(true) - } // Dist the class jar artifact for sdk builds. if !Bool(module.sdkLibraryProperties.No_dist) { props.Dist.Targets = []string{"sdk", "win_sdk"} @@ -654,12 +1126,12 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Dist.Tag = proptools.StringPtr(".jar") } - mctx.CreateModule(LibraryFactory, &props) + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } // Creates a droidstubs module that creates stubs source files from the given full source // files and also updates and checks the API specification files. -func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope) { +func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, createStubSources, createApi bool, scopeSpecificDroidstubsArgs []string) { props := struct { Name *string Visibility []string @@ -673,10 +1145,17 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC Java_version *string Merge_annotations_dirs []string Merge_inclusion_annotations_dirs []string + Generate_stubs *bool Check_api struct { Current ApiToCheck Last_released ApiToCheck Ignore_missing_latest_api *bool + + Api_lint struct { + Enabled *bool + New_since *string + Baseline_file *string + } } Aidl struct { Include_dirs []string @@ -695,24 +1174,24 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC // * system_modules // * libs (static_libs/libs) - props.Name = proptools.StringPtr(module.stubsSourceName(apiScope)) + props.Name = proptools.StringPtr(name) // If stubs_source_visibility is not set then the created module will use the // visibility of this module. visibility := module.sdkLibraryProperties.Stubs_source_visibility props.Visibility = visibility - props.Srcs = append(props.Srcs, module.Library.Module.properties.Srcs...) - props.Sdk_version = module.Library.Module.deviceProperties.Sdk_version - props.System_modules = module.Library.Module.deviceProperties.System_modules + props.Srcs = append(props.Srcs, module.properties.Srcs...) + props.Sdk_version = module.deviceProperties.Sdk_version + props.System_modules = module.deviceProperties.System_modules props.Installable = proptools.BoolPtr(false) // A droiddoc module has only one Libs property and doesn't distinguish between // shared libs and static libs. So we need to add both of these libs to Libs property. - props.Libs = module.Library.Module.properties.Libs - props.Libs = append(props.Libs, module.Library.Module.properties.Static_libs...) - props.Aidl.Include_dirs = module.Library.Module.deviceProperties.Aidl.Include_dirs - props.Aidl.Local_include_dirs = module.Library.Module.deviceProperties.Aidl.Local_include_dirs - props.Java_version = module.Library.Module.properties.Java_version + props.Libs = module.properties.Libs + props.Libs = append(props.Libs, module.properties.Static_libs...) + props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs + props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs + props.Java_version = module.properties.Java_version props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs @@ -739,38 +1218,64 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC } droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) + if !createStubSources { + // Stubs are not required. + props.Generate_stubs = proptools.BoolPtr(false) + } + // Add in scope specific arguments. - droidstubsArgs = append(droidstubsArgs, apiScope.droidstubsArgs...) + droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " ")) - // List of APIs identified from the provided source files are created. They are later - // compared against to the not-yet-released (a.k.a current) list of APIs and to the - // last-released (a.k.a numbered) list of API. - currentApiFileName := apiScope.apiFilePrefix + "current.txt" - removedApiFileName := apiScope.apiFilePrefix + "removed.txt" - apiDir := module.getApiDir() - currentApiFileName = path.Join(apiDir, currentApiFileName) - removedApiFileName = path.Join(apiDir, removedApiFileName) - - // check against the not-yet-release API - props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) - props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) - - if !apiScope.unstable { - // check against the latest released API - props.Check_api.Last_released.Api_file = proptools.StringPtr( - module.latestApiFilegroupName(apiScope)) - props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( - module.latestRemovedApiFilegroupName(apiScope)) - props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) - } + if createApi { + // List of APIs identified from the provided source files are created. They are later + // compared against to the not-yet-released (a.k.a current) list of APIs and to the + // last-released (a.k.a numbered) list of API. + currentApiFileName := apiScope.apiFilePrefix + "current.txt" + removedApiFileName := apiScope.apiFilePrefix + "removed.txt" + apiDir := module.getApiDir() + currentApiFileName = path.Join(apiDir, currentApiFileName) + removedApiFileName = path.Join(apiDir, removedApiFileName) + + // check against the not-yet-release API + props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) + props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) + + if !apiScope.unstable { + // check against the latest released API + latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) + props.Check_api.Last_released.Api_file = latestApiFilegroupName + props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( + module.latestRemovedApiFilegroupName(apiScope)) + props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) + + if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { + // Enable api lint. + props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) + props.Check_api.Api_lint.New_since = latestApiFilegroupName + + // If it exists then pass a lint-baseline.txt through to droidstubs. + baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") + baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) + paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) + if err != nil { + mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) + } + if len(paths) == 1 { + props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) + } else if len(paths) != 0 { + mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) + } + } + } - // Dist the api txt artifact for sdk builds. - if !Bool(module.sdkLibraryProperties.No_dist) { - props.Dist.Targets = []string{"sdk", "win_sdk"} - props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName())) - props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) + // Dist the api txt artifact for sdk builds. + if !Bool(module.sdkLibraryProperties.No_dist) { + props.Dist.Targets = []string{"sdk", "win_sdk"} + props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName())) + props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) + } } mctx.CreateModule(DroidstubsFactory, &props) @@ -787,29 +1292,15 @@ func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep an // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { props := struct { - Name *string - Lib_name *string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Apex_available []string + Name *string + Lib_name *string + Apex_available []string }{ Name: proptools.StringPtr(module.xmlFileName()), Lib_name: proptools.StringPtr(module.BaseModuleName()), Apex_available: module.ApexProperties.Apex_available, } - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } else if module.SystemExtSpecific() { - props.System_ext_specific = proptools.BoolPtr(true) - } - mctx.CreateModule(sdkLibraryXmlFactory, &props) } @@ -840,41 +1331,50 @@ func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) and return android.Paths{jarPath.Path()} } -func (module *SdkLibrary) sdkJars( - ctx android.BaseModuleContext, - sdkVersion sdkSpec, - headerJars bool) android.Paths { +// Get the apex name for module, "" if it is for platform. +func getApexNameForModule(module android.Module) string { + if apex, ok := module.(android.ApexModule); ok { + return apex.ApexName() + } - // If a specific numeric version has been requested then use prebuilt versions of the sdk. - if sdkVersion.version.isNumbered() { - return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion) - } else { - if !sdkVersion.specified() { + return "" +} + +// Check to see if the other module is within the same named APEX as this module. +// +// If either this or the other module are on the platform then this will return +// false. +func (module *SdkLibrary) withinSameApexAs(other android.Module) bool { + name := module.ApexName() + return name != "" && getApexNameForModule(other) == name +} + +func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths { + // If the client doesn't set sdk_version, but if this library prefers stubs over + // the impl library, let's provide the widest API surface possible. To do so, + // force override sdk_version to module_current so that the closest possible API + // surface could be found in selectHeaderJarsForSdkVersion + if module.defaultsToStubs() && !sdkVersion.specified() { + sdkVersion = sdkSpecFrom("module_current") + } + + // Only provide access to the implementation library if it is actually built. + if module.requiresRuntimeImplementationLibrary() { + // Check any special cases for java_sdk_library. + // + // Only allow access to the implementation library in the following condition: + // * No sdk_version specified on the referencing module. + // * The referencing module is in the same apex as this. + if sdkVersion.kind == sdkPrivate || module.withinSameApexAs(ctx.Module()) { if headerJars { - return module.Library.HeaderJars() + return module.HeaderJars() } else { - return module.Library.ImplementationJars() + return module.ImplementationJars() } } - var apiScope *apiScope - switch sdkVersion.kind { - case sdkSystem: - apiScope = apiScopeSystem - case sdkTest: - apiScope = apiScopeTest - case sdkPrivate: - return module.Library.HeaderJars() - default: - apiScope = apiScopePublic - } - - paths := module.getScopePaths(apiScope) - if headerJars { - return paths.stubsHeaderPath - } else { - return paths.stubsImplPath - } } + + return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) } // to satisfy SdkLibraryDependency interface @@ -912,7 +1412,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont return } - if len(module.Library.Module.properties.Srcs) == 0 { + if len(module.properties.Srcs) == 0 { mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs") return } @@ -958,13 +1458,40 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont } for _, scope := range generatedScopes { + stubsSourceArgs := scope.droidstubsArgsForGeneratingStubsSource + stubsSourceModuleName := module.stubsSourceModuleName(scope) + + // If the args needed to generate the stubs and API are the same then they + // can be generated in a single invocation of metalava, otherwise they will + // need separate invocations. + if scope.createStubsSourceAndApiTogether { + // Use the stubs source name for legacy reasons. + module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, true, stubsSourceArgs) + } else { + module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, false, stubsSourceArgs) + + apiArgs := scope.droidstubsArgsForGeneratingApi + apiName := module.apiModuleName(scope) + module.createStubsSourcesAndApi(mctx, scope, apiName, false, true, apiArgs) + } + module.createStubsLibrary(mctx, scope) - module.createStubsSourcesAndApi(mctx, scope) } - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { - // for runtime - module.createXmlFile(mctx) + if module.requiresRuntimeImplementationLibrary() { + // Create child module to create an implementation library. + // + // This temporarily creates a second implementation library that can be explicitly + // referenced. + // + // TODO(b/156618935) - update comment once only one implementation library is created. + module.createImplLibrary(mctx) + + // Only create an XML permissions file that declares the library as being usable + // as a shared library if required. + if module.sharedLibrary() { + module.createXmlFile(mctx) + } // record java_sdk_library modules so that they are exported to make javaSdkLibraries := javaSdkLibraries(mctx.Config()) @@ -977,16 +1504,77 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont func (module *SdkLibrary) InitSdkLibraryProperties() { module.AddProperties( &module.sdkLibraryProperties, - &module.Library.Module.properties, - &module.Library.Module.dexpreoptProperties, - &module.Library.Module.deviceProperties, - &module.Library.Module.protoProperties, + &module.properties, + &module.dexpreoptProperties, + &module.deviceProperties, + &module.protoProperties, ) - module.Library.Module.properties.Installable = proptools.BoolPtr(true) - module.Library.Module.deviceProperties.IsSDKLibrary = true + module.initSdkLibraryComponent(&module.ModuleBase) + + module.properties.Installable = proptools.BoolPtr(true) + module.deviceProperties.IsSDKLibrary = true } +func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool { + return !proptools.Bool(module.sdkLibraryProperties.Api_only) +} + +func (module *SdkLibrary) defaultsToStubs() bool { + return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs) +} + +// Defines how to name the individual component modules the sdk library creates. +type sdkLibraryComponentNamingScheme interface { + stubsLibraryModuleName(scope *apiScope, baseName string) string + + stubsSourceModuleName(scope *apiScope, baseName string) string + + apiModuleName(scope *apiScope, baseName string) string +} + +type defaultNamingScheme struct { +} + +func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { + return scope.stubsLibraryModuleName(baseName) +} + +func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { + return scope.stubsSourceModuleName(baseName) +} + +func (s *defaultNamingScheme) apiModuleName(scope *apiScope, baseName string) string { + return scope.apiModuleName(baseName) +} + +var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) + +type frameworkModulesNamingScheme struct { +} + +func (s *frameworkModulesNamingScheme) moduleSuffix(scope *apiScope) string { + suffix := scope.name + if scope == apiScopeModuleLib { + suffix = "module_libs_" + } + return suffix +} + +func (s *frameworkModulesNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-stubs-%sapi", baseName, s.moduleSuffix(scope)) +} + +func (s *frameworkModulesNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-stubs-srcs-%sapi", baseName, s.moduleSuffix(scope)) +} + +func (s *frameworkModulesNamingScheme) apiModuleName(scope *apiScope, baseName string) string { + return fmt.Sprintf("%s-api-%sapi", baseName, s.moduleSuffix(scope)) +} + +var _ sdkLibraryComponentNamingScheme = (*frameworkModulesNamingScheme)(nil) + // java_sdk_library is a special Java library that provides optional platform APIs to apps. // In practice, it can be viewed as a combination of several modules: 1) stubs library that clients // are linked against to, 2) droiddoc module that internally generates API stubs source files, @@ -994,6 +1582,10 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { // the runtime lib to the classpath at runtime if requested via <uses-library>. func SdkLibraryFactory() android.Module { module := &SdkLibrary{} + + // Initialize information common between source and prebuilt. + module.initCommon(&module.ModuleBase) + module.InitSdkLibraryProperties() android.InitApexModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -1006,10 +1598,27 @@ func SdkLibraryFactory() android.Module { module.scopeToProperties = scopeToProperties // Add the properties containing visibility rules so that they are checked. + android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility) android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility) android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) - module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { module.CreateInternalModules(ctx) }) + module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + // If no implementation is required then it cannot be used as a shared library + // either. + if !module.requiresRuntimeImplementationLibrary() { + // If shared_library has been explicitly set to true then it is incompatible + // with api_only: true. + if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) { + ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true") + } + // Set shared_library: false. + module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false) + } + + if module.initCommonAfterDefaultsApplied(ctx) { + module.CreateInternalModules(ctx) + } + }) return module } @@ -1030,10 +1639,10 @@ type sdkLibraryScopeProperties struct { Stub_srcs []string `android:"path"` // The current.txt - Current_api string `android:"path"` + Current_api *string `android:"path"` // The removed.txt - Removed_api string `android:"path"` + Removed_api *string `android:"path"` } type sdkLibraryImportProperties struct { @@ -1105,12 +1714,19 @@ func sdkLibraryImportFactory() android.Module { module.scopeProperties = scopeToProperties module.AddProperties(&module.properties, allScopeProperties) + // Initialize information common between source and prebuilt. + module.initCommon(&module.ModuleBase) + android.InitPrebuiltModule(module, &[]string{""}) android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) - module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { module.createInternalModules(mctx) }) + module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { + if module.initCommonAfterDefaultsApplied(mctx) { + module.createInternalModules(mctx) + } + }) return module } @@ -1136,7 +1752,9 @@ func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHo module.createJavaImportForStubs(mctx, apiScope, scopeProperties) - module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties) + if len(scopeProperties.Stub_srcs) > 0 { + module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties) + } } javaSdkLibraries := javaSdkLibraries(mctx.Config()) @@ -1148,47 +1766,37 @@ func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHo func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { // Creates a java import for the jar with ".stubs" suffix props := struct { - Name *string - Soc_specific *bool - Device_specific *bool - Product_specific *bool - System_ext_specific *bool - Sdk_version *string - Libs []string - Jars []string - Prefer *bool + Name *string + Sdk_version *string + Libs []string + Jars []string + Prefer *bool }{} - props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName())) + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) props.Sdk_version = scopeProperties.Sdk_version // Prepend any of the libs from the legacy public properties to the libs for each of the // scopes to avoid having to duplicate them in each scope. props.Libs = append(module.properties.Libs, scopeProperties.Libs...) props.Jars = scopeProperties.Jars - if module.SocSpecific() { - props.Soc_specific = proptools.BoolPtr(true) - } else if module.DeviceSpecific() { - props.Device_specific = proptools.BoolPtr(true) - } else if module.ProductSpecific() { - props.Product_specific = proptools.BoolPtr(true) - } else if module.SystemExtSpecific() { - props.System_ext_specific = proptools.BoolPtr(true) - } - // If the build should use prebuilt sdks then set prefer to true on the stubs library. - // That will cause the prebuilt version of the stubs to override the source version. - if mctx.Config().UnbundledBuildUsePrebuiltSdks() { - props.Prefer = proptools.BoolPtr(true) - } - mctx.CreateModule(ImportFactory, &props) + + // The imports are preferred if the java_sdk_library_import is preferred. + props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) + + mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { props := struct { - Name *string - Srcs []string + Name *string + Srcs []string + Prefer *bool }{} - props.Name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName())) + props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope)) props.Srcs = scopeProperties.Stub_srcs mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) + + // The stubs source is preferred if the java_sdk_library_import is preferred. + props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) } func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1198,46 +1806,49 @@ func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) } // Add dependencies to the prebuilt stubs library - ctx.AddVariationDependencies(nil, apiScope.stubsTag, apiScope.stubsModuleName(module.BaseModuleName())) + ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) + + if len(scopeProperties.Stub_srcs) > 0 { + // Add dependencies to the prebuilt stubs source library + ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope)) + } } } +func (module *sdkLibraryImport) OutputFiles(tag string) (android.Paths, error) { + return module.commonOutputFiles(tag) +} + func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Record the paths to the prebuilt stubs library. + // Record the paths to the prebuilt stubs library and stubs source. ctx.VisitDirectDeps(func(to android.Module) { tag := ctx.OtherModuleDependencyTag(to) - if lib, ok := to.(Dependency); ok { - if scopeTag, ok := tag.(scopeDependencyTag); ok { - apiScope := scopeTag.apiScope - scopePaths := module.getScopePaths(apiScope) - scopePaths.stubsHeaderPath = lib.HeaderJars() - } + // Extract information from any of the scope specific dependencies. + if scopeTag, ok := tag.(scopeDependencyTag); ok { + apiScope := scopeTag.apiScope + scopePaths := module.getScopePathsCreateIfNeeded(apiScope) + + // Extract information from the dependency. The exact information extracted + // is determined by the nature of the dependency which is determined by the tag. + scopeTag.extractDepInfo(ctx, to, scopePaths) } }) -} -func (module *sdkLibraryImport) sdkJars( - ctx android.BaseModuleContext, - sdkVersion sdkSpec) android.Paths { - - // If a specific numeric version has been requested then use prebuilt versions of the sdk. - if sdkVersion.version.isNumbered() { - return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion) - } + // Populate the scope paths with information from the properties. + for apiScope, scopeProperties := range module.scopeProperties { + if len(scopeProperties.Jars) == 0 { + continue + } - var apiScope *apiScope - switch sdkVersion.kind { - case sdkSystem: - apiScope = apiScopeSystem - case sdkTest: - apiScope = apiScopeTest - default: - apiScope = apiScopePublic + paths := module.getScopePathsCreateIfNeeded(apiScope) + paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api) + paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api) } +} - paths := module.getScopePaths(apiScope) - return paths.stubsHeaderPath +func (module *sdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths { + return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) } // to satisfy SdkLibraryDependency interface @@ -1392,6 +2003,13 @@ type sdkLibrarySdkMemberProperties struct { // The Java stubs source files. Stub_srcs []string + + // The naming scheme. + Naming_scheme *string + + // True if the java_sdk_library_import is for a shared library, false + // otherwise. + Shared_library *bool } type scopeProperties struct { @@ -1407,26 +2025,39 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe s.Scopes = make(map[*apiScope]scopeProperties) for _, apiScope := range allApiScopes { - paths := sdk.getScopePaths(apiScope) + paths := sdk.findScopePaths(apiScope) + if paths == nil { + continue + } + jars := paths.stubsImplPath if len(jars) > 0 { properties := scopeProperties{} properties.Jars = jars - properties.SdkVersion = apiScope.sdkVersion - properties.StubsSrcJar = paths.stubsSrcJar - properties.CurrentApiFile = paths.currentApiFilePath - properties.RemovedApiFile = paths.removedApiFilePath + properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope) + properties.StubsSrcJar = paths.stubsSrcJar.Path() + properties.CurrentApiFile = paths.currentApiFilePath.Path() + properties.RemovedApiFile = paths.removedApiFilePath.Path() s.Scopes[apiScope] = properties } } s.Libs = sdk.properties.Libs + s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme + s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary()) } func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { + if s.Naming_scheme != nil { + propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme)) + } + if s.Shared_library != nil { + propertySet.AddProperty("shared_library", *s.Shared_library) + } + for _, apiScope := range allApiScopes { if properties, ok := s.Scopes[apiScope]; ok { - scopeSet := propertySet.AddPropertySet(apiScope.name) + scopeSet := propertySet.AddPropertySet(apiScope.propertyName) scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name) diff --git a/java/sdk_test.go b/java/sdk_test.go index 088db9e70..fb8646313 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -83,6 +83,16 @@ func TestClasspath(t *testing.T) { }, { + name: "sdk v30", + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "current", properties: `sdk_version: "current",`, bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"}, @@ -110,6 +120,16 @@ func TestClasspath(t *testing.T) { }, { + name: "system_30", + properties: `sdk_version: "system_30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "test_current", properties: `sdk_version: "test_current",`, bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"}, @@ -176,12 +196,24 @@ func TestClasspath(t *testing.T) { }, { + name: "unbundled sdk v30", + unbundled: true, + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, + { + name: "unbundled current", unbundled: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, + system: "sdk_public_current_system_modules", java8classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/current/public/framework.aidl", }, @@ -189,27 +221,30 @@ func TestClasspath(t *testing.T) { name: "pdk default", pdk: true, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk current", pdk: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk 29", pdk: true, properties: `sdk_version: "29",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "module_current", @@ -292,12 +327,16 @@ func TestClasspath(t *testing.T) { if testcase.system == "none" { system = "--system=none" } else if testcase.system != "" { - system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + dir := "" + if strings.HasPrefix(testcase.system, "sdk_public_") { + dir = "prebuilts/sdk" + } + system = "--system=" + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system") // The module-relative parts of these paths are hardcoded in system_modules.go: systemDeps = []string{ - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "modules"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "release"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "modules"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "release"), } } diff --git a/java/testing.go b/java/testing.go index 6929bb724..faf4d32b4 100644 --- a/java/testing.go +++ b/java/testing.go @@ -55,36 +55,54 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "assets_a/a": nil, "assets_b/b": nil, - "prebuilts/sdk/14/public/android.jar": nil, - "prebuilts/sdk/14/public/framework.aidl": nil, - "prebuilts/sdk/14/system/android.jar": nil, - "prebuilts/sdk/17/public/android.jar": nil, - "prebuilts/sdk/17/public/framework.aidl": nil, - "prebuilts/sdk/17/system/android.jar": nil, - "prebuilts/sdk/29/public/android.jar": nil, - "prebuilts/sdk/29/public/framework.aidl": nil, - "prebuilts/sdk/29/system/android.jar": nil, - "prebuilts/sdk/29/system/foo.jar": nil, - "prebuilts/sdk/current/core/android.jar": nil, - "prebuilts/sdk/current/public/android.jar": nil, - "prebuilts/sdk/current/public/framework.aidl": nil, - "prebuilts/sdk/current/public/core.jar": nil, - "prebuilts/sdk/current/system/android.jar": nil, - "prebuilts/sdk/current/test/android.jar": nil, - "prebuilts/sdk/28/public/api/foo.txt": nil, - "prebuilts/sdk/28/system/api/foo.txt": nil, - "prebuilts/sdk/28/test/api/foo.txt": nil, - "prebuilts/sdk/28/public/api/foo-removed.txt": nil, - "prebuilts/sdk/28/system/api/foo-removed.txt": nil, - "prebuilts/sdk/28/test/api/foo-removed.txt": nil, - "prebuilts/sdk/28/public/api/bar.txt": nil, - "prebuilts/sdk/28/system/api/bar.txt": nil, - "prebuilts/sdk/28/test/api/bar.txt": nil, - "prebuilts/sdk/28/public/api/bar-removed.txt": nil, - "prebuilts/sdk/28/system/api/bar-removed.txt": nil, - "prebuilts/sdk/28/test/api/bar-removed.txt": nil, - "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, - "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), + "prebuilts/sdk/14/public/android.jar": nil, + "prebuilts/sdk/14/public/framework.aidl": nil, + "prebuilts/sdk/14/system/android.jar": nil, + "prebuilts/sdk/17/public/android.jar": nil, + "prebuilts/sdk/17/public/framework.aidl": nil, + "prebuilts/sdk/17/system/android.jar": nil, + "prebuilts/sdk/29/public/android.jar": nil, + "prebuilts/sdk/29/public/framework.aidl": nil, + "prebuilts/sdk/29/system/android.jar": nil, + "prebuilts/sdk/29/system/foo.jar": nil, + "prebuilts/sdk/30/public/android.jar": nil, + "prebuilts/sdk/30/public/framework.aidl": nil, + "prebuilts/sdk/30/system/android.jar": nil, + "prebuilts/sdk/30/system/foo.jar": nil, + "prebuilts/sdk/30/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/core/android.jar": nil, + "prebuilts/sdk/current/public/android.jar": nil, + "prebuilts/sdk/current/public/framework.aidl": nil, + "prebuilts/sdk/current/public/core.jar": nil, + "prebuilts/sdk/current/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/system/android.jar": nil, + "prebuilts/sdk/current/test/android.jar": nil, + "prebuilts/sdk/28/public/api/foo.txt": nil, + "prebuilts/sdk/28/system/api/foo.txt": nil, + "prebuilts/sdk/28/test/api/foo.txt": nil, + "prebuilts/sdk/28/public/api/foo-removed.txt": nil, + "prebuilts/sdk/28/system/api/foo-removed.txt": nil, + "prebuilts/sdk/28/test/api/foo-removed.txt": nil, + "prebuilts/sdk/28/public/api/bar.txt": nil, + "prebuilts/sdk/28/system/api/bar.txt": nil, + "prebuilts/sdk/28/test/api/bar.txt": nil, + "prebuilts/sdk/28/public/api/bar-removed.txt": nil, + "prebuilts/sdk/28/system/api/bar-removed.txt": nil, + "prebuilts/sdk/28/test/api/bar-removed.txt": nil, + "prebuilts/sdk/30/public/api/foo.txt": nil, + "prebuilts/sdk/30/system/api/foo.txt": nil, + "prebuilts/sdk/30/test/api/foo.txt": nil, + "prebuilts/sdk/30/public/api/foo-removed.txt": nil, + "prebuilts/sdk/30/system/api/foo-removed.txt": nil, + "prebuilts/sdk/30/test/api/foo-removed.txt": nil, + "prebuilts/sdk/30/public/api/bar.txt": nil, + "prebuilts/sdk/30/system/api/bar.txt": nil, + "prebuilts/sdk/30/test/api/bar.txt": nil, + "prebuilts/sdk/30/public/api/bar-removed.txt": nil, + "prebuilts/sdk/30/system/api/bar-removed.txt": nil, + "prebuilts/sdk/30/test/api/bar-removed.txt": nil, + "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, + "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), "prebuilts/apk/app.apk": nil, "prebuilts/apk/app_arm.apk": nil, @@ -92,6 +110,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/apk/app_xhdpi.apk": nil, "prebuilts/apk/app_xxhdpi.apk": nil, + "prebuilts/apks/app.apks": nil, + // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, "build/make/target/product/security/testkey": nil, @@ -116,6 +136,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "cert/new_cert.x509.pem": nil, "cert/new_cert.pk8": nil, + "lineage.bin": nil, "testdata/data": nil, @@ -209,6 +230,22 @@ func GatherRequiredDepsForTest() string { system_modules: "core-platform-api-stubs-system-modules", installable: true, } + + java_library { + name: "android.test.base", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "core-platform-api-stubs-system-modules", + installable: true, + } + + java_library { + name: "android.test.mock", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "core-platform-api-stubs-system-modules", + installable: true, + } ` systemModules := []string{ diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go index 99e29dc0f..d6e2c0a75 100644 --- a/remoteexec/remoteexec.go +++ b/remoteexec/remoteexec.go @@ -75,6 +75,9 @@ type REParams struct { // OutputFiles is a list of output file paths or ninja variables as placeholders for rule // outputs. OutputFiles []string + // OutputDirectories is a list of output directories or ninja variables as placeholders for + // rule output directories. + OutputDirectories []string // ToolchainInputs is a list of paths or ninja variables pointing to the location of // toolchain binaries used by the rule. ToolchainInputs []string @@ -99,7 +102,7 @@ func (r *REParams) Template() string { return "${remoteexec.Wrapper}" + r.wrapperArgs() } -// NoVarTemplate generate the remote execution wrapper template without variables, to be used in +// NoVarTemplate generates the remote execution wrapper template without variables, to be used in // RuleBuilder. func (r *REParams) NoVarTemplate(cfg android.Config) string { return wrapper(cfg) + r.wrapperArgs() @@ -151,6 +154,10 @@ func (r *REParams) wrapperArgs() string { args += " --output_files=" + strings.Join(r.OutputFiles, ",") } + if len(r.OutputDirectories) > 0 { + args += " --output_directories=" + strings.Join(r.OutputDirectories, ",") + } + if len(r.ToolchainInputs) > 0 { args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",") } @@ -159,7 +166,9 @@ func (r *REParams) wrapperArgs() string { } // StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a -// locally executable rule and the second rule is a remotely executable rule. +// locally executable rule and the second rule is a remotely executable rule. commonArgs are args +// used for both the local and remotely executable rules. reArgs are used only for remote +// execution. func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) { ruleParamsRE := ruleParams ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "") @@ -169,6 +178,22 @@ func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.R ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...) } +// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first +// rule is a locally executable rule and the second rule is a remotely executable rule. This +// function supports multiple remote execution wrappers placed in the template when commands are +// chained together with &&. commonArgs are args used for both the local and remotely executable +// rules. reArgs are args used only for remote execution. +func MultiCommandStaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams map[string]*REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) { + ruleParamsRE := ruleParams + for k, v := range reParams { + ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "") + ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template()) + } + + return ctx.AndroidStaticRule(name, ruleParams, commonArgs...), + ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...) +} + // EnvOverrideFunc retrieves a variable func that evaluates to the value of the given environment // variable if set, otherwise the given default. func EnvOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string { diff --git a/rust/config/x86_darwin_host.go b/rust/config/x86_darwin_host.go index 7cfc59cec..4c16693f3 100644 --- a/rust/config/x86_darwin_host.go +++ b/rust/config/x86_darwin_host.go @@ -62,7 +62,11 @@ func (t *toolchainDarwinX8664) RustTriple() string { return "x86_64-apple-darwin" } -func (t *toolchainDarwin) ShlibSuffix() string { +func (t *toolchainDarwin) SharedLibSuffix() string { + return ".dylib" +} + +func (t *toolchainDarwin) ProcMacroSuffix() string { return ".dylib" } diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh index 770adc98a..f836ea9fa 100755 --- a/scripts/build-mainline-modules.sh +++ b/scripts/build-mainline-modules.sh @@ -19,6 +19,7 @@ MODULES_SDK_AND_EXPORTS=( conscrypt-module-sdk conscrypt-module-test-exports conscrypt-module-host-exports + runtime-module-sdk ) # We want to create apex modules for all supported architectures. diff --git a/scripts/package-check.sh b/scripts/package-check.sh index f982e8244..d7e602f31 100755 --- a/scripts/package-check.sh +++ b/scripts/package-check.sh @@ -52,6 +52,7 @@ zip_contents=`zipinfo -1 $jar_file` # Check all class file names against the expected prefixes. old_ifs=${IFS} IFS=$'\n' +failed=false for zip_entry in ${zip_contents}; do # Check the suffix. if [[ "${zip_entry}" = *.class ]]; then @@ -65,8 +66,11 @@ for zip_entry in ${zip_contents}; do done if [[ "${found}" == "false" ]]; then echo "Class file ${zip_entry} is outside specified packages." - exit 1 + failed=true fi fi done +if [[ "${failed}" == "true" ]]; then + exit 1 +fi IFS=${old_ifs} diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index dded15360..4a090814d 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -401,7 +401,6 @@ func TestSnapshotWithCcBinary(t *testing.T) { "Test.cpp", ], compile_multilib: "both", - stl: "none", } `) @@ -494,6 +493,7 @@ cc_prebuilt_binary { device_supported: false, host_supported: true, installable: false, + stl: "none", target: { linux_glibc: { compile_multilib: "both", @@ -518,6 +518,7 @@ cc_prebuilt_binary { prefer: false, device_supported: false, host_supported: true, + stl: "none", target: { linux_glibc: { compile_multilib: "both", @@ -557,6 +558,90 @@ module_exports_snapshot { ) } +// Test that we support the necessary flags for the linker binary, which is +// special in several ways. +func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) { + // b/145598135 - Generating host snapshots for anything other than linux is not supported. + SkipIfNotLinux(t) + + result := testSdkWithCc(t, ` + module_exports { + name: "mymodule_exports", + host_supported: true, + device_supported: false, + native_binaries: ["linker"], + } + + cc_binary { + name: "linker", + host_supported: true, + static_executable: true, + nocrt: true, + stl: "none", + srcs: [ + "Test.cpp", + ], + compile_multilib: "both", + } + `) + + result.CheckSnapshot("mymodule_exports", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_binary { + name: "mymodule_exports_linker@current", + sdk_member_name: "linker", + device_supported: false, + host_supported: true, + installable: false, + stl: "none", + static_executable: true, + nocrt: true, + compile_multilib: "both", + arch: { + x86_64: { + srcs: ["x86_64/bin/linker"], + }, + x86: { + srcs: ["x86/bin/linker"], + }, + }, +} + +cc_prebuilt_binary { + name: "linker", + prefer: false, + device_supported: false, + host_supported: true, + stl: "none", + static_executable: true, + nocrt: true, + compile_multilib: "both", + arch: { + x86_64: { + srcs: ["x86_64/bin/linker"], + }, + x86: { + srcs: ["x86/bin/linker"], + }, + }, +} + +module_exports_snapshot { + name: "mymodule_exports@current", + device_supported: false, + host_supported: true, + native_binaries: ["mymodule_exports_linker@current"], +} +`), + checkAllCopyRules(` +.intermediates/linker/linux_glibc_x86_64/linker -> x86_64/bin/linker +.intermediates/linker/linux_glibc_x86/linker -> x86/bin/linker +`), + ) +} + func TestSnapshotWithCcSharedLibrary(t *testing.T) { result := testSdkWithCc(t, ` sdk { diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index 560a6b856..f8e9fc163 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -989,6 +989,7 @@ func TestSnapshotWithJavaSdkLibrary(t *testing.T) { apex_available: ["//apex_available:anyapex"], srcs: ["Test.java"], sdk_version: "current", + shared_library: false, stubs_library_visibility: ["//other"], stubs_source_visibility: ["//another"], } @@ -1002,6 +1003,7 @@ java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", apex_available: ["//apex_available:anyapex"], + shared_library: false, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1029,6 +1031,7 @@ java_sdk_library_import { name: "myjavalib", prefer: false, apex_available: ["//apex_available:anyapex"], + shared_library: false, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1075,7 +1078,132 @@ sdk_snapshot { ) } -func TestSnapshotWithJavaSdkLibrary_ApiSurfaces(t *testing.T) { +func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) { + result := testSdkWithJava(t, ` + sdk { + name: "mysdk", + java_sdk_libs: ["myjavalib"], + } + + java_sdk_library { + name: "myjavalib", + srcs: ["Test.java"], + sdk_version: "none", + system_modules: "none", + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "mysdk_myjavalib@current", + sdk_member_name: "myjavalib", + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "none", + }, +} + +java_sdk_library_import { + name: "myjavalib", + prefer: false, + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "none", + }, +} + +sdk_snapshot { + name: "mysdk@current", + java_sdk_libs: ["mysdk_myjavalib@current"], +} +`), + checkAllCopyRules(` +.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt +`), + checkMergeZips( + ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", + ), + ) +} + +func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { + result := testSdkWithJava(t, ` + sdk { + name: "mysdk", + java_sdk_libs: ["myjavalib"], + } + + java_sdk_library { + name: "myjavalib", + srcs: ["Test.java"], + sdk_version: "module_current", + public: { + enabled: true, + sdk_version: "module_current", + }, + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "mysdk_myjavalib@current", + sdk_member_name: "myjavalib", + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "module_current", + }, +} + +java_sdk_library_import { + name: "myjavalib", + prefer: false, + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "module_current", + }, +} + +sdk_snapshot { + name: "mysdk@current", + java_sdk_libs: ["mysdk_myjavalib@current"], +} +`), + checkAllCopyRules(` +.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt +`), + checkMergeZips( + ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", + ), + ) +} + +func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) { result := testSdkWithJava(t, ` sdk { name: "mysdk", @@ -1104,6 +1232,7 @@ java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", apex_available: ["//apex_available:anyapex"], + shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1124,6 +1253,7 @@ java_sdk_library_import { name: "myjavalib", prefer: false, apex_available: ["//apex_available:anyapex"], + shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1192,6 +1322,7 @@ java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", apex_available: ["//apex_available:anyapex"], + shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1207,10 +1338,10 @@ java_sdk_library_import { sdk_version: "system_current", }, module_lib: { - jars: ["sdk_library/module_lib/myjavalib-stubs.jar"], - stub_srcs: ["sdk_library/module_lib/myjavalib_stub_sources"], - current_api: "sdk_library/module_lib/myjavalib.txt", - removed_api: "sdk_library/module_lib/myjavalib-removed.txt", + jars: ["sdk_library/module-lib/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"], + current_api: "sdk_library/module-lib/myjavalib.txt", + removed_api: "sdk_library/module-lib/myjavalib-removed.txt", sdk_version: "module_current", }, } @@ -1219,6 +1350,7 @@ java_sdk_library_import { name: "myjavalib", prefer: false, apex_available: ["//apex_available:anyapex"], + shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], @@ -1234,10 +1366,10 @@ java_sdk_library_import { sdk_version: "system_current", }, module_lib: { - jars: ["sdk_library/module_lib/myjavalib-stubs.jar"], - stub_srcs: ["sdk_library/module_lib/myjavalib_stub_sources"], - current_api: "sdk_library/module_lib/myjavalib.txt", - removed_api: "sdk_library/module_lib/myjavalib-removed.txt", + jars: ["sdk_library/module-lib/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"], + current_api: "sdk_library/module-lib/myjavalib.txt", + removed_api: "sdk_library/module-lib/myjavalib-removed.txt", sdk_version: "module_current", }, } @@ -1254,14 +1386,83 @@ sdk_snapshot { .intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt -.intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module_lib/myjavalib-stubs.jar -.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module_lib/myjavalib.txt -.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module_lib/myjavalib-removed.txt +.intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar +.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt +.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib-removed.txt `), checkMergeZips( ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", ".intermediates/mysdk/common_os/tmp/sdk_library/system/myjavalib_stub_sources.zip", - ".intermediates/mysdk/common_os/tmp/sdk_library/module_lib/myjavalib_stub_sources.zip", + ".intermediates/mysdk/common_os/tmp/sdk_library/module-lib/myjavalib_stub_sources.zip", + ), + ) +} + +func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) { + result := testSdkWithJava(t, ` + sdk { + name: "mysdk", + java_sdk_libs: ["myjavalib"], + } + + java_sdk_library { + name: "myjavalib", + apex_available: ["//apex_available:anyapex"], + srcs: ["Test.java"], + sdk_version: "current", + naming_scheme: "framework-modules", + public: { + enabled: true, + }, + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "mysdk_myjavalib@current", + sdk_member_name: "myjavalib", + apex_available: ["//apex_available:anyapex"], + naming_scheme: "framework-modules", + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "current", + }, +} + +java_sdk_library_import { + name: "myjavalib", + prefer: false, + apex_available: ["//apex_available:anyapex"], + naming_scheme: "framework-modules", + shared_library: true, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "current", + }, +} + +sdk_snapshot { + name: "mysdk@current", + java_sdk_libs: ["mysdk_myjavalib@current"], +} +`), + checkAllCopyRules(` +.intermediates/myjavalib-stubs-publicapi/android_common/javac/myjavalib-stubs-publicapi.jar -> sdk_library/public/myjavalib-stubs.jar +.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib.txt +.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib-removed.txt +`), + checkMergeZips( + ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", ), ) } diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index ae1a4923a..56be7417b 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -103,6 +103,7 @@ func TestSnapshotVisibility(t *testing.T) { "myjavalib", "mypublicjavalib", "mydefaultedjavalib", + "myprivatejavalib", ], } @@ -140,6 +141,14 @@ func TestSnapshotVisibility(t *testing.T) { system_modules: "none", sdk_version: "none", } + + java_library { + name: "myprivatejavalib", + srcs: ["Test.java"], + visibility: ["//visibility:private"], + system_modules: "none", + sdk_version: "none", + } ` result := testSdkWithFs(t, ``, @@ -155,14 +164,20 @@ func TestSnapshotVisibility(t *testing.T) { java_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", - visibility: ["//other/foo:__pkg__"], + visibility: [ + "//other/foo", + "//package", + ], jars: ["java/myjavalib.jar"], } java_import { name: "myjavalib", prefer: false, - visibility: ["//other/foo:__pkg__"], + visibility: [ + "//other/foo", + "//package", + ], jars: ["java/myjavalib.jar"], } @@ -183,27 +198,48 @@ java_import { java_import { name: "mysdk_mydefaultedjavalib@current", sdk_member_name: "mydefaultedjavalib", - visibility: ["//other/bar:__pkg__"], + visibility: [ + "//other/bar", + "//package", + ], jars: ["java/mydefaultedjavalib.jar"], } java_import { name: "mydefaultedjavalib", prefer: false, - visibility: ["//other/bar:__pkg__"], + visibility: [ + "//other/bar", + "//package", + ], jars: ["java/mydefaultedjavalib.jar"], } +java_import { + name: "mysdk_myprivatejavalib@current", + sdk_member_name: "myprivatejavalib", + visibility: ["//package"], + jars: ["java/myprivatejavalib.jar"], +} + +java_import { + name: "myprivatejavalib", + prefer: false, + visibility: ["//package"], + jars: ["java/myprivatejavalib.jar"], +} + sdk_snapshot { name: "mysdk@current", visibility: [ - "//other/foo:__pkg__", + "//other/foo", "//package:__subpackages__", ], java_header_libs: [ "mysdk_myjavalib@current", "mysdk_mypublicjavalib@current", "mysdk_mydefaultedjavalib@current", + "mysdk_myprivatejavalib@current", ], } `)) diff --git a/sdk/update.go b/sdk/update.go index 476a4a5ea..1ba58064d 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -350,6 +350,9 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro bp = newGeneratedFile(ctx, "snapshot", "Android.bp") generateBpContents(&bp.generatedContents, bpFile) + contents := bp.content.String() + syntaxCheckSnapshotBpFile(ctx, contents) + bp.build(pctx, ctx, nil) filesToZip := builder.filesToZip @@ -394,6 +397,36 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro return outputZipFile } +// Check the syntax of the generated Android.bp file contents and if they are +// invalid then log an error with the contents (tagged with line numbers) and the +// errors that were found so that it is easy to see where the problem lies. +func syntaxCheckSnapshotBpFile(ctx android.ModuleContext, contents string) { + errs := android.CheckBlueprintSyntax(ctx, "Android.bp", contents) + if len(errs) != 0 { + message := &strings.Builder{} + _, _ = fmt.Fprint(message, `errors in generated Android.bp snapshot: + +Generated Android.bp contents +======================================================================== +`) + for i, line := range strings.Split(contents, "\n") { + _, _ = fmt.Fprintf(message, "%6d: %s\n", i+1, line) + } + + _, _ = fmt.Fprint(message, ` +======================================================================== + +Errors found: +`) + + for _, err := range errs { + _, _ = fmt.Fprintf(message, "%s\n", err.Error()) + } + + ctx.ModuleErrorf("%s", message.String()) + } +} + func extractCommonProperties(ctx android.ModuleContext, extractor *commonValueExtractor, commonProperties interface{}, inputPropertiesSlice interface{}) { err := extractor.extractCommonProperties(commonProperties, inputPropertiesSlice) if err != nil { diff --git a/tradefed/autogen.go b/tradefed/autogen.go index 596284beb..be44cac5d 100644 --- a/tradefed/autogen.go +++ b/tradefed/autogen.go @@ -219,31 +219,39 @@ func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigPro } var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{ - Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template", + Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs}", CommandDeps: []string{ "${AutoGenTestConfigScript}", "${EmptyTestConfig}", "$template", }, -}, "name", "template") +}, "name", "template", "extraConfigs") func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, - testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool) android.Path { + testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool, configs []Config) android.Path { path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp) + var configStrings []string if autogenPath != nil { template := "${InstrumentationTestConfigTemplate}" moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp) if moduleTemplate.Valid() { template = moduleTemplate.String() } + for _, config := range configs { + configStrings = append(configStrings, config.Config()) + } + extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent)) + extraConfigs = fmt.Sprintf("--extra-configs '%s'", extraConfigs) + ctx.Build(pctx, android.BuildParams{ Rule: autogenInstrumentationTest, Description: "test config", Input: manifest, Output: autogenPath, Args: map[string]string{ - "name": ctx.ModuleName(), - "template": template, + "name": ctx.ModuleName(), + "template": template, + "extraConfigs": extraConfigs, }, }) return autogenPath diff --git a/ui/build/build.go b/ui/build/build.go index 112273345..89c3fad20 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -141,7 +141,26 @@ func help(ctx Context, config Config, what int) { func Build(ctx Context, config Config, what int) { ctx.Verboseln("Starting build with args:", config.Arguments()) ctx.Verboseln("Environment:", config.Environment().Environ()) - ctx.Verbosef("Total RAM: %dGB", config.TotalRAM()/1024/1024/1024) + + if totalRAM := config.TotalRAM(); totalRAM != 0 { + ram := float32(totalRAM) / (1024 * 1024 * 1024) + ctx.Verbosef("Total RAM: %.3vGB", ram) + + if ram <= 16 { + ctx.Println("************************************************************") + ctx.Printf("You are building on a machine with %.3vGB of RAM\n", ram) + ctx.Println("") + ctx.Println("The minimum required amount of free memory is around 16GB,") + ctx.Println("and even with that, some configurations may not work.") + ctx.Println("") + ctx.Println("If you run into segfaults or other errors, try reducing your") + ctx.Println("-j value.") + ctx.Println("************************************************************") + } else if ram <= float32(config.Parallel()) { + ctx.Printf("Warning: high -j%d count compared to %.3vGB of RAM", config.Parallel(), ram) + ctx.Println("If you run into segfaults or other errors, try a lower -j value") + } + } ctx.BeginTrace(metrics.Total, "total") defer ctx.EndTrace() diff --git a/ui/build/config.go b/ui/build/config.go index 7fcc47199..d66a86cb1 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -737,6 +737,9 @@ func (c *configImpl) HighmemParallel() int { } else if c.totalRAM == 0 { // Couldn't detect the total RAM, don't restrict highmem processes. return parallel + } else if c.totalRAM <= 16*1024*1024*1024 { + // Less than 16GB of ram, restrict to 1 highmem processes + return 1 } else if c.totalRAM <= 32*1024*1024*1024 { // Less than 32GB of ram, restrict to 2 highmem processes return 2 diff --git a/ui/build/ninja.go b/ui/build/ninja.go index 1b13e5d36..fa44cb1e6 100644 --- a/ui/build/ninja.go +++ b/ui/build/ninja.go @@ -39,6 +39,7 @@ func runNinja(ctx Context, config Config) { args := []string{ "-d", "keepdepfile", "-d", "keeprsp", + "-d", "stats", "--frontend_file", fifo, } diff --git a/ui/build/soong.go b/ui/build/soong.go index 2fbf381b6..6a12add78 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -119,6 +119,7 @@ func runSoong(ctx Context, config Config) { cmd := Command(ctx, config, "soong "+name, config.PrebuiltBuildTool("ninja"), "-d", "keepdepfile", + "-d", "stats", "-o", "usesphonyoutputs=yes", "-o", "preremoveoutputs=yes", "-w", "dupbuild=err", diff --git a/ui/status/ninja.go b/ui/status/ninja.go index 9cf2f6a81..a11774cce 100644 --- a/ui/status/ninja.go +++ b/ui/status/ninja.go @@ -174,6 +174,8 @@ func (n *NinjaReader) run() { n.status.Print("warning: " + message) case ninja_frontend.Status_Message_ERROR: n.status.Error(message) + case ninja_frontend.Status_Message_DEBUG: + n.status.Verbose(message) default: n.status.Print(message) } diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go index 7c05eed4b..7ba9de2a9 100644 --- a/ui/status/ninja_frontend/frontend.pb.go +++ b/ui/status/ninja_frontend/frontend.pb.go @@ -3,9 +3,11 @@ package ninja_frontend -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -16,7 +18,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type Status_Message_Level int32 @@ -24,17 +26,21 @@ const ( Status_Message_INFO Status_Message_Level = 0 Status_Message_WARNING Status_Message_Level = 1 Status_Message_ERROR Status_Message_Level = 2 + Status_Message_DEBUG Status_Message_Level = 3 ) var Status_Message_Level_name = map[int32]string{ 0: "INFO", 1: "WARNING", 2: "ERROR", + 3: "DEBUG", } + var Status_Message_Level_value = map[string]int32{ "INFO": 0, "WARNING": 1, "ERROR": 2, + "DEBUG": 3, } func (x Status_Message_Level) Enum() *Status_Message_Level { @@ -42,9 +48,11 @@ func (x Status_Message_Level) Enum() *Status_Message_Level { *p = x return p } + func (x Status_Message_Level) String() string { return proto.EnumName(Status_Message_Level_name, int32(x)) } + func (x *Status_Message_Level) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Status_Message_Level_value, data, "Status_Message_Level") if err != nil { @@ -53,8 +61,9 @@ func (x *Status_Message_Level) UnmarshalJSON(data []byte) error { *x = Status_Message_Level(value) return nil } + func (Status_Message_Level) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 5, 0} + return fileDescriptor_eca3873955a29cfe, []int{0, 5, 0} } type Status struct { @@ -73,16 +82,17 @@ func (m *Status) Reset() { *m = Status{} } func (m *Status) String() string { return proto.CompactTextString(m) } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0} + return fileDescriptor_eca3873955a29cfe, []int{0} } + func (m *Status) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status.Unmarshal(m, b) } func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status.Marshal(b, m, deterministic) } -func (dst *Status) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status.Merge(dst, src) +func (m *Status) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status.Merge(m, src) } func (m *Status) XXX_Size() int { return xxx_messageInfo_Status.Size(m) @@ -147,16 +157,17 @@ func (m *Status_TotalEdges) Reset() { *m = Status_TotalEdges{} } func (m *Status_TotalEdges) String() string { return proto.CompactTextString(m) } func (*Status_TotalEdges) ProtoMessage() {} func (*Status_TotalEdges) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 0} + return fileDescriptor_eca3873955a29cfe, []int{0, 0} } + func (m *Status_TotalEdges) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_TotalEdges.Unmarshal(m, b) } func (m *Status_TotalEdges) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_TotalEdges.Marshal(b, m, deterministic) } -func (dst *Status_TotalEdges) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_TotalEdges.Merge(dst, src) +func (m *Status_TotalEdges) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_TotalEdges.Merge(m, src) } func (m *Status_TotalEdges) XXX_Size() int { return xxx_messageInfo_Status_TotalEdges.Size(m) @@ -188,16 +199,17 @@ func (m *Status_BuildStarted) Reset() { *m = Status_BuildStarted{} } func (m *Status_BuildStarted) String() string { return proto.CompactTextString(m) } func (*Status_BuildStarted) ProtoMessage() {} func (*Status_BuildStarted) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 1} + return fileDescriptor_eca3873955a29cfe, []int{0, 1} } + func (m *Status_BuildStarted) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_BuildStarted.Unmarshal(m, b) } func (m *Status_BuildStarted) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_BuildStarted.Marshal(b, m, deterministic) } -func (dst *Status_BuildStarted) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_BuildStarted.Merge(dst, src) +func (m *Status_BuildStarted) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_BuildStarted.Merge(m, src) } func (m *Status_BuildStarted) XXX_Size() int { return xxx_messageInfo_Status_BuildStarted.Size(m) @@ -232,16 +244,17 @@ func (m *Status_BuildFinished) Reset() { *m = Status_BuildFinished{} } func (m *Status_BuildFinished) String() string { return proto.CompactTextString(m) } func (*Status_BuildFinished) ProtoMessage() {} func (*Status_BuildFinished) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 2} + return fileDescriptor_eca3873955a29cfe, []int{0, 2} } + func (m *Status_BuildFinished) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_BuildFinished.Unmarshal(m, b) } func (m *Status_BuildFinished) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_BuildFinished.Marshal(b, m, deterministic) } -func (dst *Status_BuildFinished) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_BuildFinished.Merge(dst, src) +func (m *Status_BuildFinished) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_BuildFinished.Merge(m, src) } func (m *Status_BuildFinished) XXX_Size() int { return xxx_messageInfo_Status_BuildFinished.Size(m) @@ -276,16 +289,17 @@ func (m *Status_EdgeStarted) Reset() { *m = Status_EdgeStarted{} } func (m *Status_EdgeStarted) String() string { return proto.CompactTextString(m) } func (*Status_EdgeStarted) ProtoMessage() {} func (*Status_EdgeStarted) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 3} + return fileDescriptor_eca3873955a29cfe, []int{0, 3} } + func (m *Status_EdgeStarted) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_EdgeStarted.Unmarshal(m, b) } func (m *Status_EdgeStarted) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_EdgeStarted.Marshal(b, m, deterministic) } -func (dst *Status_EdgeStarted) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_EdgeStarted.Merge(dst, src) +func (m *Status_EdgeStarted) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_EdgeStarted.Merge(m, src) } func (m *Status_EdgeStarted) XXX_Size() int { return xxx_messageInfo_Status_EdgeStarted.Size(m) @@ -353,7 +367,11 @@ type Status_EdgeFinished struct { // Exit status (0 for success). Status *int32 `protobuf:"zigzag32,3,opt,name=status" json:"status,omitempty"` // Edge output, may contain ANSI codes. - Output *string `protobuf:"bytes,4,opt,name=output" json:"output,omitempty"` + Output *string `protobuf:"bytes,4,opt,name=output" json:"output,omitempty"` + // Number of milliseconds spent executing in user mode + UserTime *uint32 `protobuf:"varint,5,opt,name=user_time,json=userTime" json:"user_time,omitempty"` + // Number of milliseconds spent executing in kernel mode + SystemTime *uint32 `protobuf:"varint,6,opt,name=system_time,json=systemTime" json:"system_time,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -363,16 +381,17 @@ func (m *Status_EdgeFinished) Reset() { *m = Status_EdgeFinished{} } func (m *Status_EdgeFinished) String() string { return proto.CompactTextString(m) } func (*Status_EdgeFinished) ProtoMessage() {} func (*Status_EdgeFinished) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 4} + return fileDescriptor_eca3873955a29cfe, []int{0, 4} } + func (m *Status_EdgeFinished) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_EdgeFinished.Unmarshal(m, b) } func (m *Status_EdgeFinished) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_EdgeFinished.Marshal(b, m, deterministic) } -func (dst *Status_EdgeFinished) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_EdgeFinished.Merge(dst, src) +func (m *Status_EdgeFinished) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_EdgeFinished.Merge(m, src) } func (m *Status_EdgeFinished) XXX_Size() int { return xxx_messageInfo_Status_EdgeFinished.Size(m) @@ -411,8 +430,22 @@ func (m *Status_EdgeFinished) GetOutput() string { return "" } +func (m *Status_EdgeFinished) GetUserTime() uint32 { + if m != nil && m.UserTime != nil { + return *m.UserTime + } + return 0 +} + +func (m *Status_EdgeFinished) GetSystemTime() uint32 { + if m != nil && m.SystemTime != nil { + return *m.SystemTime + } + return 0 +} + type Status_Message struct { - // Message priority level (INFO, WARNING, or ERROR). + // Message priority level (DEBUG, INFO, WARNING, ERROR). Level *Status_Message_Level `protobuf:"varint,1,opt,name=level,enum=ninja.Status_Message_Level,def=0" json:"level,omitempty"` // Info/warning/error message from Ninja. Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` @@ -425,16 +458,17 @@ func (m *Status_Message) Reset() { *m = Status_Message{} } func (m *Status_Message) String() string { return proto.CompactTextString(m) } func (*Status_Message) ProtoMessage() {} func (*Status_Message) Descriptor() ([]byte, []int) { - return fileDescriptor_frontend_5a49d9b15a642005, []int{0, 5} + return fileDescriptor_eca3873955a29cfe, []int{0, 5} } + func (m *Status_Message) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Status_Message.Unmarshal(m, b) } func (m *Status_Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Status_Message.Marshal(b, m, deterministic) } -func (dst *Status_Message) XXX_Merge(src proto.Message) { - xxx_messageInfo_Status_Message.Merge(dst, src) +func (m *Status_Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status_Message.Merge(m, src) } func (m *Status_Message) XXX_Size() int { return xxx_messageInfo_Status_Message.Size(m) @@ -462,6 +496,7 @@ func (m *Status_Message) GetMessage() string { } func init() { + proto.RegisterEnum("ninja.Status_Message_Level", Status_Message_Level_name, Status_Message_Level_value) proto.RegisterType((*Status)(nil), "ninja.Status") proto.RegisterType((*Status_TotalEdges)(nil), "ninja.Status.TotalEdges") proto.RegisterType((*Status_BuildStarted)(nil), "ninja.Status.BuildStarted") @@ -469,42 +504,46 @@ func init() { proto.RegisterType((*Status_EdgeStarted)(nil), "ninja.Status.EdgeStarted") proto.RegisterType((*Status_EdgeFinished)(nil), "ninja.Status.EdgeFinished") proto.RegisterType((*Status_Message)(nil), "ninja.Status.Message") - proto.RegisterEnum("ninja.Status_Message_Level", Status_Message_Level_name, Status_Message_Level_value) } -func init() { proto.RegisterFile("frontend.proto", fileDescriptor_frontend_5a49d9b15a642005) } - -var fileDescriptor_frontend_5a49d9b15a642005 = []byte{ - // 496 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xd1, 0x6e, 0xd3, 0x30, - 0x14, 0xa5, 0x69, 0xd3, 0x34, 0x37, 0x6d, 0x28, 0x96, 0x40, 0x59, 0x10, 0xa2, 0xda, 0xd3, 0x78, - 0x20, 0x48, 0xbc, 0x20, 0x10, 0x12, 0xa2, 0xd2, 0x06, 0x43, 0xd0, 0x49, 0xde, 0x24, 0x24, 0x5e, - 0xaa, 0x74, 0xf6, 0x86, 0x51, 0xe2, 0x54, 0xb1, 0xbb, 0x5f, 0xe0, 0x7f, 0x78, 0xe0, 0xfb, 0x90, - 0xaf, 0xed, 0x2c, 0x65, 0x7b, 0xcb, 0xf1, 0x3d, 0xe7, 0xde, 0x73, 0x8f, 0x1d, 0x48, 0xaf, 0xda, - 0x46, 0x6a, 0x2e, 0x59, 0xb1, 0x6d, 0x1b, 0xdd, 0x90, 0x50, 0x0a, 0xf9, 0xab, 0x3c, 0xfc, 0x13, - 0xc1, 0xf8, 0x5c, 0x97, 0x7a, 0xa7, 0xc8, 0x5b, 0x48, 0x74, 0xa3, 0xcb, 0x6a, 0xcd, 0xd9, 0x35, - 0x57, 0xd9, 0x60, 0x31, 0x38, 0x4a, 0x5e, 0x67, 0x05, 0xf2, 0x0a, 0xcb, 0x29, 0x2e, 0x0c, 0xe1, - 0xd8, 0xd4, 0x29, 0xe8, 0xee, 0x9b, 0x7c, 0x80, 0xd9, 0x66, 0x27, 0x2a, 0xb6, 0x56, 0xba, 0x6c, - 0x35, 0x67, 0x59, 0x80, 0xe2, 0x7c, 0x5f, 0xbc, 0x34, 0x94, 0x73, 0xcb, 0xa0, 0xd3, 0x4d, 0x0f, - 0x91, 0x25, 0xa4, 0xb6, 0xc1, 0x95, 0x90, 0x42, 0xfd, 0xe4, 0x2c, 0x1b, 0x62, 0x87, 0xa7, 0xf7, - 0x74, 0x38, 0x71, 0x14, 0x6a, 0x67, 0x7a, 0x48, 0xde, 0xc3, 0xd4, 0x38, 0xef, 0x3c, 0x8c, 0xb0, - 0xc3, 0xc1, 0x7e, 0x07, 0xe3, 0xd7, 0x5b, 0x48, 0xf8, 0x2d, 0x30, 0x2b, 0xa0, 0xba, 0x33, 0x10, - 0xde, 0xb7, 0x82, 0x91, 0x77, 0xf3, 0x71, 0x5c, 0x37, 0xfe, 0x15, 0x44, 0x35, 0x57, 0xaa, 0xbc, - 0xe6, 0xd9, 0x18, 0xa5, 0x8f, 0xf7, 0xa5, 0xdf, 0x6c, 0x91, 0x7a, 0x56, 0xfe, 0x12, 0xe0, 0x36, - 0x4e, 0xf2, 0xfc, 0x6e, 0xfa, 0xb3, 0x7e, 0xc6, 0xf9, 0x17, 0x98, 0xf6, 0x03, 0x24, 0x0b, 0x48, - 0xb6, 0x65, 0x5b, 0x56, 0x15, 0xaf, 0x84, 0xaa, 0x9d, 0xa0, 0x7f, 0x44, 0x32, 0x88, 0x6e, 0x78, - 0xbb, 0x69, 0x14, 0xc7, 0xfb, 0x98, 0x50, 0x0f, 0xf3, 0x87, 0x30, 0xdb, 0x8b, 0x32, 0xff, 0x3b, - 0x80, 0xa4, 0x17, 0x0d, 0x49, 0x21, 0x10, 0xcc, 0xf5, 0x0c, 0x04, 0x23, 0xcf, 0x00, 0x30, 0xd6, - 0xb5, 0x16, 0xb5, 0xed, 0x36, 0xa3, 0x31, 0x9e, 0x5c, 0x88, 0x9a, 0x93, 0x27, 0x30, 0x16, 0x72, - 0xbb, 0xd3, 0x2a, 0x1b, 0x2e, 0x86, 0x47, 0x31, 0x75, 0xc8, 0x38, 0x68, 0x76, 0x1a, 0x0b, 0x23, - 0x2c, 0x78, 0x48, 0x08, 0x8c, 0x18, 0x57, 0x97, 0x98, 0x72, 0x4c, 0xf1, 0xdb, 0xb0, 0x2f, 0x9b, - 0xba, 0x2e, 0x25, 0xc3, 0x04, 0x63, 0xea, 0xa1, 0xad, 0x48, 0xd5, 0x54, 0x3c, 0x8b, 0xec, 0x26, - 0x0e, 0xe6, 0x02, 0xa6, 0xfd, 0x3b, 0xb9, 0x63, 0xfc, 0x00, 0x26, 0x5c, 0xb2, 0xbe, 0xed, 0x88, - 0x4b, 0xe6, 0x4d, 0x2b, 0xbc, 0x1a, 0x7c, 0x6b, 0x8f, 0xa8, 0x43, 0xe6, 0xdc, 0xba, 0xc4, 0x17, - 0x14, 0x53, 0x87, 0xf2, 0xdf, 0x03, 0x88, 0xdc, 0x25, 0x92, 0x37, 0x10, 0x56, 0xfc, 0x86, 0x57, - 0x38, 0x29, 0xfd, 0xff, 0x99, 0x3a, 0x56, 0xf1, 0xd5, 0x50, 0xde, 0x8d, 0x4e, 0x57, 0x27, 0x67, - 0xd4, 0xf2, 0xcd, 0x26, 0xfe, 0x95, 0x04, 0x76, 0x47, 0x07, 0x0f, 0x5f, 0x40, 0x88, 0x7c, 0x32, - 0x01, 0x54, 0xcc, 0x1f, 0x90, 0x04, 0xa2, 0xef, 0x1f, 0xe9, 0xea, 0x74, 0xf5, 0x69, 0x3e, 0x20, - 0x31, 0x84, 0xc7, 0x94, 0x9e, 0xd1, 0x79, 0xb0, 0x24, 0x9f, 0x87, 0x3f, 0x52, 0x9c, 0xb8, 0xf6, - 0x7f, 0xf5, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2e, 0x8c, 0xef, 0xcb, 0xe0, 0x03, 0x00, 0x00, +func init() { + proto.RegisterFile("frontend.proto", fileDescriptor_eca3873955a29cfe) +} + +var fileDescriptor_eca3873955a29cfe = []byte{ + // 539 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0xd1, 0x6e, 0xd3, 0x4a, + 0x10, 0xbd, 0x4e, 0xe2, 0x38, 0x1e, 0x27, 0xb9, 0x61, 0x25, 0x90, 0xeb, 0x0a, 0x35, 0xea, 0x53, + 0x5f, 0x08, 0x12, 0x42, 0x42, 0x20, 0x24, 0x44, 0x44, 0x5a, 0x8a, 0x20, 0x95, 0xb6, 0x45, 0x48, + 0xbc, 0x44, 0x4e, 0x77, 0x5a, 0x8c, 0xec, 0x75, 0xe4, 0xdd, 0x54, 0xe2, 0x37, 0xf8, 0x09, 0xfe, + 0x80, 0xaf, 0xe3, 0x01, 0xed, 0xec, 0xda, 0x75, 0x68, 0xdf, 0x7c, 0x76, 0xce, 0x9c, 0x39, 0x7b, + 0x76, 0x64, 0x18, 0x5f, 0x55, 0xa5, 0xd4, 0x28, 0xc5, 0x6c, 0x53, 0x95, 0xba, 0x64, 0xbe, 0xcc, + 0xe4, 0xf7, 0xf4, 0xf0, 0x4f, 0x00, 0xfd, 0x73, 0x9d, 0xea, 0xad, 0x62, 0x2f, 0x21, 0xd2, 0xa5, + 0x4e, 0xf3, 0x15, 0x8a, 0x6b, 0x54, 0xb1, 0x37, 0xf5, 0x8e, 0xa2, 0x67, 0xf1, 0x8c, 0x78, 0x33, + 0xcb, 0x99, 0x5d, 0x18, 0xc2, 0xc2, 0xd4, 0x39, 0xe8, 0xe6, 0x9b, 0xbd, 0x81, 0xd1, 0x7a, 0x9b, + 0xe5, 0x62, 0xa5, 0x74, 0x5a, 0x69, 0x14, 0x71, 0x87, 0x9a, 0x93, 0xdd, 0xe6, 0xb9, 0xa1, 0x9c, + 0x5b, 0x06, 0x1f, 0xae, 0x5b, 0x88, 0xcd, 0x61, 0x6c, 0x05, 0xae, 0x32, 0x99, 0xa9, 0x6f, 0x28, + 0xe2, 0x2e, 0x29, 0xec, 0xdf, 0xa3, 0x70, 0xec, 0x28, 0xdc, 0xce, 0xac, 0x21, 0x7b, 0x0d, 0x43, + 0xe3, 0xbc, 0xf1, 0xd0, 0x23, 0x85, 0xbd, 0x5d, 0x05, 0xe3, 0xb7, 0xb6, 0x10, 0xe1, 0x2d, 0x30, + 0x57, 0xa0, 0xee, 0xc6, 0x80, 0x7f, 0xdf, 0x15, 0x4c, 0x7b, 0x33, 0x9f, 0xc6, 0x35, 0xe3, 0x9f, + 0x42, 0x50, 0xa0, 0x52, 0xe9, 0x35, 0xc6, 0x7d, 0x6a, 0x7d, 0xb8, 0xdb, 0xfa, 0xc9, 0x16, 0x79, + 0xcd, 0x4a, 0x9e, 0x00, 0xdc, 0xc6, 0xc9, 0x0e, 0xee, 0xa6, 0x3f, 0x6a, 0x67, 0x9c, 0x7c, 0x80, + 0x61, 0x3b, 0x40, 0x36, 0x85, 0x68, 0x93, 0x56, 0x69, 0x9e, 0x63, 0x9e, 0xa9, 0xc2, 0x35, 0xb4, + 0x8f, 0x58, 0x0c, 0xc1, 0x0d, 0x56, 0xeb, 0x52, 0x21, 0xbd, 0xc7, 0x80, 0xd7, 0x30, 0xf9, 0x1f, + 0x46, 0x3b, 0x51, 0x26, 0xbf, 0x3d, 0x88, 0x5a, 0xd1, 0xb0, 0x31, 0x74, 0x32, 0xe1, 0x34, 0x3b, + 0x99, 0x60, 0x8f, 0x01, 0x28, 0xd6, 0x95, 0xce, 0x0a, 0xab, 0x36, 0xe2, 0x21, 0x9d, 0x5c, 0x64, + 0x05, 0xb2, 0x47, 0xd0, 0xcf, 0xe4, 0x66, 0xab, 0x55, 0xdc, 0x9d, 0x76, 0x8f, 0x42, 0xee, 0x90, + 0x71, 0x50, 0x6e, 0x35, 0x15, 0x7a, 0x54, 0xa8, 0x21, 0x63, 0xd0, 0x13, 0xa8, 0x2e, 0x29, 0xe5, + 0x90, 0xd3, 0xb7, 0x61, 0x5f, 0x96, 0x45, 0x91, 0x4a, 0x41, 0x09, 0x86, 0xbc, 0x86, 0xb6, 0x22, + 0x55, 0x99, 0x63, 0x1c, 0xd8, 0x9b, 0x38, 0x98, 0xfc, 0xf2, 0x60, 0xd8, 0x7e, 0x94, 0x3b, 0xce, + 0xf7, 0x60, 0x80, 0x52, 0xb4, 0x7d, 0x07, 0x28, 0x45, 0xed, 0x5a, 0xd1, 0xdb, 0xd0, 0xb2, 0x3d, + 0xe0, 0x0e, 0x99, 0x73, 0x6b, 0x93, 0x56, 0x28, 0xe4, 0x0e, 0xb1, 0x7d, 0x08, 0xb7, 0x0a, 0x2b, + 0xab, 0xe5, 0x93, 0xd6, 0xc0, 0x1c, 0x90, 0xd8, 0x01, 0x44, 0xea, 0x87, 0xd2, 0x58, 0xd8, 0x72, + 0xdf, 0xbe, 0x9f, 0x3d, 0x32, 0x84, 0xe4, 0xa7, 0x07, 0x81, 0xdb, 0x01, 0xf6, 0x02, 0xfc, 0x1c, + 0x6f, 0x30, 0x27, 0x9f, 0xe3, 0x7f, 0xb7, 0xdc, 0xb1, 0x66, 0x1f, 0x0d, 0xe5, 0x55, 0xef, 0x74, + 0x79, 0x7c, 0xc6, 0x2d, 0xdf, 0x04, 0x51, 0x2f, 0x59, 0xc7, 0x46, 0xe4, 0xe0, 0xe1, 0x73, 0xf0, + 0x89, 0xcf, 0x06, 0x40, 0x1d, 0x93, 0xff, 0x58, 0x04, 0xc1, 0x97, 0xb7, 0x7c, 0x79, 0xba, 0x3c, + 0x99, 0x78, 0x2c, 0x04, 0x7f, 0xc1, 0xf9, 0x19, 0x9f, 0x74, 0xcc, 0xe7, 0xbb, 0xc5, 0xfc, 0xf3, + 0xc9, 0xa4, 0x3b, 0x67, 0xef, 0xbb, 0x5f, 0xc7, 0x34, 0x7c, 0x55, 0xff, 0x1f, 0xfe, 0x06, 0x00, + 0x00, 0xff, 0xff, 0xaf, 0x93, 0x48, 0xcf, 0x2a, 0x04, 0x00, 0x00, } diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto index 13fd535dc..baa004668 100644 --- a/ui/status/ninja_frontend/frontend.proto +++ b/ui/status/ninja_frontend/frontend.proto @@ -61,6 +61,10 @@ message Status { optional sint32 status = 3; // Edge output, may contain ANSI codes. optional string output = 4; + // Number of milliseconds spent executing in user mode + optional uint32 user_time = 5; + // Number of milliseconds spent executing in kernel mode + optional uint32 system_time = 6; } message Message { @@ -68,8 +72,9 @@ message Status { INFO = 0; WARNING = 1; ERROR = 2; + DEBUG = 3; } - // Message priority level (INFO, WARNING, or ERROR). + // Message priority level (DEBUG, INFO, WARNING, ERROR). optional Level level = 1 [default = INFO]; // Info/warning/error message from Ninja. optional string message = 2; |