Merge "Make it possible to specify separate rules for native_bridge case"
diff --git a/Android.bp b/Android.bp
index 342ca4c..0b44198 100644
--- a/Android.bp
+++ b/Android.bp
@@ -11,14 +11,6 @@
]
bootstrap_go_package {
- name: "soong-env",
- pkgPath: "android/soong/env",
- srcs: [
- "env/env.go",
- ],
-}
-
-bootstrap_go_package {
name: "soong",
pkgPath: "android/soong",
deps: [
@@ -29,544 +21,6 @@
],
}
-bootstrap_go_package {
- name: "soong-android",
- pkgPath: "android/soong/android",
- deps: [
- "blueprint",
- "blueprint-bootstrap",
- "soong",
- "soong-android-soongconfig",
- "soong-env",
- "soong-shared",
- "soong-ui-metrics_proto",
- ],
- srcs: [
- "android/androidmk.go",
- "android/apex.go",
- "android/api_levels.go",
- "android/arch.go",
- "android/config.go",
- "android/csuite_config.go",
- "android/defaults.go",
- "android/defs.go",
- "android/expand.go",
- "android/filegroup.go",
- "android/hooks.go",
- "android/image.go",
- "android/makevars.go",
- "android/metrics.go",
- "android/module.go",
- "android/mutator.go",
- "android/namespace.go",
- "android/neverallow.go",
- "android/notices.go",
- "android/onceper.go",
- "android/override_module.go",
- "android/package.go",
- "android/package_ctx.go",
- "android/path_properties.go",
- "android/paths.go",
- "android/prebuilt.go",
- "android/prebuilt_etc.go",
- "android/proto.go",
- "android/register.go",
- "android/rule_builder.go",
- "android/sandbox.go",
- "android/sdk.go",
- "android/sh_binary.go",
- "android/singleton.go",
- "android/soong_config_modules.go",
- "android/testing.go",
- "android/util.go",
- "android/variable.go",
- "android/visibility.go",
- "android/vts_config.go",
- "android/writedocs.go",
-
- // Lock down environment access last
- "android/env.go",
- ],
- testSrcs: [
- "android/android_test.go",
- "android/androidmk_test.go",
- "android/arch_test.go",
- "android/config_test.go",
- "android/csuite_config_test.go",
- "android/expand_test.go",
- "android/module_test.go",
- "android/mutator_test.go",
- "android/namespace_test.go",
- "android/neverallow_test.go",
- "android/onceper_test.go",
- "android/package_test.go",
- "android/path_properties_test.go",
- "android/paths_test.go",
- "android/prebuilt_test.go",
- "android/prebuilt_etc_test.go",
- "android/rule_builder_test.go",
- "android/soong_config_modules_test.go",
- "android/util_test.go",
- "android/variable_test.go",
- "android/visibility_test.go",
- "android/vts_config_test.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-android-soongconfig",
- pkgPath: "android/soong/android/soongconfig",
- deps: [
- "blueprint",
- "blueprint-parser",
- "blueprint-proptools",
- ],
- srcs: [
- "android/soongconfig/config.go",
- "android/soongconfig/modules.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-cc-config",
- pkgPath: "android/soong/cc/config",
- deps: [
- "soong-android",
- "soong-remoteexec",
- ],
- srcs: [
- "cc/config/clang.go",
- "cc/config/global.go",
- "cc/config/tidy.go",
- "cc/config/toolchain.go",
- "cc/config/vndk.go",
-
- "cc/config/arm_device.go",
- "cc/config/arm64_device.go",
- "cc/config/arm64_fuchsia_device.go",
- "cc/config/x86_device.go",
- "cc/config/x86_64_device.go",
- "cc/config/x86_64_fuchsia_device.go",
-
- "cc/config/x86_darwin_host.go",
- "cc/config/x86_linux_host.go",
- "cc/config/x86_linux_bionic_host.go",
- "cc/config/x86_windows_host.go",
- ],
- testSrcs: [
- "cc/config/tidy_test.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-cc",
- pkgPath: "android/soong/cc",
- deps: [
- "blueprint",
- "blueprint-pathtools",
- "soong",
- "soong-android",
- "soong-cc-config",
- "soong-genrule",
- "soong-tradefed",
- ],
- srcs: [
- "cc/androidmk.go",
- "cc/builder.go",
- "cc/cc.go",
- "cc/ccdeps.go",
- "cc/check.go",
- "cc/coverage.go",
- "cc/gen.go",
- "cc/linkable.go",
- "cc/lto.go",
- "cc/makevars.go",
- "cc/pgo.go",
- "cc/prebuilt.go",
- "cc/proto.go",
- "cc/rs.go",
- "cc/sanitize.go",
- "cc/sabi.go",
- "cc/sdk.go",
- "cc/snapshot_utils.go",
- "cc/stl.go",
- "cc/strip.go",
- "cc/sysprop.go",
- "cc/tidy.go",
- "cc/util.go",
- "cc/vendor_snapshot.go",
- "cc/vndk.go",
- "cc/vndk_prebuilt.go",
-
- "cc/cflag_artifacts.go",
- "cc/cmakelists.go",
- "cc/compdb.go",
- "cc/compiler.go",
- "cc/installer.go",
- "cc/linker.go",
-
- "cc/binary.go",
- "cc/binary_sdk_member.go",
- "cc/fuzz.go",
- "cc/library.go",
- "cc/library_headers.go",
- "cc/library_sdk_member.go",
- "cc/object.go",
- "cc/test.go",
- "cc/toolchain_library.go",
-
- "cc/ndk_prebuilt.go",
- "cc/ndk_headers.go",
- "cc/ndk_library.go",
- "cc/ndk_sysroot.go",
-
- "cc/llndk_library.go",
-
- "cc/kernel_headers.go",
-
- "cc/genrule.go",
-
- "cc/vendor_public_library.go",
-
- "cc/testing.go",
- ],
- testSrcs: [
- "cc/cc_test.go",
- "cc/compiler_test.go",
- "cc/gen_test.go",
- "cc/genrule_test.go",
- "cc/library_headers_test.go",
- "cc/library_test.go",
- "cc/object_test.go",
- "cc/prebuilt_test.go",
- "cc/proto_test.go",
- "cc/test_data_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-genrule",
- pkgPath: "android/soong/genrule",
- deps: [
- "blueprint",
- "blueprint-pathtools",
- "soong",
- "soong-android",
- "soong-shared",
- ],
- srcs: [
- "genrule/genrule.go",
- ],
- testSrcs: [
- "genrule/genrule_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-phony",
- pkgPath: "android/soong/phony",
- deps: [
- "blueprint",
- "soong-android",
- ],
- srcs: [
- "phony/phony.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-java",
- pkgPath: "android/soong/java",
- deps: [
- "blueprint",
- "blueprint-pathtools",
- "soong",
- "soong-android",
- "soong-cc",
- "soong-dexpreopt",
- "soong-genrule",
- "soong-java-config",
- "soong-tradefed",
- ],
- srcs: [
- "java/aapt2.go",
- "java/aar.go",
- "java/android_manifest.go",
- "java/android_resources.go",
- "java/androidmk.go",
- "java/app_builder.go",
- "java/app.go",
- "java/builder.go",
- "java/device_host_converter.go",
- "java/dex.go",
- "java/dexpreopt.go",
- "java/dexpreopt_bootjars.go",
- "java/dexpreopt_config.go",
- "java/droiddoc.go",
- "java/gen.go",
- "java/genrule.go",
- "java/hiddenapi.go",
- "java/hiddenapi_singleton.go",
- "java/jacoco.go",
- "java/java.go",
- "java/jdeps.go",
- "java/java_resources.go",
- "java/kotlin.go",
- "java/platform_compat_config.go",
- "java/plugin.go",
- "java/prebuilt_apis.go",
- "java/proto.go",
- "java/robolectric.go",
- "java/sdk.go",
- "java/sdk_library.go",
- "java/support_libraries.go",
- "java/sysprop.go",
- "java/system_modules.go",
- "java/testing.go",
- "java/tradefed.go",
- ],
- testSrcs: [
- "java/androidmk_test.go",
- "java/app_test.go",
- "java/device_host_converter_test.go",
- "java/dexpreopt_test.go",
- "java/dexpreopt_bootjars_test.go",
- "java/java_test.go",
- "java/jdeps_test.go",
- "java/kotlin_test.go",
- "java/plugin_test.go",
- "java/sdk_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-java-config",
- pkgPath: "android/soong/java/config",
- deps: [
- "blueprint-proptools",
- "soong-android",
- "soong-remoteexec",
- ],
- srcs: [
- "java/config/config.go",
- "java/config/error_prone.go",
- "java/config/kotlin.go",
- "java/config/makevars.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-rust-config",
- pkgPath: "android/soong/rust/config",
- deps: [
- "soong-android",
- "soong-cc-config",
- ],
- srcs: [
- "rust/config/arm_device.go",
- "rust/config/arm64_device.go",
- "rust/config/global.go",
- "rust/config/toolchain.go",
- "rust/config/whitelist.go",
- "rust/config/x86_darwin_host.go",
- "rust/config/x86_linux_host.go",
- "rust/config/x86_device.go",
- "rust/config/x86_64_device.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-rust",
- pkgPath: "android/soong/rust",
- deps: [
- "soong",
- "soong-android",
- "soong-cc",
- "soong-rust-config",
- ],
- srcs: [
- "rust/androidmk.go",
- "rust/compiler.go",
- "rust/coverage.go",
- "rust/binary.go",
- "rust/builder.go",
- "rust/library.go",
- "rust/prebuilt.go",
- "rust/proc_macro.go",
- "rust/rust.go",
- "rust/test.go",
- "rust/testing.go",
- ],
- testSrcs: [
- "rust/binary_test.go",
- "rust/compiler_test.go",
- "rust/coverage_test.go",
- "rust/library_test.go",
- "rust/rust_test.go",
- "rust/test_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-python",
- pkgPath: "android/soong/python",
- deps: [
- "blueprint",
- "soong-android",
- "soong-tradefed",
- ],
- srcs: [
- "python/androidmk.go",
- "python/binary.go",
- "python/builder.go",
- "python/defaults.go",
- "python/installer.go",
- "python/library.go",
- "python/proto.go",
- "python/python.go",
- "python/test.go",
- ],
- testSrcs: [
- "python/python_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-shared",
- pkgPath: "android/soong/shared",
- srcs: [
- "shared/paths.go",
- ],
-}
-
-bootstrap_go_package {
- name: "soong-tradefed",
- pkgPath: "android/soong/tradefed",
- deps: [
- "blueprint",
- "soong-android",
- ],
- srcs: [
- "tradefed/autogen.go",
- "tradefed/config.go",
- "tradefed/makevars.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-xml",
- pkgPath: "android/soong/xml",
- deps: [
- "blueprint",
- "blueprint-pathtools",
- "soong",
- "soong-android",
- ],
- srcs: [
- "xml/xml.go",
- ],
- testSrcs: [
- "xml/xml_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-apex",
- pkgPath: "android/soong/apex",
- deps: [
- "blueprint",
- "soong",
- "soong-android",
- "soong-cc",
- "soong-java",
- "soong-python",
- ],
- srcs: [
- "apex/androidmk.go",
- "apex/apex.go",
- "apex/builder.go",
- "apex/key.go",
- "apex/prebuilt.go",
- "apex/vndk.go",
- ],
- testSrcs: [
- "apex/apex_test.go",
- "apex/vndk_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-sysprop",
- pkgPath: "android/soong/sysprop",
- deps: [
- "blueprint",
- "soong",
- "soong-android",
- "soong-cc",
- "soong-java",
- ],
- srcs: [
- "sysprop/sysprop_library.go",
- ],
- testSrcs: [
- "sysprop/sysprop_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-sdk",
- pkgPath: "android/soong/sdk",
- deps: [
- "blueprint",
- "soong",
- "soong-android",
- "soong-apex",
- "soong-cc",
- "soong-java",
- ],
- srcs: [
- "sdk/bp.go",
- "sdk/exports.go",
- "sdk/sdk.go",
- "sdk/update.go",
- ],
- testSrcs: [
- "sdk/bp_test.go",
- "sdk/cc_sdk_test.go",
- "sdk/exports_test.go",
- "sdk/java_sdk_test.go",
- "sdk/sdk_test.go",
- "sdk/testing.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
- name: "soong-remoteexec",
- pkgPath: "android/soong/remoteexec",
- deps: [
- "blueprint",
- "soong-android",
- ],
- srcs: [
- "remoteexec/remoteexec.go",
- ],
- testSrcs: [
- "remoteexec/remoteexec_test.go",
- ],
- pluginFor: ["soong_build"],
-}
-
//
// Defaults to enable various configurations of host bionic
//
diff --git a/OWNERS b/OWNERS
index e1db459..adf2b4c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,10 @@
-per-file * = asmundak@google.com,ccross@android.com,dwillemsen@google.com,jungjw@google.com,paulduffin@google.com
+per-file * = asmundak@google.com
+per-file * = ccross@android.com
+per-file * = dwillemsen@google.com
+per-file * = eakammer@google.com
+per-file * = jungjw@google.com
+per-file * = patricearruda@google.com
+per-file * = paulduffin@google.com
per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
diff --git a/README.md b/README.md
index 8b028a8..f1857f8 100644
--- a/README.md
+++ b/README.md
@@ -289,6 +289,9 @@
* `["//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/Android.bp b/android/Android.bp
new file mode 100644
index 0000000..47dbc5d
--- /dev/null
+++ b/android/Android.bp
@@ -0,0 +1,80 @@
+bootstrap_go_package {
+ name: "soong-android",
+ pkgPath: "android/soong/android",
+ deps: [
+ "blueprint",
+ "blueprint-bootstrap",
+ "soong",
+ "soong-android-soongconfig",
+ "soong-env",
+ "soong-shared",
+ "soong-ui-metrics_proto",
+ ],
+ srcs: [
+ "androidmk.go",
+ "apex.go",
+ "api_levels.go",
+ "arch.go",
+ "config.go",
+ "csuite_config.go",
+ "defaults.go",
+ "defs.go",
+ "expand.go",
+ "filegroup.go",
+ "hooks.go",
+ "image.go",
+ "makevars.go",
+ "metrics.go",
+ "module.go",
+ "mutator.go",
+ "namespace.go",
+ "neverallow.go",
+ "notices.go",
+ "onceper.go",
+ "override_module.go",
+ "package.go",
+ "package_ctx.go",
+ "path_properties.go",
+ "paths.go",
+ "prebuilt.go",
+ "proto.go",
+ "register.go",
+ "rule_builder.go",
+ "sandbox.go",
+ "sdk.go",
+ "singleton.go",
+ "soong_config_modules.go",
+ "testing.go",
+ "util.go",
+ "variable.go",
+ "visibility.go",
+ "vts_config.go",
+ "writedocs.go",
+
+ // Lock down environment access last
+ "env.go",
+ ],
+ testSrcs: [
+ "android_test.go",
+ "androidmk_test.go",
+ "arch_test.go",
+ "config_test.go",
+ "csuite_config_test.go",
+ "expand_test.go",
+ "module_test.go",
+ "mutator_test.go",
+ "namespace_test.go",
+ "neverallow_test.go",
+ "onceper_test.go",
+ "package_test.go",
+ "path_properties_test.go",
+ "paths_test.go",
+ "prebuilt_test.go",
+ "rule_builder_test.go",
+ "soong_config_modules_test.go",
+ "util_test.go",
+ "variable_test.go",
+ "visibility_test.go",
+ "vts_config_test.go",
+ ],
+}
diff --git a/android/apex.go b/android/apex.go
index 9056c3d..30152db 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -421,21 +421,16 @@
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 @@
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 ee31c10..59118ce 100644
--- a/android/config.go
+++ b/android/config.go
@@ -897,27 +897,31 @@
}
// 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 46bd3d6..c7c96d5 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 @@
// 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 f5cfe66..82321f4 100644
--- a/android/module.go
+++ b/android/module.go
@@ -19,6 +19,7 @@
"os"
"path"
"path/filepath"
+ "regexp"
"strings"
"text/scanner"
@@ -103,11 +104,15 @@
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
@@ -135,6 +140,13 @@
// GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
GetTagPath() []blueprint.DependencyTag
+ // GetPathString is supposed to be called in visit function passed in WalkDeps()
+ // and returns a multi-line string showing the modules and dependency tags
+ // among them along the top-down dependency path from a start module to current child module.
+ // skipFirst when set to true, the output doesn't include the start module,
+ // which is already printed when this function is used along with ModuleErrorf().
+ GetPathString(skipFirst bool) string
+
AddMissingDependencies(missingDeps []string)
Target() Target
@@ -249,9 +261,6 @@
// 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
@@ -323,6 +332,8 @@
// ["//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,
@@ -799,15 +810,6 @@
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
}
@@ -900,6 +902,13 @@
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() {
@@ -1426,6 +1435,12 @@
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)
}
@@ -1434,6 +1449,10 @@
return b.bp.GetDirectDepWithTag(name, tag)
}
+func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
+ return b.bp
+}
+
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
@@ -1734,6 +1753,41 @@
return b.tagPath
}
+// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
+// a dependency tag.
+var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:blueprint.BaseDependencyTag{}\E(, )?`)
+
+// PrettyPrintTag returns string representation of the tag, but prefers
+// custom String() method if available.
+func PrettyPrintTag(tag blueprint.DependencyTag) string {
+ // Use tag's custom String() method if available.
+ if stringer, ok := tag.(fmt.Stringer); ok {
+ return stringer.String()
+ }
+
+ // Otherwise, get a default string representation of the tag's struct.
+ tagString := fmt.Sprintf("%#v", tag)
+
+ // Remove the boilerplate from BaseDependencyTag as it adds no value.
+ tagString = tagCleaner.ReplaceAllString(tagString, "")
+ return tagString
+}
+
+func (b *baseModuleContext) GetPathString(skipFirst bool) string {
+ sb := strings.Builder{}
+ tagPath := b.GetTagPath()
+ walkPath := b.GetWalkPath()
+ if !skipFirst {
+ sb.WriteString(walkPath[0].String())
+ }
+ for i, m := range walkPath[1:] {
+ sb.WriteString("\n")
+ sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
+ sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
+ }
+ return sb.String()
+}
+
func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
visit(module.(Module))
@@ -2320,4 +2374,10 @@
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 cf09792..be3f712 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -55,6 +55,7 @@
AddNeverAllowRules(createMediaRules()...)
AddNeverAllowRules(createJavaDeviceForHostRules()...)
AddNeverAllowRules(createCcSdkVariantRules()...)
+ AddNeverAllowRules(createUncompressDexRules()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -141,6 +142,7 @@
"external/icu",
"external/okhttp",
"external/wycheproof",
+ "prebuilts",
}
// Core library constraints. The sdk_version: "none" can only be used in core library projects.
@@ -185,6 +187,10 @@
// derive_sdk_prefer32 suppress the platform installation rules, but fails when
// the APEX modules contain the SDK variant and the platform variant still exists.
"frameworks/base/apex/sdkextensions/derive_sdk",
+ // These are for apps and shouldn't be used by non-SDK variant modules.
+ "prebuilts/ndk",
+ "tools/test/graphicsbenchmark/apps/sample_app",
+ "tools/test/graphicsbenchmark/functional_tests/java",
}
platformVariantPropertiesWhitelist := []string{
@@ -209,6 +215,15 @@
}
}
+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 2fc42e3..85c8c59 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -303,6 +303,29 @@
`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 @@
}
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 8bb9a96..3ad27ac 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -43,6 +43,14 @@
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 @@
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 82745a4..a29ec91 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -52,6 +52,9 @@
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 @@
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 @@
}
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 {
+ name := m.base().BaseModuleName()
+ 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()
- name := m.base().BaseModuleName()
- if ctx.OtherModuleExists(name) {
- ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
- p.properties.SourceExists = true
- } else {
- ctx.Rename(name)
+ 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
deleted file mode 100644
index 3dea6d8..0000000
--- a/android/prebuilt_etc.go
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2016 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 android
-
-import "strconv"
-
-// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
-
-func init() {
- RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
- RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
- RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
- RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
- RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
- RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
-}
-
-type prebuiltEtcProperties struct {
- // Source file of this prebuilt.
- Src *string `android:"path,arch_variant"`
-
- // optional subdirectory under which this file is installed into
- Sub_dir *string `android:"arch_variant"`
-
- // optional name for the installed file. If unspecified, name of the module is used as the file name
- Filename *string `android:"arch_variant"`
-
- // when set to true, and filename property is not set, the name for the installed file
- // is the same as the file name of the source file.
- Filename_from_src *bool `android:"arch_variant"`
-
- // Make this module available when building for ramdisk.
- Ramdisk_available *bool
-
- // Make this module available when building for recovery.
- Recovery_available *bool
-
- // Whether this module is directly installable to one of the partitions. Default: true.
- Installable *bool
-}
-
-type PrebuiltEtcModule interface {
- Module
- SubDir() string
- OutputFile() OutputPath
-}
-
-type PrebuiltEtc struct {
- ModuleBase
-
- properties prebuiltEtcProperties
-
- sourceFilePath Path
- outputFilePath OutputPath
- // The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
- installDirBase string
- // The base install location when soc_specific property is set to true, e.g. "firmware" for prebuilt_firmware.
- socInstallDirBase string
- installDirPath InstallPath
- additionalDependencies *Paths
-}
-
-func (p *PrebuiltEtc) inRamdisk() bool {
- return p.ModuleBase.InRamdisk() || p.ModuleBase.InstallInRamdisk()
-}
-
-func (p *PrebuiltEtc) onlyInRamdisk() bool {
- return p.ModuleBase.InstallInRamdisk()
-}
-
-func (p *PrebuiltEtc) InstallInRamdisk() bool {
- return p.inRamdisk()
-}
-
-func (p *PrebuiltEtc) inRecovery() bool {
- return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
-}
-
-func (p *PrebuiltEtc) onlyInRecovery() bool {
- return p.ModuleBase.InstallInRecovery()
-}
-
-func (p *PrebuiltEtc) InstallInRecovery() bool {
- return p.inRecovery()
-}
-
-var _ ImageInterface = (*PrebuiltEtc)(nil)
-
-func (p *PrebuiltEtc) ImageMutatorBegin(ctx BaseModuleContext) {}
-
-func (p *PrebuiltEtc) CoreVariantNeeded(ctx BaseModuleContext) bool {
- return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk()
-}
-
-func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx BaseModuleContext) bool {
- return Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
-}
-
-func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx BaseModuleContext) bool {
- return Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
-}
-
-func (p *PrebuiltEtc) ExtraImageVariations(ctx BaseModuleContext) []string {
- return nil
-}
-
-func (p *PrebuiltEtc) SetImageVariation(ctx BaseModuleContext, variation string, module Module) {
-}
-
-func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
- if p.properties.Src == nil {
- ctx.PropertyErrorf("src", "missing prebuilt source file")
- }
-}
-
-func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
- return PathForModuleSrc(ctx, String(p.properties.Src))
-}
-
-func (p *PrebuiltEtc) InstallDirPath() InstallPath {
- return p.installDirPath
-}
-
-// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
-// additional steps (like validating the src) before the file is installed.
-func (p *PrebuiltEtc) SetAdditionalDependencies(paths Paths) {
- p.additionalDependencies = &paths
-}
-
-func (p *PrebuiltEtc) OutputFile() OutputPath {
- return p.outputFilePath
-}
-
-func (p *PrebuiltEtc) SubDir() string {
- return String(p.properties.Sub_dir)
-}
-
-func (p *PrebuiltEtc) Installable() bool {
- return p.properties.Installable == nil || Bool(p.properties.Installable)
-}
-
-func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
- p.sourceFilePath = PathForModuleSrc(ctx, String(p.properties.Src))
- filename := String(p.properties.Filename)
- filename_from_src := Bool(p.properties.Filename_from_src)
- if filename == "" {
- if filename_from_src {
- filename = p.sourceFilePath.Base()
- } else {
- filename = ctx.ModuleName()
- }
- } else if filename_from_src {
- ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
- return
- }
- p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
-
- // If soc install dir was specified and SOC specific is set, set the installDirPath to the specified
- // socInstallDirBase.
- installBaseDir := p.installDirBase
- if ctx.SocSpecific() && p.socInstallDirBase != "" {
- installBaseDir = p.socInstallDirBase
- }
- p.installDirPath = PathForModuleInstall(ctx, installBaseDir, String(p.properties.Sub_dir))
-
- // This ensures that outputFilePath has the correct name for others to
- // use, as the source file may have a different name.
- ctx.Build(pctx, BuildParams{
- Rule: Cp,
- Output: p.outputFilePath,
- Input: p.sourceFilePath,
- })
-}
-
-func (p *PrebuiltEtc) AndroidMkEntries() []AndroidMkEntries {
- nameSuffix := ""
- if p.inRamdisk() && !p.onlyInRamdisk() {
- nameSuffix = ".ramdisk"
- }
- if p.inRecovery() && !p.onlyInRecovery() {
- nameSuffix = ".recovery"
- }
- return []AndroidMkEntries{AndroidMkEntries{
- Class: "ETC",
- SubName: nameSuffix,
- OutputFile: OptionalPathForPath(p.outputFilePath),
- ExtraEntries: []AndroidMkExtraEntriesFunc{
- func(entries *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())
- 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())
- }
- }
- },
- },
- }}
-}
-
-func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) {
- p.installDirBase = dirBase
- p.AddProperties(&p.properties)
-}
-
-// prebuilt_etc is for a prebuilt artifact that is installed in
-// <partition>/etc/<sub_dir> directory.
-func PrebuiltEtcFactory() Module {
- module := &PrebuiltEtc{}
- InitPrebuiltEtcModule(module, "etc")
- // This module is device-only
- InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
- return module
-}
-
-// prebuilt_etc_host is for a host prebuilt artifact that is installed in
-// $(HOST_OUT)/etc/<sub_dir> directory.
-func PrebuiltEtcHostFactory() Module {
- module := &PrebuiltEtc{}
- InitPrebuiltEtcModule(module, "etc")
- // This module is host-only
- InitAndroidArchModule(module, HostSupported, MultilibCommon)
- return module
-}
-
-// prebuilt_usr_share is for a prebuilt artifact that is installed in
-// <partition>/usr/share/<sub_dir> directory.
-func PrebuiltUserShareFactory() Module {
- module := &PrebuiltEtc{}
- InitPrebuiltEtcModule(module, "usr/share")
- // This module is device-only
- InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
- return module
-}
-
-// prebuild_usr_share_host is for a host prebuilt artifact that is installed in
-// $(HOST_OUT)/usr/share/<sub_dir> directory.
-func PrebuiltUserShareHostFactory() Module {
- module := &PrebuiltEtc{}
- InitPrebuiltEtcModule(module, "usr/share")
- // This module is host-only
- InitAndroidArchModule(module, HostSupported, MultilibCommon)
- return module
-}
-
-// prebuilt_font installs a font in <partition>/fonts directory.
-func PrebuiltFontFactory() Module {
- module := &PrebuiltEtc{}
- InitPrebuiltEtcModule(module, "fonts")
- // This module is device-only
- InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
- return module
-}
-
-// prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system image.
-// If soc_specific property is set to true, the firmware file is installed to the vendor <partition>/firmware
-// directory for vendor image.
-func PrebuiltFirmwareFactory() Module {
- module := &PrebuiltEtc{}
- module.socInstallDirBase = "firmware"
- InitPrebuiltEtcModule(module, "etc/firmware")
- // This module is device-only
- InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
- return module
-}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 8ff5c40..b568f78 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -24,7 +24,7 @@
var prebuiltsTests = []struct {
name string
modules string
- prebuilt bool
+ prebuilt []OsClass
}{
{
name: "no prebuilt",
@@ -32,7 +32,7 @@
source {
name: "bar",
}`,
- prebuilt: false,
+ prebuilt: nil,
},
{
name: "no source prebuilt not preferred",
@@ -42,7 +42,7 @@
prefer: false,
srcs: ["prebuilt_file"],
}`,
- prebuilt: true,
+ prebuilt: []OsClass{Device, Host},
},
{
name: "no source prebuilt preferred",
@@ -52,7 +52,7 @@
prefer: true,
srcs: ["prebuilt_file"],
}`,
- prebuilt: true,
+ prebuilt: []OsClass{Device, Host},
},
{
name: "prebuilt not preferred",
@@ -60,13 +60,13 @@
source {
name: "bar",
}
-
+
prebuilt {
name: "bar",
prefer: false,
srcs: ["prebuilt_file"],
}`,
- prebuilt: false,
+ prebuilt: nil,
},
{
name: "prebuilt preferred",
@@ -74,13 +74,13 @@
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 @@
source {
name: "bar",
}
-
+
prebuilt {
name: "bar",
prefer: false,
}`,
- prebuilt: false,
+ prebuilt: nil,
},
{
name: "prebuilt no file preferred",
@@ -101,12 +101,12 @@
source {
name: "bar",
}
-
+
prebuilt {
name: "bar",
prefer: true,
}`,
- prebuilt: false,
+ prebuilt: nil,
},
{
name: "prebuilt file from filegroup preferred",
@@ -120,7 +120,40 @@
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 @@
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 @@
_, 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 @@
ModuleBase
prebuilt Prebuilt
properties struct {
- Srcs []string `android:"path"`
+ Srcs []string `android:"path,arch_variant"`
}
src Path
}
@@ -230,7 +273,7 @@
m := &prebuiltModule{}
m.AddProperties(&m.properties)
InitPrebuiltModule(m, &m.properties.Srcs)
- InitAndroidModule(m)
+ InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
return m
}
@@ -260,7 +303,7 @@
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 @@
func newSourceModule() Module {
m := &sourceModule{}
m.AddProperties(&m.properties)
- InitAndroidModule(m)
+ InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
return m
}
diff --git a/android/sdk.go b/android/sdk.go
index 873e089..e823106 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -342,9 +342,24 @@
//
// * The variant property structs are analysed to find exported (capitalized) fields which
// have common values. Those fields are cleared and the common value added to the common
- // properties. A field annotated with a tag of `sdk:"keep"` will be treated as if it
+ // properties.
+ //
+ // A field annotated with a tag of `sdk:"keep"` will be treated as if it
// was not capitalized, i.e. not optimized for common values.
//
+ // A field annotated with a tag of `android:"arch_variant"` will be allowed to have
+ // values that differ by arch, fields not tagged as such must have common values across
+ // all variants.
+ //
+ // * Additional field tags can be specified on a field that will ignore certain values
+ // for the purpose of common value optimization. A value that is ignored must have the
+ // default value for the property type. This is to ensure that significant value are not
+ // ignored by accident. The purpose of this is to allow the snapshot generation to reflect
+ // the behavior of the runtime. e.g. if a property is ignored on the host then a property
+ // that is common for android can be treated as if it was common for android and host as
+ // the setting for host is ignored anyway.
+ // * `sdk:"ignored-on-host" - this indicates the property is ignored on the host variant.
+ //
// * The sdk module type populates the BpModule structure, creating the arch specific
// structure and calls AddToPropertySet(...) on the properties struct to add the member
// specific properties in the correct place in the structure.
diff --git a/android/sh_binary.go b/android/sh_binary.go
deleted file mode 100644
index 7d9dc67..0000000
--- a/android/sh_binary.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2019 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 android
-
-import (
- "fmt"
- "path/filepath"
- "strings"
-)
-
-// sh_binary is for shell scripts (and batch files) that are installed as
-// executable files into .../bin/
-//
-// Do not use them for prebuilt C/C++/etc files. Use cc_prebuilt_binary
-// instead.
-
-func init() {
- RegisterModuleType("sh_binary", ShBinaryFactory)
- RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
- RegisterModuleType("sh_test", ShTestFactory)
- RegisterModuleType("sh_test_host", ShTestHostFactory)
-}
-
-type shBinaryProperties struct {
- // Source file of this prebuilt.
- Src *string `android:"path,arch_variant"`
-
- // optional subdirectory under which this file is installed into
- Sub_dir *string `android:"arch_variant"`
-
- // optional name for the installed file. If unspecified, name of the module is used as the file name
- Filename *string `android:"arch_variant"`
-
- // when set to true, and filename property is not set, the name for the installed file
- // is the same as the file name of the source file.
- Filename_from_src *bool `android:"arch_variant"`
-
- // Whether this module is directly installable to one of the partitions. Default: true.
- Installable *bool
-
- // install symlinks to the binary
- Symlinks []string `android:"arch_variant"`
-}
-
-type TestProperties struct {
- // list of compatibility suites (for example "cts", "vts") that the module should be
- // installed into.
- Test_suites []string `android:"arch_variant"`
-
- // the name of the test configuration (for example "AndroidTest.xml") that should be
- // installed with the module.
- Test_config *string `android:"arch_variant"`
-
- // list of files or filegroup modules that provide data that should be installed alongside
- // the test.
- Data []string `android:"path,arch_variant"`
-}
-
-type ShBinary struct {
- ModuleBase
-
- properties shBinaryProperties
-
- sourceFilePath Path
- outputFilePath OutputPath
- installedFile InstallPath
-}
-
-var _ HostToolProvider = (*ShBinary)(nil)
-
-type ShTest struct {
- ShBinary
-
- testProperties TestProperties
-
- data Paths
-}
-
-func (s *ShBinary) HostToolPath() OptionalPath {
- return OptionalPathForPath(s.installedFile)
-}
-
-func (s *ShBinary) DepsMutator(ctx BottomUpMutatorContext) {
- if s.properties.Src == nil {
- ctx.PropertyErrorf("src", "missing prebuilt source file")
- }
-}
-
-func (s *ShBinary) OutputFile() OutputPath {
- return s.outputFilePath
-}
-
-func (s *ShBinary) SubDir() string {
- return String(s.properties.Sub_dir)
-}
-
-func (s *ShBinary) Installable() bool {
- return s.properties.Installable == nil || Bool(s.properties.Installable)
-}
-
-func (s *ShBinary) Symlinks() []string {
- return s.properties.Symlinks
-}
-
-func (s *ShBinary) generateAndroidBuildActions(ctx ModuleContext) {
- s.sourceFilePath = PathForModuleSrc(ctx, String(s.properties.Src))
- filename := String(s.properties.Filename)
- filename_from_src := Bool(s.properties.Filename_from_src)
- if filename == "" {
- if filename_from_src {
- filename = s.sourceFilePath.Base()
- } else {
- filename = ctx.ModuleName()
- }
- } else if filename_from_src {
- ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
- return
- }
- s.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
-
- // This ensures that outputFilePath has the correct name for others to
- // use, as the source file may have a different name.
- ctx.Build(pctx, BuildParams{
- Rule: CpExecutable,
- Output: s.outputFilePath,
- Input: s.sourceFilePath,
- })
-}
-
-func (s *ShBinary) GenerateAndroidBuildActions(ctx ModuleContext) {
- s.generateAndroidBuildActions(ctx)
- installDir := PathForModuleInstall(ctx, "bin", String(s.properties.Sub_dir))
- s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
-}
-
-func (s *ShBinary) AndroidMkEntries() []AndroidMkEntries {
- return []AndroidMkEntries{AndroidMkEntries{
- Class: "EXECUTABLES",
- OutputFile: OptionalPathForPath(s.outputFilePath),
- Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
- ExtraEntries: []AndroidMkExtraEntriesFunc{
- func(entries *AndroidMkEntries) {
- s.customAndroidMkEntries(entries)
- },
- },
- }}
-}
-
-func (s *ShBinary) customAndroidMkEntries(entries *AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_RELATIVE_PATH", String(s.properties.Sub_dir))
- entries.SetString("LOCAL_MODULE_SUFFIX", "")
- entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
- if len(s.properties.Symlinks) > 0 {
- entries.SetString("LOCAL_MODULE_SYMLINKS", strings.Join(s.properties.Symlinks, " "))
- }
-}
-
-func (s *ShTest) GenerateAndroidBuildActions(ctx ModuleContext) {
- s.ShBinary.generateAndroidBuildActions(ctx)
- testDir := "nativetest"
- if ctx.Target().Arch.ArchType.Multilib == "lib64" {
- testDir = "nativetest64"
- }
- if ctx.Target().NativeBridge == NativeBridgeEnabled {
- testDir = filepath.Join(testDir, ctx.Target().NativeBridgeRelativePath)
- } else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
- testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
- }
- installDir := PathForModuleInstall(ctx, testDir, String(s.properties.Sub_dir))
- s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
-
- s.data = PathsForModuleSrc(ctx, s.testProperties.Data)
-}
-
-func (s *ShTest) InstallInData() bool {
- return true
-}
-
-func (s *ShTest) AndroidMkEntries() []AndroidMkEntries {
- return []AndroidMkEntries{AndroidMkEntries{
- Class: "NATIVE_TESTS",
- OutputFile: OptionalPathForPath(s.outputFilePath),
- Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
- ExtraEntries: []AndroidMkExtraEntriesFunc{
- func(entries *AndroidMkEntries) {
- s.customAndroidMkEntries(entries)
-
- entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
- entries.SetString("LOCAL_TEST_CONFIG", String(s.testProperties.Test_config))
- for _, d := range s.data {
- rel := d.Rel()
- path := d.String()
- if !strings.HasSuffix(path, rel) {
- panic(fmt.Errorf("path %q does not end with %q", path, rel))
- }
- path = strings.TrimSuffix(path, rel)
- entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel)
- }
- },
- },
- }}
-}
-
-func InitShBinaryModule(s *ShBinary) {
- s.AddProperties(&s.properties)
-}
-
-// sh_binary is for a shell script or batch file to be installed as an
-// executable binary to <partition>/bin.
-func ShBinaryFactory() Module {
- module := &ShBinary{}
- module.Prefer32(func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool {
- return class == Device && ctx.Config().DevicePrefer32BitExecutables()
- })
- InitShBinaryModule(module)
- InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
- return module
-}
-
-// sh_binary_host is for a shell script to be installed as an executable binary
-// to $(HOST_OUT)/bin.
-func ShBinaryHostFactory() Module {
- module := &ShBinary{}
- InitShBinaryModule(module)
- InitAndroidArchModule(module, HostSupported, MultilibFirst)
- return module
-}
-
-// sh_test defines a shell script based test module.
-func ShTestFactory() Module {
- module := &ShTest{}
- InitShBinaryModule(&module.ShBinary)
- module.AddProperties(&module.testProperties)
-
- InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
- return module
-}
-
-// sh_test_host defines a shell script based test module that runs on a host.
-func ShTestHostFactory() Module {
- module := &ShTest{}
- InitShBinaryModule(&module.ShBinary)
- module.AddProperties(&module.testProperties)
-
- InitAndroidArchModule(module, HostSupported, MultilibFirst)
- return module
-}
diff --git a/android/soongconfig/Android.bp b/android/soongconfig/Android.bp
new file mode 100644
index 0000000..df912e6
--- /dev/null
+++ b/android/soongconfig/Android.bp
@@ -0,0 +1,13 @@
+bootstrap_go_package {
+ name: "soong-android-soongconfig",
+ pkgPath: "android/soong/android/soongconfig",
+ deps: [
+ "blueprint",
+ "blueprint-parser",
+ "blueprint-proptools",
+ ],
+ srcs: [
+ "config.go",
+ "modules.go",
+ ],
+}
diff --git a/android/testing.go b/android/testing.go
index 90989ef..696efb6 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -18,6 +18,7 @@
"fmt"
"path/filepath"
"regexp"
+ "sort"
"strings"
"testing"
@@ -122,9 +123,10 @@
ctx.VisitAllModules(func(m blueprint.Module) {
allModuleNames = append(allModuleNames, m.(Module).Name()+"("+ctx.ModuleSubDir(m)+")")
})
+ sort.Strings(allModuleNames)
- panic(fmt.Errorf("failed to find module %q variant %q."+
- "\nall modules: %v", name, variant, allModuleNames))
+ panic(fmt.Errorf("failed to find module %q variant %q. All modules:\n %s",
+ name, variant, strings.Join(allModuleNames, "\n ")))
}
return TestingModule{module}
diff --git a/android/visibility.go b/android/visibility.go
index 1e3b91d..68da1c4 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -140,7 +140,7 @@
}
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 @@
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 @@
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 @@
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 @@
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 4cf41a6..ca09345 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -636,6 +636,177 @@
},
},
{
+ 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 f863f8d..eaf06c5 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -40,26 +40,31 @@
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"))),
@@ -111,6 +116,7 @@
"LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",
"LOCAL_TEST_CONFIG": "test_config",
+ "LOCAL_RRO_THEME": "theme",
})
addStandardProperties(bpparser.ListType,
map[string]string{
@@ -494,10 +500,6 @@
Value: false,
}
- trueValue := &bpparser.Bool{
- Value: true,
- }
-
if inList("windows") {
err = setVariable(ctx.file, ctx.append, "target.windows", "enabled", trueValue, true)
}
@@ -703,6 +705,11 @@
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()
@@ -925,6 +932,7 @@
"BUILD_HOST_JAVA_LIBRARY": "java_library_host",
"BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
"BUILD_PACKAGE": "android_app",
+ "BUILD_RRO_PACKAGE": "runtime_resource_overlay",
"BUILD_CTS_EXECUTABLE": "cc_binary", // will be further massaged by bpfix depending on the output path
"BUILD_CTS_SUPPORT_PACKAGE": "cts_support_package", // will be rewritten to android_test by bpfix
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 3e1d486..54bd586 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1342,6 +1342,31 @@
`,
},
{
+ 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)
@@ -1360,6 +1385,29 @@
}
`,
},
+ {
+ desc: "runtime_resource_overlay",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := foo
+LOCAL_PRODUCT_MODULE := true
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SDK_VERSION := current
+LOCAL_RRO_THEME := FooTheme
+
+include $(BUILD_RRO_PACKAGE)
+`,
+ expected: `
+runtime_resource_overlay {
+ name: "foo",
+ product_specific: true,
+ resource_dirs: ["res"],
+ sdk_version: "current",
+ theme: "FooTheme",
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/Android.bp b/apex/Android.bp
new file mode 100644
index 0000000..144f441
--- /dev/null
+++ b/apex/Android.bp
@@ -0,0 +1,27 @@
+bootstrap_go_package {
+ name: "soong-apex",
+ pkgPath: "android/soong/apex",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-java",
+ "soong-python",
+ "soong-sh",
+ ],
+ srcs: [
+ "androidmk.go",
+ "apex.go",
+ "apex_singleton.go",
+ "builder.go",
+ "key.go",
+ "prebuilt.go",
+ "vndk.go",
+ ],
+ testSrcs: [
+ "apex_test.go",
+ "vndk_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index db1048e..1b3a4ba 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -78,8 +78,10 @@
}
}
+ seenDataOutPaths := make(map[string]bool)
+
for _, fi := range a.filesInfo {
- if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
+ if ccMod, ok := fi.module.(*cc.Module); ok && ccMod.Properties.HideFromMake {
continue
}
@@ -112,14 +114,25 @@
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(), " "))
@@ -165,41 +178,49 @@
if fi.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
}
- if fi.class == javaSharedLib {
- javaModule := fi.module.(javaLibrary)
+ switch fi.class {
+ case javaSharedLib:
+ 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())
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
- } else if fi.class == app {
+ case app:
fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", fi.certificate.AndroidMkString())
// 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())
- if cc, ok := fi.module.(*cc.Module); ok {
- if cc.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
+ case appSet:
+ as, ok := fi.module.(*java.AndroidAppSet)
+ if !ok {
+ panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
+ }
+ fmt.Fprintln(w, "LOCAL_APK_SET_MASTER_FILE :=", as.MasterFile())
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
+ case nativeSharedLib, nativeExecutable, nativeTest:
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem())
+ if ccMod, ok := fi.module.(*cc.Module); ok {
+ if ccMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
}
- cc.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- if cc.CoverageOutputFile().Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", cc.CoverageOutputFile().String())
+ ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ if ccMod.CoverageOutputFile().Valid() {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
- } else {
- fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
+ default:
+ 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
@@ -308,7 +329,7 @@
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
if apexType == imageApex {
- fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
+ fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
}
if a.installedFilesFile != nil {
diff --git a/apex/apex.go b/apex/apex.go
index 1947980..2f7b2e5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,19 +18,20 @@
"fmt"
"path"
"path/filepath"
- "regexp"
"sort"
"strings"
"sync"
- "android/soong/android"
- "android/soong/cc"
- "android/soong/java"
- "android/soong/python"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/cc"
+ prebuilt_etc "android/soong/etc"
+ "android/soong/java"
+ "android/soong/python"
+ "android/soong/sh"
)
const (
@@ -94,69 +95,6 @@
//
// 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",
@@ -245,19 +183,6 @@
//
// 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",
@@ -301,7 +226,10 @@
"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",
@@ -556,12 +484,6 @@
// 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",
@@ -632,13 +554,21 @@
// 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
@@ -662,8 +592,6 @@
"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",
@@ -685,7 +613,6 @@
"wifi-nano-protos",
"wifi-service-pre-jarjar",
"wifi-service-resources",
- "prebuilt_androidx.annotation_annotation-nodeps",
}
//
// Module separator
@@ -705,6 +632,15 @@
// 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",
@@ -724,6 +660,7 @@
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)
@@ -760,7 +697,7 @@
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 {
@@ -1178,6 +1115,7 @@
javaSharedLib
nativeTest
app
+ appSet
)
func (class apexFileClass) NameInMake() string {
@@ -1192,7 +1130,7 @@
return "JAVA_LIBRARIES"
case nativeTest:
return "NATIVE_TESTS"
- case app:
+ case app, appSet:
// b/142537672 Why isn't this APP? We want to have full control over
// the paths and file names of the apk file under the flattend APEX.
// If this is set to APP, then the paths and file names are modified
@@ -1209,12 +1147,14 @@
// 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
@@ -1250,16 +1190,27 @@
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
}
@@ -1459,19 +1410,7 @@
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,
@@ -1603,6 +1542,21 @@
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 {
@@ -1665,6 +1619,7 @@
fileToCopy := cc.OutputFile().Path()
af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
af.symlinks = cc.Symlinks()
+ af.dataPaths = cc.DataPaths()
return af
}
@@ -1687,7 +1642,7 @@
return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
}
-func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) apexFile {
+func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
dirInApex := filepath.Join("bin", sh.SubDir())
fileToCopy := sh.OutputFile()
af := newApexFile(ctx, fileToCopy, sh.Name(), dirInApex, shBinary, sh)
@@ -1695,21 +1650,22 @@
return af
}
-// TODO(b/146586360): replace javaLibrary(in apex/apex.go) with java.Dependency
-type javaLibrary interface {
- android.Module
- java.Dependency
+type javaDependency interface {
+ DexJarBuildPath() android.Path
+ JacocoReportClassesFile() android.Path
+ 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)
+ fileToCopy := lib.DexJarBuildPath()
+ af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module)
af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
+ af.stem = lib.Stem() + ".jar"
return af
}
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
dirInApex := filepath.Join("etc", prebuilt.SubDir())
fileToCopy := prebuilt.OutputFile()
return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
@@ -1811,24 +1767,12 @@
return intVer
}
-// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
-// a dependency tag.
-var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:blueprint.BaseDependencyTag{}\E(, )?`)
-
-func PrettyPrintTag(tag blueprint.DependencyTag) string {
- // Use tag's custom String() method if available.
- if stringer, ok := tag.(fmt.Stringer); ok {
- return stringer.String()
- }
-
- // Otherwise, get a default string representation of the tag's struct.
- tagString := fmt.Sprintf("%#v", tag)
-
- // Remove the boilerplate from BaseDependencyTag as it adds no value.
- tagString = tagCleaner.ReplaceAllString(tagString, "")
- return tagString
+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
@@ -1863,21 +1807,14 @@
if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
return true
}
- message := ""
- tagPath := ctx.GetTagPath()
- // Skip the first module as that will be added at the start of the error message by ctx.ModuleErrorf().
- walkPath := ctx.GetWalkPath()[1:]
- for i, m := range walkPath {
- message = fmt.Sprintf("%s\n via tag %s\n -> %s", message, PrettyPrintTag(tagPath[i]), m.String())
- }
- ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, message)
+ ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, ctx.GetPathString(true))
// Visit this module's dependencies to check and report any issues with their availability.
return true
})
}
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")
}
@@ -1886,6 +1823,51 @@
}
}
+// 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 {
@@ -1923,6 +1905,7 @@
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
+ a.checkStaticLinkingToStubLibraries(ctx)
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
@@ -1967,13 +1950,13 @@
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"
@@ -1986,7 +1969,7 @@
if cc, ok := child.(*cc.Module); ok {
filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
return true // track transitive dependencies
- } else if sh, ok := child.(*android.ShBinary); ok {
+ } else if sh, ok := child.(*sh.ShBinary); ok {
filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
@@ -1996,23 +1979,16 @@
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
}
case javaLibTag:
- if javaLib, ok := child.(*java.Library); ok {
- af := apexFileForJavaLibrary(ctx, javaLib)
- if !af.Ok() {
- ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
- } else {
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- }
- } else if sdkLib, ok := child.(*java.SdkLibrary); ok {
- af := apexFileForJavaLibrary(ctx, sdkLib)
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary, *java.DexImport:
+ af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module))
if !af.Ok() {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
return false
}
filesInfo = append(filesInfo, af)
return true // track transitive dependencies
- } else {
+ default:
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
case androidAppTag:
@@ -2023,6 +1999,15 @@
filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
+ } else if ap, ok := child.(*java.AndroidAppSet); ok {
+ appDir := "app"
+ if ap.Privileged() {
+ appDir = "priv-app"
+ }
+ af := newApexFile(ctx, ap.OutputFile(), ap.Name(),
+ filepath.Join(appDir, ap.BaseModuleName()), appSet, ap)
+ af.certificate = java.PresignedCertificate
+ filesInfo = append(filesInfo, af)
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
@@ -2033,7 +2018,7 @@
ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
}
case prebuiltTag:
- if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
+ if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
} else if prebuilt, ok := child.(java.PlatformCompatConfigIntf); ok {
filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, prebuilt, depName))
@@ -2093,6 +2078,8 @@
// 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.
@@ -2104,12 +2091,10 @@
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
}
@@ -2130,11 +2115,11 @@
// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
return false
} else if java.IsXmlPermissionsFileDepTag(depTag) {
- if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
+ if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
}
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
- ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", PrettyPrintTag(depTag), depName)
+ ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
}
}
}
@@ -2217,7 +2202,7 @@
// 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
}
@@ -2283,6 +2268,10 @@
// 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 0000000..83a56a2
--- /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 dc69862..d6a5d09 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -19,6 +19,7 @@
"os"
"path"
"reflect"
+ "regexp"
"sort"
"strings"
"testing"
@@ -28,7 +29,9 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
+ prebuilt_etc "android/soong/etc"
"android/soong/java"
+ "android/soong/sh"
)
var buildDir string
@@ -93,7 +96,7 @@
// - X86 (secondary)
// - Arm64 on X86_64 (native bridge)
// - Arm on X86 (native bridge)
-func withNativeBridgeEnabled(fs map[string][]byte, config android.Config) {
+func withNativeBridgeEnabled(_ map[string][]byte, config android.Config) {
config.Targets[android.Android] = []android.Target{
{Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
@@ -112,15 +115,15 @@
}
}
-func withBinder32bit(fs map[string][]byte, config android.Config) {
+func withBinder32bit(_ map[string][]byte, config android.Config) {
config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
}
-func withUnbundledBuild(fs map[string][]byte, config android.Config) {
+func withUnbundledBuild(_ map[string][]byte, config android.Config) {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
-func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
android.ClearApexDependency()
bp = bp + `
@@ -175,11 +178,16 @@
"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,
+ "AppSet.apks": nil,
}
cc.GatherRequiredFilesForTest(fs)
@@ -216,6 +224,7 @@
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)
@@ -224,9 +233,9 @@
ctx.RegisterModuleType("cc_test", cc.TestFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
- ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
+ ctx.RegisterModuleType("prebuilt_etc", prebuilt_etc.PrebuiltEtcFactory)
ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
- ctx.RegisterModuleType("sh_binary", android.ShBinaryFactory)
+ ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
java.RegisterJavaBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
@@ -250,7 +259,7 @@
}
func tearDown() {
- os.RemoveAll(buildDir)
+ _ = os.RemoveAll(buildDir)
}
// ensure that 'result' equals 'expected'
@@ -269,6 +278,15 @@
}
}
+// 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()
@@ -277,6 +295,17 @@
}
}
+func ensureMatches(t *testing.T, result string, expectedRex string) {
+ ok, err := regexp.MatchString(expectedRex, result)
+ if err != nil {
+ t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err)
+ return
+ }
+ if !ok {
+ t.Errorf("%s does not match regular expession %s", result, expectedRex)
+ }
+}
+
func ensureListContains(t *testing.T, result []string, expected string) {
t.Helper()
if !android.InList(expected, result) {
@@ -312,7 +341,10 @@
binaries: ["foo",],
}
},
- java_libs: ["myjar"],
+ java_libs: [
+ "myjar",
+ "myjar_dex",
+ ],
}
apex {
@@ -409,6 +441,7 @@
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
+ stem: "myjar_stem",
sdk_version: "none",
system_modules: "none",
static_libs: ["myotherjar"],
@@ -420,6 +453,15 @@
],
}
+ dex_import {
+ name: "myjar_dex",
+ jars: ["prebuilt.jar"],
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
java_library {
name: "myotherjar",
srcs: ["foo/bar/MyClass.java"],
@@ -455,6 +497,7 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_myapex")
// Ensure that apex variant is created for the indirect dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
@@ -463,7 +506,8 @@
// 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")
+ ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar")
// .. but not for java libs
ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
@@ -905,6 +949,130 @@
}
+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 +3435,14 @@
private_key: "testkey.pem",
}
+ filegroup {
+ name: "fg",
+ srcs: [
+ "baz",
+ "bar/baz"
+ ],
+ }
+
cc_test {
name: "mytest",
gtest: false,
@@ -3276,6 +3452,7 @@
system_shared_libs: [],
static_executable: true,
stl: "none",
+ data: [":fg"],
}
cc_library {
@@ -3285,6 +3462,13 @@
stl: "none",
}
+ filegroup {
+ name: "fg2",
+ srcs: [
+ "testdata/baz"
+ ],
+ }
+
cc_test {
name: "mytests",
gtest: false,
@@ -3298,6 +3482,10 @@
system_shared_libs: [],
static_executable: true,
stl: "none",
+ data: [
+ ":fg",
+ ":fg2",
+ ],
}
`)
@@ -3308,15 +3496,19 @@
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 +3520,13 @@
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 +4314,15 @@
}
}
+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 +4343,7 @@
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 +4355,98 @@
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 +4784,110 @@
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 TestAppSetBundle(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppSet"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_app_set {
+ name: "AppSet",
+ set: "AppSet.apks",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ bundleConfigRule := mod.Description("Bundle Config")
+ content := bundleConfigRule.Args["content"]
+ ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
+ s := mod.Rule("apexRule").Args["copy_commands"]
+ copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
+ if len(copyCmds) != 3 {
+ t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
+ }
+ ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet$")
+ ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet$")
+ ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
+}
+
+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 +4974,86 @@
}
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",
- ],
- }
-
- 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",
- }
- `
-
- var error string
+ var err 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)
+ 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)
+ })
- // 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)
+ t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
+ err = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"com.android.art.something:some-art-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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)
+ t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
+ err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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)
+ t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
+ err = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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)
+ t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
+ err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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)
+ 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)
+ })
- // 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)
+ t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
+ err = "failed to find a dex jar path for module 'nonexistent'"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"platform:nonexistent"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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)
+ t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
+ err = "failed to find a dex jar path for module 'nonexistent'"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"platform:nonexistent"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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) {
+ err = "module 'some-platform-lib' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"platform:some-platform-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, err, 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 +5108,84 @@
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 ca24f2c..17eac1a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -61,6 +61,7 @@
pctx.HostBinToolVariable("zipalign", "zipalign")
pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
pctx.HostBinToolVariable("conv_apex_manifest", "conv_apex_manifest")
+ pctx.HostBinToolVariable("extract_apks", "extract_apks")
}
var (
@@ -68,11 +69,14 @@
// by default set to (uid/gid/mode) = (1000/1000/0644)
// TODO(b/113082813) make this configurable using config.fs syntax
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
- Command: `echo '/ 1000 1000 0755' > ${out} && ` +
- `echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
- `echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`,
- Description: "fs_config ${out}",
- }, "ro_paths", "exec_paths")
+ Command: `( echo '/ 1000 1000 0755' ` +
+ `&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
+ `&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
+ `&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
+ Description: "fs_config ${out}",
+ Rspfile: "$out.apklist",
+ RspfileContent: "$in",
+ }, "ro_paths", "exec_paths", "apk_paths")
apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${jsonmodify} $in ` +
@@ -189,7 +193,7 @@
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 +250,7 @@
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 {
@@ -286,7 +290,7 @@
// collect the manifest names and paths of android apps
// if their manifest names are overridden
for _, fi := range a.filesInfo {
- if fi.class != app {
+ if fi.class != app && fi.class != appSet {
continue
}
packageName := fi.overriddenPackageName
@@ -336,13 +340,22 @@
var copyCommands []string
for _, fi := range a.filesInfo {
destPath := android.PathForModuleOut(ctx, "image"+suffix, fi.Path()).String()
- copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(destPath))
+ destPathDir := filepath.Dir(destPath)
+ if fi.class == appSet {
+ copyCommands = append(copyCommands, "rm -rf "+destPathDir)
+ }
+ copyCommands = append(copyCommands, "mkdir -p "+destPathDir)
if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
pathOnDevice := filepath.Join("/system", fi.Path())
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
- copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ if fi.class == appSet {
+ copyCommands = append(copyCommands,
+ fmt.Sprintf("unzip -q -d %s %s", destPathDir, fi.builtFile.String()))
+ } else {
+ copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ }
implicitInputs = append(implicitInputs, fi.builtFile)
}
// create additional symlinks pointing the file inside the APEX
@@ -350,6 +363,19 @@
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
@@ -402,13 +428,21 @@
// files and dirs that will be created in APEX
var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
var executablePaths []string // this also includes dirs
+ var extractedAppSetPaths android.Paths
+ var extractedAppSetDirs []string
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))
}
+ } else if f.class == appSet {
+ extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile)
+ extractedAppSetDirs = append(extractedAppSetDirs, f.installDir)
} else {
readOnlyPaths = append(readOnlyPaths, pathInApex)
}
@@ -429,9 +463,11 @@
Rule: generateFsConfig,
Output: cannedFsConfig,
Description: "generate fs config",
+ Inputs: extractedAppSetPaths,
Args: map[string]string{
"ro_paths": strings.Join(readOnlyPaths, " "),
"exec_paths": strings.Join(executablePaths, " "),
+ "apk_paths": strings.Join(extractedAppSetDirs, " "),
},
})
@@ -453,11 +489,11 @@
}
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 +601,27 @@
}
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 +686,7 @@
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 d089c28..03266c5 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -16,13 +16,29 @@
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 @@
},
}}
}
+
+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 a1c5de1..e731750 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -408,6 +408,8 @@
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 @@
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/Android.bp b/cc/Android.bp
new file mode 100644
index 0000000..9ece05f
--- /dev/null
+++ b/cc/Android.bp
@@ -0,0 +1,87 @@
+bootstrap_go_package {
+ name: "soong-cc",
+ pkgPath: "android/soong/cc",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-cc-config",
+ "soong-etc",
+ "soong-genrule",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "androidmk.go",
+ "builder.go",
+ "cc.go",
+ "ccdeps.go",
+ "check.go",
+ "coverage.go",
+ "gen.go",
+ "linkable.go",
+ "lto.go",
+ "makevars.go",
+ "pgo.go",
+ "prebuilt.go",
+ "proto.go",
+ "rs.go",
+ "sanitize.go",
+ "sabi.go",
+ "sdk.go",
+ "snapshot_utils.go",
+ "stl.go",
+ "strip.go",
+ "sysprop.go",
+ "tidy.go",
+ "util.go",
+ "vendor_snapshot.go",
+ "vndk.go",
+ "vndk_prebuilt.go",
+
+ "cflag_artifacts.go",
+ "cmakelists.go",
+ "compdb.go",
+ "compiler.go",
+ "installer.go",
+ "linker.go",
+
+ "binary.go",
+ "binary_sdk_member.go",
+ "fuzz.go",
+ "library.go",
+ "library_headers.go",
+ "library_sdk_member.go",
+ "object.go",
+ "test.go",
+ "toolchain_library.go",
+
+ "ndk_prebuilt.go",
+ "ndk_headers.go",
+ "ndk_library.go",
+ "ndk_sysroot.go",
+
+ "llndk_library.go",
+
+ "kernel_headers.go",
+
+ "genrule.go",
+
+ "vendor_public_library.go",
+
+ "testing.go",
+ ],
+ testSrcs: [
+ "cc_test.go",
+ "compiler_test.go",
+ "gen_test.go",
+ "genrule_test.go",
+ "library_headers_test.go",
+ "library_test.go",
+ "object_test.go",
+ "prebuilt_test.go",
+ "proto_test.go",
+ "test_data_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 671adb5..52480ea 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -149,7 +149,7 @@
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 @@
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...)
@@ -543,6 +548,25 @@
})
}
+func (c *vendorSnapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "STATIC_LIBRARIES"
+
+ if c.androidMkVendorSuffix {
+ entries.SubName = vendorSuffix
+ } else {
+ entries.SubName = ""
+ }
+
+ entries.ExtraFooters = append(entries.ExtraFooters,
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ out := entries.OutputFile.Path()
+ varname := fmt.Sprintf("SOONG_%sOBJECT_%s%s", prefix, name, entries.SubName)
+
+ fmt.Fprintf(w, "\n%s := %s\n", varname, out.String())
+ fmt.Fprintln(w, ".KATI_READONLY: "+varname)
+ })
+}
+
func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "SHARED_LIBRARIES"
}
diff --git a/cc/binary.go b/cc/binary.go
index 661264e..251b7f0 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -231,6 +231,10 @@
return binary.static()
}
+func (binary *binaryDecorator) binary() bool {
+ return true
+}
+
func (binary *binaryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseLinker.linkerFlags(ctx, flags)
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 88ac513..372a72e 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -20,6 +20,7 @@
"android/soong/android"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -65,7 +66,15 @@
}
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 @@
//
// 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 @@
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 @@
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 4e8f1fa..e571e5a 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -99,6 +99,15 @@
},
"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 @@
}, []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 @@
}
// 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 @@
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)
}
diff --git a/cc/cc.go b/cc/cc.go
index 02c4879..8eabff5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -124,10 +124,16 @@
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
@@ -310,6 +316,8 @@
static() bool
staticBinary() bool
header() bool
+ binary() bool
+ object() bool
toolchain() config.Toolchain
canUseSdk() bool
useSdk() bool
@@ -1011,14 +1019,8 @@
}
func (c *Module) isSnapshotPrebuilt() bool {
- if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
- return true
- }
- if _, ok := c.linker.(*vendorSnapshotLibraryDecorator); ok {
- return true
- }
- if _, ok := c.linker.(*vendorSnapshotBinaryDecorator); ok {
- return true
+ if p, ok := c.linker.(interface{ isSnapshotPrebuilt() bool }); ok {
+ return p.isSnapshotPrebuilt()
}
return false
}
@@ -1068,7 +1070,7 @@
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)
}
@@ -1123,6 +1125,14 @@
return ctx.mod.header()
}
+func (ctx *moduleContextImpl) binary() bool {
+ return ctx.mod.binary()
+}
+
+func (ctx *moduleContextImpl) object() bool {
+ return ctx.mod.object()
+}
+
func (ctx *moduleContextImpl) canUseSdk() bool {
return ctx.mod.canUseSdk()
}
@@ -1395,6 +1405,15 @@
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.
@@ -1910,7 +1929,7 @@
if deps.StaticUnwinderIfLegacy {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, staticUnwinderDepTag, staticUnwinder(actx))
+ }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
}
for _, lib := range deps.LateStaticLibs {
@@ -1991,11 +2010,13 @@
actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
+ vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
+
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(nil, CrtBeginDepTag, deps.CrtBegin)
+ actx.AddVariationDependencies(nil, CrtBeginDepTag, rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(nil, CrtEndDepTag, deps.CrtEnd)
+ actx.AddVariationDependencies(nil, CrtEndDepTag, rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2473,7 +2494,11 @@
}
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)
@@ -2733,6 +2758,24 @@
return false
}
+func (c *Module) binary() bool {
+ if b, ok := c.linker.(interface {
+ binary() bool
+ }); ok {
+ return b.binary()
+ }
+ return false
+}
+
+func (c *Module) object() bool {
+ if o, ok := c.linker.(interface {
+ object() bool
+ }); ok {
+ return o.object()
+ }
+ return false
+}
+
func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
if c.UseVndk() {
if lib, ok := c.linker.(*llndkStubDecorator); ok {
@@ -2862,6 +2905,9 @@
return false
}
}
+ } else if ctx.OtherModuleDependencyTag(dep) == llndkImplDep {
+ // We don't track beyond LLNDK
+ return false
}
return true
}
@@ -3042,20 +3088,32 @@
// This will be available in /system, /vendor and /product
// or a /system directory that is available to vendor and product.
coreVariantNeeded = true
- vendorVariants = append(vendorVariants, platformVndkVersion)
- productVariants = append(productVariants, platformVndkVersion)
- // VNDK modules must not create BOARD_VNDK_VERSION variant because its
- // code is PLATFORM_VNDK_VERSION.
- // On the other hand, vendor_available modules which are not VNDK should
- // also build BOARD_VNDK_VERSION because it's installed in /vendor.
- // vendor_available modules are also available to /product.
- if !m.IsVndk() {
+
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+
+ // vendor_available modules are also available to /product.
+ productVariants = append(productVariants, platformVndkVersion)
+ // VNDK is always PLATFORM_VNDK_VERSION
+ if !m.IsVndk() {
productVariants = append(productVariants, productVndkVersion)
}
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
// This will be available in /vendor (or /odm) only
- vendorVariants = append(vendorVariants, boardVndkVersion)
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 67eb248..76b4e38 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -258,9 +258,7 @@
}
}
-func checkSnapshot(t *testing.T, ctx *android.TestContext, singletonName, moduleName, snapshotFilename, subDir, variant string) {
- snapshotSingleton := ctx.SingletonForTests(singletonName)
-
+func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
if !ok {
t.Errorf("%q must have output\n", moduleName)
@@ -273,7 +271,7 @@
}
snapshotPath := filepath.Join(subDir, snapshotFilename)
- out := snapshotSingleton.Output(snapshotPath)
+ out := singleton.Output(snapshotPath)
if out.Input.String() != outputFiles[0].String() {
t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
}
@@ -398,16 +396,18 @@
variant := "android_vendor.VER_arm64_armv8-a_shared"
variant2nd := "android_vendor.VER_arm_armv7-a-neon_shared"
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLibPath, variant)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
+ snapshotSingleton := ctx.SingletonForTests("vndk-snapshot")
+
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
- checkSnapshot(t, ctx, "vndk-snapshot", "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
"LLNDK: libc.so",
@@ -839,6 +839,17 @@
vendor_available: true,
nocrt: true,
}
+
+ toolchain_library {
+ name: "libb",
+ vendor_available: true,
+ src: "libb.a",
+ }
+
+ cc_object {
+ name: "obj",
+ vendor_available: true,
+ }
`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -849,6 +860,9 @@
snapshotDir := "vendor-snapshot"
snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var jsonFiles []string
for _, arch := range [][]string{
[]string{"arm64", "armv8-a"},
@@ -861,22 +875,51 @@
// For shared libraries, only non-VNDK vendor_available modules are captured
sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libvendor.so.json"),
+ filepath.Join(sharedDir, "libvendor_available.so.json"))
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- checkSnapshot(t, ctx, "vendor-snapshot", "libvndk", "libvndk.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libb.a.json"),
+ filepath.Join(staticDir, "libvndk.a.json"),
+ filepath.Join(staticDir, "libvendor.a.json"),
+ filepath.Join(staticDir, "libvendor_available.a.json"))
- // For binary libraries, all vendor:true and vendor_available modules are captured.
+ // For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
binaryVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- checkSnapshot(t, ctx, "vendor-snapshot", "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "vendor_bin.json"),
+ filepath.Join(binaryDir, "vendor_available_bin.json"))
+ }
+
+ // For header libraries, all vendor:true and vendor_available modules are captured.
+ headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
+ jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
+
+ // For object modules, all vendor:true and vendor_available modules are captured.
+ objectVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
+ objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
+ checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
+ jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
+ }
+
+ for _, jsonFile := range jsonFiles {
+ // verify all json files exist
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("%q expected but not found", jsonFile)
}
}
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 681b1ab..e7495da 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -300,8 +300,7 @@
if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
"${config.CommonGlobalIncludes}",
- tc.IncludeFlags(),
- "${config.CommonNativehelperInclude}")
+ tc.IncludeFlags())
}
if ctx.useSdk() {
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
new file mode 100644
index 0000000..6275064
--- /dev/null
+++ b/cc/config/Android.bp
@@ -0,0 +1,30 @@
+bootstrap_go_package {
+ name: "soong-cc-config",
+ pkgPath: "android/soong/cc/config",
+ deps: [
+ "soong-android",
+ "soong-remoteexec",
+ ],
+ srcs: [
+ "clang.go",
+ "global.go",
+ "tidy.go",
+ "toolchain.go",
+ "vndk.go",
+
+ "arm_device.go",
+ "arm64_device.go",
+ "arm64_fuchsia_device.go",
+ "x86_device.go",
+ "x86_64_device.go",
+ "x86_64_fuchsia_device.go",
+
+ "x86_darwin_host.go",
+ "x86_linux_host.go",
+ "x86_linux_bionic_host.go",
+ "x86_windows_host.go",
+ ],
+ testSrcs: [
+ "tidy_test.go",
+ ],
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 4e51ae9..1dd8a2d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -162,7 +162,7 @@
// 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 @@
} 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 @@
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 cc9a1ad..f885fcb 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -92,7 +92,7 @@
// 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/genrule.go b/cc/genrule.go
index 9331448..66d1784 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -79,8 +79,14 @@
var variants []string
if Bool(g.Vendor_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
- variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
- if vndkVersion := ctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ // If vndkVersion is current, we can always use PlatformVndkVersion.
+ // If not, we assume modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
+ // PLATFORM_VNDK_VERSION.
+ if vndkVersion == "current" || !isVendorProprietaryPath(ctx.ModuleDir()) {
+ variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+ } else {
variants = append(variants, VendorVariationPrefix+vndkVersion)
}
}
diff --git a/cc/library.go b/cc/library.go
index ecea2ea..ba8b0f4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -407,6 +407,31 @@
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 @@
}
}
- 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/library_sdk_member.go b/cc/library_sdk_member.go
index 2c8e311..a7a1de2 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -307,7 +307,7 @@
// The list of possibly common exported include dirs.
//
// This field is exported as its contents may not be arch specific.
- ExportedIncludeDirs android.Paths
+ ExportedIncludeDirs android.Paths `android:"arch_variant"`
// The list of arch specific exported generated include dirs.
//
@@ -322,27 +322,31 @@
// The list of possibly common exported system include dirs.
//
// This field is exported as its contents may not be arch specific.
- ExportedSystemIncludeDirs android.Paths
+ ExportedSystemIncludeDirs android.Paths `android:"arch_variant"`
// The list of possibly common exported flags.
//
// This field is exported as its contents may not be arch specific.
- ExportedFlags []string
+ ExportedFlags []string `android:"arch_variant"`
// The set of shared libraries
//
// This field is exported as its contents may not be arch specific.
- SharedLibs []string
+ SharedLibs []string `android:"arch_variant"`
// The set of system shared libraries. Note nil and [] are semantically
// distinct - see BaseLinkerProperties.System_shared_libs.
//
// This field is exported as its contents may not be arch specific.
- SystemSharedLibs []string
+ SystemSharedLibs []string `android:"arch_variant"`
// The specific stubs version for the lib variant, or empty string if stubs
// are not in use.
- StubsVersion string
+ //
+ // Marked 'ignored-on-host' as the StubsVersion() from which this is initialized is
+ // not set on host and the stubs.versions property which this is written to is does
+ // not vary by arch so cannot be android specific.
+ StubsVersion string `sdk:"ignored-on-host"`
// outputFile is not exported as it is always arch specific.
outputFile android.Path
diff --git a/cc/object.go b/cc/object.go
index 19decec..15a529e 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -158,3 +158,7 @@
func (object *objectLinker) coverageOutputFilePath() android.OptionalPath {
return android.OptionalPath{}
}
+
+func (object *objectLinker) object() bool {
+ return true
+}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index ac990f3..0751f1c 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -291,6 +291,10 @@
return nil
}
+func (p *prebuiltObjectLinker) object() bool {
+ return true
+}
+
func newPrebuiltObject() *Module {
module := newObject()
prebuilt := &prebuiltObjectLinker{
@@ -349,6 +353,10 @@
return nil
}
+func (p *prebuiltBinaryLinker) binary() bool {
+ return true
+}
+
// cc_prebuilt_binary installs a precompiled executable in srcs property in the
// device's directory.
func prebuiltBinaryFactory() android.Module {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 3412c9b..aaaf694 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -989,6 +989,7 @@
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 @@
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 f51cf01..2439c94 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -90,6 +90,10 @@
// 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 download and install the specified modules on the device.
+ Test_mainline_modules []string
}
func init() {
@@ -156,6 +160,10 @@
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 == ""
@@ -329,24 +337,25 @@
var api_level_prop string
var configs []tradefed.Config
var min_level string
+ for _, module := range test.Properties.Test_mainline_modules {
+ configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
+ }
if Bool(test.Properties.Require_root) {
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
} else {
var options []tradefed.Option
- options = append(options, tradefed.Option{"force-root", "false"})
+ options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
}
if Bool(test.Properties.Disable_framework) {
var options []tradefed.Option
- options = append(options, tradefed.Option{"run-command", "stop"})
- options = append(options, tradefed.Option{"teardown-command", "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{"not-shardable", "true"})
+ configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
}
if test.Properties.Test_options.Run_test_as != nil {
- configs = append(configs, tradefed.Option{"run-test-as", String(test.Properties.Test_options.Run_test_as)})
+ configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(test.Properties.Test_options.Run_test_as)})
}
if test.Properties.Test_min_api_level != nil && test.Properties.Test_min_sdk_version != nil {
ctx.PropertyErrorf("test_min_api_level", "'test_min_api_level' and 'test_min_sdk_version' should not be set at the same time.")
@@ -359,8 +368,8 @@
}
if api_level_prop != "" {
var options []tradefed.Option
- options = append(options, tradefed.Option{"min-api-level", min_level})
- options = append(options, tradefed.Option{"api-level-prop", api_level_prop})
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: min_level})
+ options = append(options, tradefed.Option{Name: "api-level-prop", Value: api_level_prop})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
}
diff --git a/cc/testing.go b/cc/testing.go
index be020c5..edbb24d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -496,6 +496,7 @@
"my_include": nil,
"foo.map.txt": nil,
"liba.so": nil,
+ "libb.a": nil,
}
GatherRequiredFilesForTest(mockFS)
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 5801fc7..ea94544 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -30,6 +30,7 @@
vendorSnapshotSharedSuffix = ".vendor_shared."
vendorSnapshotStaticSuffix = ".vendor_static."
vendorSnapshotBinarySuffix = ".vendor_binary."
+ vendorSnapshotObjectSuffix = ".vendor_object."
)
var (
@@ -39,6 +40,7 @@
vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
+ vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
)
// vendor snapshot maps hold names of vendor snapshot modules per arch
@@ -72,6 +74,12 @@
}).(*snapshotMap)
}
+func vendorSnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
type vendorSnapshotLibraryProperties struct {
// snapshot version.
Version string
@@ -185,6 +193,10 @@
return false
}
+func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file)
@@ -337,6 +349,10 @@
return outputFile
}
+func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func VendorSnapshotBinaryFactory() android.Module {
module, binary := NewBinary(android.DeviceSupported)
binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
@@ -364,12 +380,98 @@
return module.Init()
}
+type vendorSnapshotObjectProperties struct {
+ // snapshot version.
+ Version string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+ Target_arch string
+
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+}
+
+type vendorSnapshotObjectLinker struct {
+ objectLinker
+ properties vendorSnapshotObjectProperties
+ androidMkVendorSuffix bool
+}
+
+func (p *vendorSnapshotObjectLinker) Name(name string) string {
+ return name + p.NameSuffix()
+}
+
+func (p *vendorSnapshotObjectLinker) NameSuffix() string {
+ versionSuffix := p.version()
+ if p.arch() != "" {
+ versionSuffix += "." + p.arch()
+ }
+ return vendorSnapshotObjectSuffix + versionSuffix
+}
+
+func (p *vendorSnapshotObjectLinker) version() string {
+ return p.properties.Version
+}
+
+func (p *vendorSnapshotObjectLinker) arch() string {
+ return p.properties.Target_arch
+}
+
+func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.arch() {
+ return false
+ }
+ if p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objs Objects) android.Path {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ m := ctx.Module().(*Module)
+ p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ return android.PathForModuleSrc(ctx, *p.properties.Src)
+}
+
+func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
+ return false
+}
+
+func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
+ return true
+}
+
+func VendorSnapshotObjectFactory() android.Module {
+ module := newObject()
+
+ prebuilt := &vendorSnapshotObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
func init() {
android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+ android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
}
func VendorSnapshotSingleton() android.Singleton {
@@ -429,7 +531,7 @@
// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
// image and newer system image altogether.
func isVendorSnapshotModule(m *Module, moduleDir string) bool {
- if !m.Enabled() {
+ if !m.Enabled() || m.Properties.HideFromMake {
return false
}
// skip proprietary modules, but include all VNDK (static)
@@ -443,37 +545,37 @@
return false
}
// the module must be installed in /vendor
- if !m.installable() || m.isSnapshotPrebuilt() || !m.inVendor() {
- return false
- }
- // exclude test modules
- if _, ok := m.linker.(interface{ gtest() bool }); ok {
- return false
- }
- // TODO(b/65377115): add full support for sanitizer
- if m.sanitize != nil && !m.sanitize.isUnsanitizedVariant() {
+ if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
return false
}
// Libraries
if l, ok := m.linker.(snapshotLibraryInterface); ok {
+ // TODO(b/65377115): add full support for sanitizer
+ if m.sanitize != nil {
+ // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
+ // Always use unsanitized variants of them.
+ for _, t := range []sanitizerType{cfi, scs, hwasan} {
+ if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
+ return false
+ }
+ }
+ }
if l.static() {
- return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+ return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
}
if l.shared() {
- return !m.IsVndk()
+ return m.outputFile.Valid() && !m.IsVndk()
}
return true
}
- // Binaries
- _, ok := m.linker.(*binaryDecorator)
- if !ok {
- if _, ok := m.linker.(*prebuiltBinaryLinker); !ok {
- return false
- }
+ // Binaries and Objects
+ if m.binary() || m.object() {
+ return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
}
- return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+
+ return false
}
func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -496,6 +598,8 @@
(header only libraries)
binary/
(executable binaries)
+ object/
+ (.o object files)
arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
shared/
(.so shared libraries)
@@ -505,6 +609,8 @@
(header only libraries)
binary/
(executable binaries)
+ object/
+ (.o object files)
NOTICE_FILES/
(notice files, e.g. libbase.txt)
configs/
@@ -620,7 +726,7 @@
}
propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
- } else {
+ } else if m.binary() {
// binary flags
prop.Symlinks = m.Symlinks()
prop.SharedLibs = m.Properties.SnapshotSharedLibs
@@ -630,6 +736,17 @@
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
propOut = snapshotBinOut + ".json"
+ } else if m.object() {
+ // object files aren't installed to the device, so their names can conflict.
+ // Use module name as stem.
+ objPath := m.outputFile.Path()
+ snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
+ ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
+ propOut = snapshotObjOut + ".json"
+ } else {
+ ctx.Errorf("unknown module %q in vendor snapshot", m.String())
+ return nil
}
j, err := json.Marshal(prop)
@@ -716,6 +833,7 @@
var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
+var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
// gathers all snapshot modules for vendor, and disable unnecessary snapshots
// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
@@ -731,12 +849,12 @@
return
}
- snapshot, ok := module.linker.(snapshotInterface)
- if !ok {
+ if !module.isSnapshotPrebuilt() {
return
}
- if !snapshot.matchesWithDevice(ctx.DeviceConfig()) {
+ // isSnapshotPrebuilt ensures snapshotInterface
+ if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
// Disable unnecessary snapshot module, but do not disable
// vndk_prebuilt_shared because they might be packed into vndk APEX
if !module.IsVndk() {
@@ -758,6 +876,8 @@
}
} else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
+ snapshotMap = vendorSnapshotObjects(ctx.Config())
} else {
return
}
@@ -804,6 +924,11 @@
return
}
+ // .. and also filter out llndk library
+ if module.isLlndk(ctx.Config()) {
+ return
+ }
+
var snapshotMap *snapshotMap
if lib, ok := module.linker.(libraryInterface); ok {
@@ -815,10 +940,10 @@
// header
snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
}
- } else if _, ok := module.linker.(*binaryDecorator); ok {
+ } else if module.binary() {
snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if _, ok := module.linker.(*prebuiltBinaryLinker); ok {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else if module.object() {
+ snapshotMap = vendorSnapshotObjects(ctx.Config())
} else {
return
}
diff --git a/cc/vndk.go b/cc/vndk.go
index dbe1f3b..04b865f 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -25,6 +25,7 @@
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/etc"
)
const (
@@ -309,7 +310,13 @@
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")
}
@@ -410,7 +417,7 @@
outputFile android.OutputPath
}
-var _ android.PrebuiltEtcModule = &vndkLibrariesTxt{}
+var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
var _ android.OutputFileProducer = &vndkLibrariesTxt{}
// vndk_libraries_txt is a special kind of module type in that it name is one of
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 53b5181..5a44c46 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -186,6 +186,10 @@
return false
}
+func (p *vndkPrebuiltLibraryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func (p *vndkPrebuiltLibraryDecorator) install(ctx ModuleContext, file android.Path) {
arches := ctx.DeviceConfig().Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
diff --git a/cmd/extract_apks/Android.bp b/cmd/extract_apks/Android.bp
new file mode 100644
index 0000000..90548cd
--- /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 0000000..bbf3314
--- /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 0000000..b36340b
--- /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 0000000..a28147a
--- /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 0000000..1c161aa
--- /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 0000000..89fb655
--- /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 0000000..187bc44
--- /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 0000000..cdc910b
--- /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 0000000..e9a850e
--- /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 0000000..bdd4bec
--- /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 f7163d7..629f6cc 100644
--- a/cmd/host_bionic_inject/host_bionic_inject.go
+++ b/cmd/host_bionic_inject/host_bionic_inject.go
@@ -105,7 +105,9 @@
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 191b919..d341b8c 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -213,10 +213,14 @@
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) 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 @@
{{- 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 @@
{{- 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 @@
{{- 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 bd1a9ed..905f206 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -18,12 +18,7 @@
"flag"
"fmt"
"os"
- "os/exec"
"path/filepath"
- "strconv"
- "strings"
- "syscall"
- "time"
"github.com/google/blueprint/bootstrap"
@@ -55,42 +50,7 @@
}
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/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 1d94f02..d0cad78 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -117,6 +117,8 @@
// Command is the type of soong_ui execution. Only one type of
// execution is specified. The args are specific to the command.
func main() {
+ buildStartedMilli := time.Now().UnixNano() / int64(time.Millisecond)
+
c, args := getCommand(os.Args)
if c == nil {
fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
@@ -166,12 +168,17 @@
logsDir = filepath.Join(config.DistDir(), "logs")
}
+ buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
+ rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
+ soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
+ defer build.UploadMetrics(buildCtx, config, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
- stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
+ stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
stat.AddOutput(status.NewCriticalPath(log))
stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
@@ -179,7 +186,7 @@
buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
- defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
+ defer met.Dump(soongMetricsFile)
if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
if !strings.HasSuffix(start, "N") {
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 98850e5..3440f8e 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -50,6 +50,8 @@
UpdatableSystemServerJars []string // jars within apex that are loaded into system server
SpeedApps []string // apps that should be speed optimized
+ BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error
+
PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified
DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags
@@ -98,6 +100,15 @@
ConstructContext android.Path
}
+// LibraryPath contains paths to the library DEX jar on host and on device.
+type LibraryPath struct {
+ Host android.Path
+ Device string
+}
+
+// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
+type LibraryPaths map[string]*LibraryPath
+
type ModuleConfig struct {
Name string
DexLocation string // dex location on device
@@ -115,7 +126,7 @@
EnforceUsesLibraries bool
PresentOptionalUsesLibraries []string
UsesLibraries []string
- LibraryPaths map[string]android.Path
+ LibraryPaths LibraryPaths
Archs []android.ArchType
DexPreoptImages []android.Path
@@ -163,14 +174,6 @@
return ret
}
-func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path {
- ret := map[string]android.Path{}
- for key, path := range paths {
- ret[key] = constructPath(ctx, path)
- }
- return ret
-}
-
func constructWritablePath(ctx android.PathContext, path string) android.WritablePath {
if path == "" {
return nil
@@ -262,6 +265,13 @@
// from Make to read the module dexpreopt.config written in the Make config
// stage.
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
+ type jsonLibraryPath struct {
+ Host string
+ Device string
+ }
+
+ type jsonLibraryPaths map[string]jsonLibraryPath
+
type ModuleJSONConfig struct {
*ModuleConfig
@@ -271,12 +281,24 @@
DexPath string
ManifestPath string
ProfileClassListing string
- LibraryPaths map[string]string
+ LibraryPaths jsonLibraryPaths
DexPreoptImages []string
DexPreoptImageLocations []string
PreoptBootClassPathDexFiles []string
}
+ // convert JSON map of library paths to LibraryPaths
+ constructLibraryPaths := func(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
+ m := LibraryPaths{}
+ for lib, path := range paths {
+ m[lib] = &LibraryPath{
+ constructPath(ctx, path.Host),
+ path.Device,
+ }
+ }
+ return m
+ }
+
config := ModuleJSONConfig{}
err := json.Unmarshal(data, &config)
@@ -289,7 +311,7 @@
config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
- config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
+ config.ModuleConfig.LibraryPaths = constructLibraryPaths(ctx, config.LibraryPaths)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index f1dde9c..57a9250 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -37,6 +37,7 @@
"fmt"
"path/filepath"
"runtime"
+ "sort"
"strings"
"android/soong/android"
@@ -82,7 +83,7 @@
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 +105,7 @@
// 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 +114,7 @@
// 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
}
@@ -192,6 +193,56 @@
return profilePath
}
+type classLoaderContext struct {
+ // The class loader context using paths in the build.
+ Host android.Paths
+
+ // The class loader context using paths as they will be on the device.
+ Target []string
+}
+
+// A map of class loader contexts for each SDK version.
+// A map entry for "any" version contains libraries that are unconditionally added to class loader
+// context. Map entries for existing versions contains libraries that were in the default classpath
+// until that API version, and should be added to class loader context if and only if the
+// targetSdkVersion in the manifest or APK is less than that API version.
+type classLoaderContextMap map[int]*classLoaderContext
+
+const anySdkVersion int = -1
+
+func (m classLoaderContextMap) getSortedKeys() []int {
+ keys := make([]int, 0, len(m))
+ for k := range m {
+ keys = append(keys, k)
+ }
+ sort.Ints(keys)
+ return keys
+}
+
+func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
+ if _, ok := m[sdkVer]; !ok {
+ m[sdkVer] = &classLoaderContext{}
+ }
+ return m[sdkVer]
+}
+
+func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) {
+ clc := m.getValue(sdkVer)
+ for _, lib := range libs {
+ p := pathForLibrary(module, lib)
+ clc.Host = append(clc.Host, p.Host)
+ clc.Target = append(clc.Target, p.Device)
+ }
+}
+
+func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
+ clc := m.getValue(sdkVer)
+ for _, lib := range libs {
+ clc.Host = append(clc.Host, SystemServerDexJarHostPath(ctx, lib))
+ clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
+ }
+}
+
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
appImage bool, generateDM bool) {
@@ -227,77 +278,45 @@
systemServerJars := NonUpdatableSystemServerJars(ctx, global)
- // The class loader context using paths in the build
- var classLoaderContextHost android.Paths
-
- // The class loader context using paths as they will be on the device
- var classLoaderContextTarget []string
-
- // Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 28
- var conditionalClassLoaderContextHost28 android.Paths
- var conditionalClassLoaderContextTarget28 []string
-
- // Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 29
- var conditionalClassLoaderContextHost29 android.Paths
- var conditionalClassLoaderContextTarget29 []string
+ classLoaderContexts := make(classLoaderContextMap)
// A flag indicating if the '&' class loader context is used.
unknownClassLoaderContext := false
if module.EnforceUsesLibraries {
+ // Unconditional class loader context.
usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
+ classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...)
- // Create class loader context for dex2oat from uses libraries and filtered optional libraries
- for _, l := range usesLibs {
-
- classLoaderContextHost = append(classLoaderContextHost,
- pathForLibrary(module, l))
- classLoaderContextTarget = append(classLoaderContextTarget,
- filepath.Join("/system/framework", l+".jar"))
- }
-
+ // Conditional class loader context for API version < 28.
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) {
- conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
- pathForLibrary(module, httpLegacyImpl))
- conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
- filepath.Join("/system/framework", httpLegacyImpl+".jar"))
+ if !contains(usesLibs, httpLegacy) {
+ classLoaderContexts.addLibs(28, module, httpLegacy)
}
- const hidlBase = "android.hidl.base-V1.0-java"
- const hidlManager = "android.hidl.manager-V1.0-java"
+ // Conditional class loader context for API version < 29.
+ usesLibs29 := []string{
+ "android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.0-java",
+ }
+ classLoaderContexts.addLibs(29, module, usesLibs29...)
- // 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.
- conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29,
- pathForLibrary(module, hidlManager))
- conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
- filepath.Join("/system/framework", hidlManager+".jar"))
- conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29,
- pathForLibrary(module, hidlBase))
- conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
- filepath.Join("/system/framework", hidlBase+".jar"))
+ // Conditional class loader context for API version < 30.
+ const testBase = "android.test.base"
+ if !contains(usesLibs, testBase) {
+ classLoaderContexts.addLibs(30, module, testBase)
+ }
} 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.
- for _, otherJar := range systemServerJars[:jarIndex] {
- classLoaderContextHost = append(classLoaderContextHost, SystemServerDexJarHostPath(ctx, otherJar))
- classLoaderContextTarget = append(classLoaderContextTarget, "/system/framework/"+otherJar+".jar")
- }
+ classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
// Copy the system server jar to a predefined location where dex2oat will find it.
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost)
+
+ checkSystemServerOrder(ctx, jarIndex)
} else {
// Pass special class loader context to skip the classpath and collision check.
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
@@ -314,10 +333,11 @@
Text(`class_loader_context_arg=--class-loader-context=\&`).
Text(`stored_class_loader_context_arg=""`)
} else {
+ clc := classLoaderContexts[anySdkVersion]
rule.Command().
- Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(classLoaderContextHost.Strings(), ":") + "]").
- Implicits(classLoaderContextHost).
- Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(classLoaderContextTarget, ":") + "]")
+ Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
+ Implicits(clc.Host).
+ Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
}
if module.EnforceUsesLibraries {
@@ -336,21 +356,19 @@
Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
Text(`)"`)
}
- rule.Command().Textf(`dex_preopt_host_libraries="%s"`,
- strings.Join(classLoaderContextHost.Strings(), " ")).
- Implicits(classLoaderContextHost)
- rule.Command().Textf(`dex_preopt_target_libraries="%s"`,
- strings.Join(classLoaderContextTarget, " "))
- rule.Command().Textf(`conditional_host_libs_28="%s"`,
- strings.Join(conditionalClassLoaderContextHost28.Strings(), " ")).
- Implicits(conditionalClassLoaderContextHost28)
- rule.Command().Textf(`conditional_target_libs_28="%s"`,
- strings.Join(conditionalClassLoaderContextTarget28, " "))
- rule.Command().Textf(`conditional_host_libs_29="%s"`,
- strings.Join(conditionalClassLoaderContextHost29.Strings(), " ")).
- Implicits(conditionalClassLoaderContextHost29)
- rule.Command().Textf(`conditional_target_libs_29="%s"`,
- strings.Join(conditionalClassLoaderContextTarget29, " "))
+ for _, ver := range classLoaderContexts.getSortedKeys() {
+ clc := classLoaderContexts.getValue(ver)
+ var varHost, varTarget string
+ if ver == anySdkVersion {
+ varHost = "dex_preopt_host_libraries"
+ varTarget = "dex_preopt_target_libraries"
+ } else {
+ varHost = fmt.Sprintf("conditional_host_libs_%d", ver)
+ varTarget = fmt.Sprintf("conditional_target_libs_%d", ver)
+ }
+ rule.Command().Textf(varHost+`="%s"`, strings.Join(clc.Host.Strings(), " ")).Implicits(clc.Host)
+ rule.Command().Textf(varTarget+`="%s"`, strings.Join(clc.Target, " "))
+ }
rule.Command().Text("source").Tool(globalSoong.ConstructContext).Input(module.DexPath)
}
@@ -540,7 +558,7 @@
return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
}
-func pathForLibrary(module *ModuleConfig, lib string) android.Path {
+func pathForLibrary(module *ModuleConfig, lib string) *LibraryPath {
path, ok := module.LibraryPaths[lib]
if !ok {
panic(fmt.Errorf("unknown library path for %q", lib))
@@ -561,8 +579,8 @@
}
// 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 +591,7 @@
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)
}
@@ -592,6 +610,29 @@
}
}
+// Check the order of jars on the system server classpath and give a warning/error if a jar precedes
+// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't
+// have the dependency jar in the class loader context, and it won't be able to resolve any
+// references to its classes and methods.
+func checkSystemServerOrder(ctx android.PathContext, jarIndex int) {
+ mctx, isModule := ctx.(android.ModuleContext)
+ if isModule {
+ config := GetGlobalConfig(ctx)
+ jars := NonUpdatableSystemServerJars(ctx, config)
+ mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ depIndex := android.IndexList(dep.Name(), jars)
+ if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
+ jar := jars[jarIndex]
+ dep := jars[depIndex]
+ mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
+ " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
+ " references from '%s' to '%s'.\n", jar, dep, jar, dep)
+ }
+ return true
+ })
+ }
+}
+
func contains(l []string, s string) bool {
for _, e := range l {
if e == s {
diff --git a/env/Android.bp b/env/Android.bp
new file mode 100644
index 0000000..90c6047
--- /dev/null
+++ b/env/Android.bp
@@ -0,0 +1,7 @@
+bootstrap_go_package {
+ name: "soong-env",
+ pkgPath: "android/soong/env",
+ srcs: [
+ "env.go",
+ ],
+}
diff --git a/etc/Android.bp b/etc/Android.bp
new file mode 100644
index 0000000..cfd303e
--- /dev/null
+++ b/etc/Android.bp
@@ -0,0 +1,16 @@
+bootstrap_go_package {
+ name: "soong-etc",
+ pkgPath: "android/soong/etc",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "prebuilt_etc.go",
+ ],
+ testSrcs: [
+ "prebuilt_etc_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
new file mode 100644
index 0000000..d6eb008
--- /dev/null
+++ b/etc/prebuilt_etc.go
@@ -0,0 +1,295 @@
+// Copyright 2016 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 etc
+
+import (
+ "strconv"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+var pctx = android.NewPackageContext("android/soong/etc")
+
+// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
+
+func init() {
+ pctx.Import("android/soong/android")
+
+ android.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
+ android.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
+ android.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
+ android.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
+ android.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
+ android.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
+}
+
+type prebuiltEtcProperties struct {
+ // Source file of this prebuilt.
+ Src *string `android:"path,arch_variant"`
+
+ // optional subdirectory under which this file is installed into
+ Sub_dir *string `android:"arch_variant"`
+
+ // optional name for the installed file. If unspecified, name of the module is used as the file name
+ Filename *string `android:"arch_variant"`
+
+ // when set to true, and filename property is not set, the name for the installed file
+ // is the same as the file name of the source file.
+ Filename_from_src *bool `android:"arch_variant"`
+
+ // Make this module available when building for ramdisk.
+ Ramdisk_available *bool
+
+ // Make this module available when building for recovery.
+ Recovery_available *bool
+
+ // 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 {
+ android.Module
+ SubDir() string
+ OutputFile() android.OutputPath
+}
+
+type PrebuiltEtc struct {
+ android.ModuleBase
+
+ properties prebuiltEtcProperties
+
+ sourceFilePath android.Path
+ outputFilePath android.OutputPath
+ // The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
+ installDirBase string
+ // The base install location when soc_specific property is set to true, e.g. "firmware" for prebuilt_firmware.
+ socInstallDirBase string
+ installDirPath android.InstallPath
+ additionalDependencies *android.Paths
+}
+
+func (p *PrebuiltEtc) inRamdisk() bool {
+ return p.ModuleBase.InRamdisk() || p.ModuleBase.InstallInRamdisk()
+}
+
+func (p *PrebuiltEtc) onlyInRamdisk() bool {
+ return p.ModuleBase.InstallInRamdisk()
+}
+
+func (p *PrebuiltEtc) InstallInRamdisk() bool {
+ return p.inRamdisk()
+}
+
+func (p *PrebuiltEtc) inRecovery() bool {
+ return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
+}
+
+func (p *PrebuiltEtc) onlyInRecovery() bool {
+ return p.ModuleBase.InstallInRecovery()
+}
+
+func (p *PrebuiltEtc) InstallInRecovery() bool {
+ return p.inRecovery()
+}
+
+var _ android.ImageInterface = (*PrebuiltEtc)(nil)
+
+func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+
+func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk()
+}
+
+func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
+}
+
+func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
+}
+
+func (p *PrebuiltEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ return nil
+}
+
+func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
+}
+
+func (p *PrebuiltEtc) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if p.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ }
+}
+
+func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
+ return android.PathForModuleSrc(ctx, android.String(p.properties.Src))
+}
+
+func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
+ return p.installDirPath
+}
+
+// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
+// additional steps (like validating the src) before the file is installed.
+func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) {
+ p.additionalDependencies = &paths
+}
+
+func (p *PrebuiltEtc) OutputFile() android.OutputPath {
+ return p.outputFilePath
+}
+
+func (p *PrebuiltEtc) SubDir() string {
+ return android.String(p.properties.Sub_dir)
+}
+
+func (p *PrebuiltEtc) Installable() bool {
+ return p.properties.Installable == nil || android.Bool(p.properties.Installable)
+}
+
+func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.sourceFilePath = android.PathForModuleSrc(ctx, android.String(p.properties.Src))
+ filename := android.String(p.properties.Filename)
+ filename_from_src := android.Bool(p.properties.Filename_from_src)
+ if filename == "" {
+ if filename_from_src {
+ filename = p.sourceFilePath.Base()
+ } else {
+ filename = ctx.ModuleName()
+ }
+ } else if filename_from_src {
+ ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+ return
+ }
+ p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
+
+ // If soc install dir was specified and SOC specific is set, set the installDirPath to the specified
+ // socInstallDirBase.
+ installBaseDir := p.installDirBase
+ if ctx.SocSpecific() && p.socInstallDirBase != "" {
+ installBaseDir = p.socInstallDirBase
+ }
+ p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, proptools.String(p.properties.Sub_dir))
+
+ // This ensures that outputFilePath has the correct name for others to
+ // use, as the source file may have a different name.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: p.outputFilePath,
+ Input: p.sourceFilePath,
+ })
+}
+
+func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
+ nameSuffix := ""
+ if p.inRamdisk() && !p.onlyInRamdisk() {
+ nameSuffix = ".ramdisk"
+ }
+ if p.inRecovery() && !p.onlyInRecovery() {
+ nameSuffix = ".recovery"
+ }
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ SubName: nameSuffix,
+ OutputFile: android.OptionalPathForPath(p.outputFilePath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.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.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", path.String())
+ }
+ }
+ },
+ },
+ }}
+}
+
+func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) {
+ p.installDirBase = dirBase
+ p.AddProperties(&p.properties)
+}
+
+// prebuilt_etc is for a prebuilt artifact that is installed in
+// <partition>/etc/<sub_dir> directory.
+func PrebuiltEtcFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "etc")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+// prebuilt_etc_host is for a host prebuilt artifact that is installed in
+// $(HOST_OUT)/etc/<sub_dir> directory.
+func PrebuiltEtcHostFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "etc")
+ // This module is host-only
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+ return module
+}
+
+// prebuilt_usr_share is for a prebuilt artifact that is installed in
+// <partition>/usr/share/<sub_dir> directory.
+func PrebuiltUserShareFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/share")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+// prebuild_usr_share_host is for a host prebuilt artifact that is installed in
+// $(HOST_OUT)/usr/share/<sub_dir> directory.
+func PrebuiltUserShareHostFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/share")
+ // This module is host-only
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+ return module
+}
+
+// prebuilt_font installs a font in <partition>/fonts directory.
+func PrebuiltFontFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "fonts")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+// prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system image.
+// If soc_specific property is set to true, the firmware file is installed to the vendor <partition>/firmware
+// directory for vendor image.
+func PrebuiltFirmwareFactory() android.Module {
+ module := &PrebuiltEtc{}
+ module.socInstallDirBase = "firmware"
+ InitPrebuiltEtcModule(module, "etc/firmware")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
diff --git a/android/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
similarity index 89%
rename from android/prebuilt_etc_test.go
rename to etc/prebuilt_etc_test.go
index 6e751e7..e13cb3c 100644
--- a/android/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -12,24 +12,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package android
+package etc
import (
+ "io/ioutil"
+ "os"
"path/filepath"
"reflect"
"testing"
+
+ "android/soong/android"
)
-func testPrebuiltEtc(t *testing.T, bp string) (*TestContext, Config) {
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_etc_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testPrebuiltEtc(t *testing.T, bp string) (*android.TestContext, android.Config) {
fs := map[string][]byte{
"foo.conf": nil,
"bar.conf": nil,
"baz.conf": nil,
}
- config := TestArchConfig(buildDir, nil, bp, fs)
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := NewTestArchContext()
+ ctx := android.NewTestArchContext()
ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
@@ -38,9 +67,9 @@
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
+ android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ android.FailIfErrored(t, errs)
return ctx, config
}
@@ -142,7 +171,7 @@
}
mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
- entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
for k, expectedValue := range expected {
if value, ok := entries.EntryMap[k]; ok {
if !reflect.DeepEqual(value, expectedValue) {
@@ -162,7 +191,7 @@
}
`)
- buildOS := BuildOs.String()
+ buildOS := android.BuildOs.String()
p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
if !p.Host() {
t.Errorf("host bit is not set for a prebuilt_etc_host module.")
@@ -194,7 +223,7 @@
}
`)
- buildOS := BuildOs.String()
+ buildOS := android.BuildOs.String()
p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar")
if p.installDirPath.String() != expected {
diff --git a/genrule/Android.bp b/genrule/Android.bp
new file mode 100644
index 0000000..ff543a6
--- /dev/null
+++ b/genrule/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+ name: "soong-genrule",
+ pkgPath: "android/soong/genrule",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-shared",
+ ],
+ srcs: [
+ "genrule.go",
+ ],
+ testSrcs: [
+ "genrule_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index fe877fe..f6904f1 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -144,6 +144,9 @@
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 (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 @@
dpInfo.Deps = append(dpInfo.Deps, src)
}
}
+ dpInfo.Paths = append(dpInfo.Paths, g.modulePaths...)
}
func (g *Module) AndroidMk() android.AndroidMkData {
diff --git a/java/Android.bp b/java/Android.bp
new file mode 100644
index 0000000..2de1b8e
--- /dev/null
+++ b/java/Android.bp
@@ -0,0 +1,66 @@
+bootstrap_go_package {
+ name: "soong-java",
+ pkgPath: "android/soong/java",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-dexpreopt",
+ "soong-genrule",
+ "soong-java-config",
+ "soong-remoteexec",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "aapt2.go",
+ "aar.go",
+ "android_manifest.go",
+ "android_resources.go",
+ "androidmk.go",
+ "app_builder.go",
+ "app.go",
+ "builder.go",
+ "device_host_converter.go",
+ "dex.go",
+ "dexpreopt.go",
+ "dexpreopt_bootjars.go",
+ "dexpreopt_config.go",
+ "droiddoc.go",
+ "gen.go",
+ "genrule.go",
+ "hiddenapi.go",
+ "hiddenapi_singleton.go",
+ "jacoco.go",
+ "java.go",
+ "jdeps.go",
+ "java_resources.go",
+ "kotlin.go",
+ "platform_compat_config.go",
+ "plugin.go",
+ "prebuilt_apis.go",
+ "proto.go",
+ "robolectric.go",
+ "sdk.go",
+ "sdk_library.go",
+ "support_libraries.go",
+ "sysprop.go",
+ "system_modules.go",
+ "testing.go",
+ "tradefed.go",
+ ],
+ testSrcs: [
+ "androidmk_test.go",
+ "app_test.go",
+ "device_host_converter_test.go",
+ "dexpreopt_test.go",
+ "dexpreopt_bootjars_test.go",
+ "java_test.go",
+ "jdeps_test.go",
+ "kotlin_test.go",
+ "plugin_test.go",
+ "sdk_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/java/aar.go b/java/aar.go
index 6e3b9e6..7413c80 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -379,8 +379,11 @@
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 @@
module.androidLibraryProperties.BuildAAR = true
+ android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
return module
}
@@ -537,8 +541,12 @@
type AARImport struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.ApexModuleBase
prebuilt android.Prebuilt
+ // Functionality common to Module and Import.
+ embeddableInModuleAndImport
+
properties AARImportProperties
classpathFile android.WritablePath
@@ -722,7 +730,7 @@
return android.Paths{a.classpathFile}
}
-func (a *AARImport) DexJar() android.Path {
+func (a *AARImport) DexJarBuildPath() android.Path {
return nil
}
@@ -742,6 +750,10 @@
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 @@
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 2c29192..62cf169 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -69,7 +69,26 @@
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 *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 *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+ if !a.IsForPlatform() {
+ return []android.AndroidMkEntries{{
+ Disabled: true,
+ }}
+ }
entriesList := a.Library.AndroidMkEntries()
entries := &entriesList[0]
@@ -502,14 +531,12 @@
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 (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 48ef90b..24dde79 100755
--- a/java/app.go
+++ b/java/app.go
@@ -20,6 +20,7 @@
"path/filepath"
"reflect"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -27,6 +28,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/dexpreopt"
"android/soong/tradefed"
)
@@ -49,6 +51,126 @@
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)
+}
+
+func (as *AndroidAppSet) OutputFile() android.Path {
+ return as.packedOutput
+}
+
+func (as *AndroidAppSet) MasterFile() string {
+ return as.masterFile
+}
+
+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, ctx.ModuleName()+".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(),
+ },
+ })
+}
+
+// android_app_set extracts a set of APKs based on the target device
+// configuration and installs this set as "split APKs".
+// The extracted set always contains 'master' APK whose name is
+// _module_name_.apk and every split APK matching target device.
+// The extraction of the density-specific splits depends on
+// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
+// be a list density names: LDPI, MDPI, HDPI, etc.), only listed
+// splits will be extracted. Otherwise all density-specific splits
+// will be extracted.
+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 @@
// 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
@@ -175,6 +300,8 @@
noticeOutputs android.NoticeOutputs
overriddenManifestPackageName string
+
+ android.ApexBundleDepsInfo
}
func (a *AndroidApp) IsInstallable() bool {
@@ -208,7 +335,7 @@
presigned bool
}
-var presignedCertificate = Certificate{presigned: true}
+var PresignedCertificate = Certificate{presigned: true}
func (c Certificate) AndroidMkString() string {
if c.presigned {
@@ -230,6 +357,16 @@
a.aapt.deps(ctx, sdkDep)
}
+ usesSDK := a.sdkVersion().specified() && a.sdkVersion().kind != sdkCorePlatform
+
+ if usesSDK && Bool(a.appProperties.Jni_uses_sdk_apis) {
+ ctx.PropertyErrorf("jni_uses_sdk_apis",
+ "can only be set for modules that do not set sdk_version")
+ } else if !usesSDK && Bool(a.appProperties.Jni_uses_platform_apis) {
+ ctx.PropertyErrorf("jni_uses_platform_apis",
+ "can only be set for modules that set sdk_version")
+ }
+
tag := &jniDependencyTag{}
for _, jniTarget := range ctx.MultiTargets() {
variation := append(jniTarget.Variations(),
@@ -237,8 +374,10 @@
// If the app builds against an Android SDK use the SDK variant of JNI dependencies
// unless jni_uses_platform_apis is set.
- if a.sdkVersion().specified() && a.sdkVersion().kind != sdkCorePlatform &&
- !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"})
}
@@ -275,19 +414,50 @@
}
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)
+ // The domain of cc.sdk_version is "current" and <number>
+ // We can rely on sdkSpec to convert it to <number> so that "current" is handled
+ // properly regardless of sdk finalization.
+ jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx)
+ if err != nil || 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 {
@@ -401,16 +571,17 @@
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)
}
@@ -573,7 +744,7 @@
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() {
@@ -585,13 +756,17 @@
// 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)
}
@@ -607,14 +782,29 @@
ctx.InstallFile(a.installDir, extra.Base(), extra)
}
}
+
+ 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)
@@ -632,16 +822,9 @@
}
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() {
@@ -675,6 +858,53 @@
return jniLibs, certificates
}
+func (a *AndroidApp) walkPayloadDeps(ctx android.ModuleContext,
+ do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
+
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ isExternal := !a.DepIsInSameApex(ctx, child)
+ if am, ok := child.(android.ApexModule); ok {
+ do(ctx, parent, am, isExternal)
+ }
+ return !isExternal
+ })
+}
+
+func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) {
+ if ctx.Host() {
+ return
+ }
+
+ depsInfo := android.DepNameToDepInfoMap{}
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ depName := to.Name()
+ if info, exist := depsInfo[depName]; exist {
+ info.From = append(info.From, from.Name())
+ info.IsExternal = info.IsExternal && externalDep
+ depsInfo[depName] = info
+ } else {
+ toMinSdkVersion := "(no version)"
+ if m, ok := to.(interface{ MinSdkVersion() string }); ok {
+ if v := m.MinSdkVersion(); v != "" {
+ toMinSdkVersion = v
+ }
+ }
+ depsInfo[depName] = android.ApexModuleDepInfo{
+ To: depName,
+ From: []string{from.Name()},
+ IsExternal: externalDep,
+ MinSdkVersion: toMinSdkVersion,
+ }
+ }
+ })
+
+ 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 {
@@ -779,6 +1009,7 @@
}
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)
@@ -791,8 +1022,12 @@
}
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)
}
@@ -954,7 +1189,7 @@
android.OverrideModuleBase
}
-func (i *OverrideAndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideAndroidApp) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -975,7 +1210,7 @@
android.OverrideModuleBase
}
-func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideAndroidTest) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -997,7 +1232,7 @@
android.OverrideModuleBase
}
-func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -1030,6 +1265,8 @@
usesLibrary usesLibrary
+ preprocessed bool
+
installPath android.InstallPath
}
@@ -1045,6 +1282,9 @@
// 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
@@ -1119,7 +1359,7 @@
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,
@@ -1140,7 +1380,7 @@
// 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
}
@@ -1188,7 +1428,7 @@
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
@@ -1232,9 +1472,13 @@
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)
@@ -1243,13 +1487,17 @@
}
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)
TransformZipAlign(ctx, alignedApk, dexOutput)
a.outputFile = alignedApk
- a.certificate = presignedCertificate
+ a.certificate = PresignedCertificate
}
// TODO: Optionally compress the output apk.
@@ -1307,13 +1555,21 @@
return Bool(a.properties.Privileged)
}
-func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
// android_app_import might have extra dependencies via uses_libs property.
// Don't track the dependency as we don't automatically add those libraries
// to the classpath. It should be explicitly added to java_libs property of APEX
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))
@@ -1361,21 +1617,31 @@
})
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)
@@ -1393,11 +1659,14 @@
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)
})
+ module.dexpreopter.isTest = true
+
android.InitApexModule(module)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
@@ -1426,6 +1695,9 @@
// 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
@@ -1497,10 +1769,14 @@
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
@@ -1590,6 +1866,7 @@
"org.apache.http.legacy",
"android.hidl.base-V1.0-java",
"android.hidl.manager-V1.0-java")
+ ctx.AddVariationDependencies(nil, usesLibTag, optionalUsesLibs...)
}
}
}
@@ -1601,24 +1878,30 @@
return optionalUsesLibs
}
-// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
-func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
- usesLibPaths := make(map[string]android.Path)
+// usesLibraryPaths returns a map of module names of shared library dependencies to the paths
+// to their dex jars on host and on device.
+func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths {
+ usesLibPaths := make(dexpreopt.LibraryPaths)
if !ctx.Config().UnbundledBuild() {
ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
+ dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok {
- if dexJar := lib.DexJar(); dexJar != nil {
- usesLibPaths[ctx.OtherModuleName(m)] = dexJar
+ if dexJar := lib.DexJarBuildPath(); dexJar != nil {
+ usesLibPaths[dep] = &dexpreopt.LibraryPath{
+ dexJar,
+ // TODO(b/132357300): propagate actual install paths here.
+ filepath.Join("/system/framework", dep+".jar"),
+ }
} else {
- ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
- ctx.OtherModuleName(m))
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must"+
+ " produce a dex jar, does it have installable: true?", dep)
}
} else if ctx.Config().AllowMissingDependencies() {
- ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
+ ctx.AddMissingDependencies([]string{dep})
} else {
- ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
- ctx.OtherModuleName(m))
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be "+
+ "a java library", dep)
}
})
}
diff --git a/java/app_builder.go b/java/app_builder.go
index 5e7fbe6..014bd54 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -26,16 +26,23 @@
"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 @@
})
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 @@
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 @@
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 @@
"-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 998c76a..eeba161 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -141,6 +141,94 @@
}
}
+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 = "foo.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 = "foo.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_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
@@ -1110,12 +1319,130 @@
}
}
+func TestJNISDK(t *testing.T) {
+ ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+ cc_library {
+ name: "libjni",
+ system_shared_libs: [],
+ stl: "none",
+ sdk_version: "current",
+ }
+
+ android_test {
+ name: "app_platform",
+ jni_libs: ["libjni"],
+ platform_apis: true,
+ }
+
+ android_test {
+ name: "app_sdk",
+ jni_libs: ["libjni"],
+ sdk_version: "current",
+ }
+
+ android_test {
+ name: "app_force_platform",
+ jni_libs: ["libjni"],
+ sdk_version: "current",
+ jni_uses_platform_apis: true,
+ }
+
+ android_test {
+ name: "app_force_sdk",
+ jni_libs: ["libjni"],
+ 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
+ vendorJNI bool
+ }{
+ {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")
+
+ jniLibZip := app.MaybeOutput("jnilibs.zip")
+ if len(jniLibZip.Implicits) != 1 {
+ t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
+ }
+ gotJNI := jniLibZip.Implicits[0].String()
+
+ if test.sdkJNI {
+ 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)
+ }
+ }
+ })
+ }
+
+ t.Run("jni_uses_platform_apis_error", func(t *testing.T) {
+ testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, `
+ android_test {
+ name: "app_platform",
+ platform_apis: true,
+ jni_uses_platform_apis: true,
+ }
+ `)
+ })
+
+ t.Run("jni_uses_sdk_apis_error", func(t *testing.T) {
+ testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, `
+ android_test {
+ name: "app_sdk",
+ sdk_version: "current",
+ jni_uses_sdk_apis: true,
+ }
+ `)
+ })
+
+}
+
func TestCertificates(t *testing.T) {
testCases := []struct {
name string
bp string
certificateOverride string
- expected string
+ expectedLineage string
+ expectedCertificate string
}{
{
name: "default",
@@ -1127,7 +1454,8 @@
}
`,
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",
@@ -1141,11 +1469,12 @@
android_app_certificate {
name: "new_certificate",
- certificate: "cert/new_cert",
+ certificate: "cert/new_cert",
}
`,
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",
@@ -1158,7 +1487,8 @@
}
`,
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",
@@ -1172,11 +1502,32 @@
android_app_certificate {
name: "new_certificate",
- certificate: "cert/new_cert",
+ certificate: "cert/new_cert",
}
`,
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",
},
}
@@ -1192,9 +1543,14 @@
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)
}
})
}
@@ -1308,6 +1664,7 @@
name: "bar",
base: "foo",
certificate: ":new_certificate",
+ lineage: "lineage.bin",
logging_parent: "bah",
}
@@ -1328,7 +1685,8 @@
variantName string
apkName string
apkPath string
- signFlag string
+ certFlag string
+ lineageFlag string
overrides []string
aaptFlag string
logging_parent string
@@ -1337,7 +1695,8 @@
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: "",
@@ -1346,7 +1705,8 @@
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",
@@ -1355,7 +1715,8 @@
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: "",
@@ -1380,9 +1741,15 @@
// 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.
@@ -1704,6 +2071,27 @@
}
}
+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 {
@@ -1981,6 +2369,45 @@
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) {
@@ -2056,6 +2483,20 @@
}
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"],
@@ -2065,6 +2506,7 @@
android_app {
name: "app",
srcs: ["a.java"],
+ libs: ["qux", "quuz.stubs"],
uses_libs: ["foo"],
sdk_version: "current",
optional_uses_libs: [
@@ -2095,6 +2537,15 @@
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) {
@@ -2355,6 +2806,32 @@
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) {
@@ -2418,6 +2895,7 @@
runtime_resource_overlay {
name: "foo",
certificate: "platform",
+ lineage: "lineage.bin",
product_specific: true,
static_libs: ["bar"],
resource_libs: ["baz"],
@@ -2472,6 +2950,11 @@
// 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 3a4a10d..a27e5c3 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -40,17 +40,17 @@
// (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 @@
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 @@
"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 @@
RspfileContent: "$in",
Restat: true,
},
- "javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion")
+ &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 = pctx.AndroidStaticRule("jar",
+ 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 @@
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 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/Android.bp b/java/config/Android.bp
new file mode 100644
index 0000000..1983521
--- /dev/null
+++ b/java/config/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+ name: "soong-java-config",
+ pkgPath: "android/soong/java/config",
+ deps: [
+ "blueprint-proptools",
+ "soong-android",
+ "soong-remoteexec",
+ ],
+ srcs: [
+ "config.go",
+ "error_prone.go",
+ "kotlin.go",
+ "makevars.go",
+ ],
+}
diff --git a/java/config/config.go b/java/config/config.go
index c4f2363..bb5be3a 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -28,8 +28,9 @@
var (
pctx = android.NewPackageContext("android/soong/java/config")
- DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"}
- DefaultSystemModules = "core-platform-api-stubs-system-modules"
+ // TODO(b/157640067): Don't depend on the legacy API by default in the long term.
+ DefaultBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
+ DefaultSystemModules = "legacy-core-platform-api-stubs-system-modules"
DefaultLibraries = []string{"ext", "framework"}
DefaultLambdaStubsLibrary = "core-lambda-stubs"
SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar"
@@ -122,7 +123,7 @@
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 +149,10 @@
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/device_host_converter.go b/java/device_host_converter.go
index b40ab93..1ffb13f 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -150,7 +150,7 @@
return d.implementationAndResourceJars
}
-func (d *DeviceHostConverter) DexJar() android.Path {
+func (d *DeviceHostConverter) DexJarBuildPath() android.Path {
return nil
}
diff --git a/java/dex.go b/java/dex.go
index 27ec6ee..9e61e95 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -18,53 +18,72 @@
"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 @@
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 @@
},
})
}
- 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.go b/java/dexpreopt.go
index 4725b07..2911fd9 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -37,7 +37,7 @@
usesLibs []string
optionalUsesLibs []string
enforceUsesLibs bool
- libraryPaths map[string]android.Path
+ libraryPaths dexpreopt.LibraryPaths
builtInstalled string
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index dffdc24..9d93838 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -109,11 +109,11 @@
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 @@
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) 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))
}
@@ -255,13 +255,13 @@
return -1, nil
}
- jar, hasJar := module.(interface{ DexJar() android.Path })
+ jar, hasJar := module.(interface{ DexJarBuildPath() android.Path })
if !hasJar {
return -1, nil
}
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
}
@@ -296,7 +296,7 @@
panic("unknown boot image: " + image.name)
}
- return index, jar.DexJar()
+ return index, jar.DexJarBuildPath()
}
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
@@ -314,7 +314,7 @@
// 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 @@
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 0946bf0..e9704dc 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -24,7 +24,7 @@
"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,14 +52,39 @@
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
ctx := testContext()
-
RegisterDexpreoptBootJarsComponents(ctx)
-
run(t, ctx, config)
dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
+ rule := dexpreoptBootJars.Output(ruleFile)
- bootArt := dexpreoptBootJars.Output("boot-foo.art")
+ for i := range expectedInputs {
+ expectedInputs[i] = filepath.Join(buildDir, "test_device", expectedInputs[i])
+ }
+
+ 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",
@@ -68,47 +93,43 @@
"dex_bootjars_input/baz.jar",
}
- for i := range expectedInputs {
- expectedInputs[i] = filepath.Join(buildDir, "test_device", expectedInputs[i])
- }
-
- inputs := bootArt.Implicits.Strings()
- sort.Strings(inputs)
- sort.Strings(expectedInputs)
-
- if !reflect.DeepEqual(inputs, expectedInputs) {
- t.Errorf("want inputs %q\n got inputs %q", expectedInputs, inputs)
- }
-
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)
+}
+
+// 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))
+ }
+ }
}
- outputs := append(android.WritablePaths{bootArt.Output}, bootArt.ImplicitOutputs...).Strings()
- sort.Strings(outputs)
- sort.Strings(expectedOutputs)
-
- 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 41a2ca7..f13d9f2 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -39,7 +39,7 @@
// 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 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 @@
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 @@
// 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 @@
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 879353d..4c3e112 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -222,8 +222,22 @@
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 @@
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 @@
srcFiles android.Paths
sourcepaths android.Paths
argFiles android.Paths
+ implicits android.Paths
args string
@@ -527,7 +547,7 @@
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 @@
// 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 @@
}
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) 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 {
@@ -1285,13 +1334,10 @@
d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
- if len(d.properties.Merge_annotations_dirs) == 0 {
- ctx.PropertyErrorf("merge_annotations_dirs",
- "has to be non-empty if annotations was enabled!")
+ if len(d.properties.Merge_annotations_dirs) != 0 {
+ d.mergeAnnoDirFlags(ctx, cmd)
}
- d.mergeAnnoDirFlags(ctx, cmd)
-
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
@@ -1373,10 +1419,25 @@
}
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()
+
+ var implicitsRsp android.WritablePath
+ if len(implicits) > 0 {
+ implicitsRsp = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
+ 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
@@ -1392,9 +1453,10 @@
inputs = append(inputs, strings.Split(v, ",")...)
}
cmd.Text((&remoteexec.REParams{
- Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "metalava"},
+ Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "metalava", "shallow": "true"},
ExecStrategy: execStrategy,
Inputs: inputs,
+ RSPFile: implicitsRsp.String(),
ToolchainInputs: []string{config.JavaCmd(ctx).String()},
Platform: map[string]string{remoteexec.PoolKey: pool},
}).NoVarTemplate(ctx.Config()))
@@ -1405,7 +1467,12 @@
FlagWithArg("-encoding ", "UTF-8").
FlagWithArg("-source ", javaVersion.String()).
FlagWithRspFileInputList("@", srcs).
- FlagWithInput("@", srcJarList)
+ FlagWithInput("@", srcJarList).
+ FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
+
+ if implicitsRsp.String() != "" {
+ cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
+ }
if len(bootclasspath) > 0 {
cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
@@ -1452,7 +1519,7 @@
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)
@@ -1521,9 +1588,9 @@
msg += fmt.Sprintf(``+
`2. You can update the baseline by executing the following\n`+
` command:\n`+
- ` cp \\ \n`+
- ` "'"$PWD"$'/%s" \\ \n`+
- ` "'"$PWD"$'/%s" \n`+
+ ` cp \\\n`+
+ ` "'"$PWD"$'/%s" \\\n`+
+ ` "'"$PWD"$'/%s"\n`+
` To submit the revised baseline.txt to the main Android\n`+
` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
} else {
@@ -1907,6 +1974,10 @@
}
}
+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 884a757..ce624bf 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -180,7 +180,9 @@
// 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/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index c7f7cbd..bff591c 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -116,7 +116,7 @@
// Core Platform API stubs
corePlatformStubModules := []string{
- "core.platform.api.stubs",
+ "legacy.core.platform.api.stubs",
}
// Allow products to define their own stubs for custom product jars that apps can use.
@@ -147,7 +147,7 @@
name := ctx.ModuleName(module)
for moduleList, pathList := range moduleListToPathList {
if i := android.IndexList(name, *moduleList); i != -1 {
- pathList[i] = j.DexJar()
+ pathList[i] = j.DexJarBuildPath()
}
}
}
diff --git a/java/java.go b/java/java.go
index 472d3da..af68e56 100644
--- a/java/java.go
+++ b/java/java.go
@@ -95,8 +95,7 @@
}
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 @@
// 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 @@
android.ApexModuleBase
android.SdkBase
+ // Functionality common to Module and Import.
+ embeddableInModuleAndImport
+
properties CompilerProperties
protoProperties android.ProtoProperties
deviceProperties CompilerDeviceProperties
@@ -443,6 +476,9 @@
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) {
@@ -465,7 +501,7 @@
ImplementationJars() android.Paths
ResourceJars() android.Paths
ImplementationAndResourcesJars() android.Paths
- DexJar() android.Path
+ DexJarBuildPath() android.Path
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
ExportedPlugins() (android.Paths, []string)
@@ -474,11 +510,6 @@
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 @@
}
} 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" ||
@@ -803,41 +836,47 @@
}
func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
- ver := m.sdkVersion()
- switch {
- case name == "core.current.stubs" || name == "core.platform.api.stubs" ||
- name == "stub-annotations" || name == "private-stub-annotations-jar" ||
- name == "core-lambda-stubs" || name == "core-generated-annotation-stubs":
+ switch name {
+ case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ "stub-annotations", "private-stub-annotations-jar",
+ "core-lambda-stubs", "core-generated-annotation-stubs":
return javaCore, true
- case ver.kind == sdkCore:
- return javaCore, false
- case name == "android_system_stubs_current":
- return javaSystem, true
- case ver.kind == sdkSystem:
- return javaSystem, false
- case name == "android_test_stubs_current":
- return javaSystem, true
- case ver.kind == sdkTest:
- return javaPlatform, false
- case name == "android_stubs_current":
+ case "android_stubs_current":
return javaSdk, true
- case ver.kind == sdkPublic:
- return javaSdk, false
- case name == "android_module_lib_stubs_current":
+ case "android_system_stubs_current":
+ return javaSystem, true
+ case "android_module_lib_stubs_current":
return javaModule, true
- case ver.kind == sdkModule:
- return javaModule, false
- case name == "android_system_server_stubs_current":
+ case "android_system_server_stubs_current":
return javaSystemServer, true
- case ver.kind == sdkSystemServer:
- return javaSystemServer, false
- case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
- return javaPlatform, false
- case !ver.valid():
- panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
- default:
- return javaSdk, false
+ case "android_test_stubs_current":
+ return javaSystem, true
}
+
+ if stub, linkType := moduleStubLinkType(name); stub {
+ return linkType, true
+ }
+
+ ver := m.sdkVersion()
+ switch ver.kind {
+ case sdkCore:
+ return javaCore, false
+ case sdkSystem:
+ return javaSystem, false
+ case sdkPublic:
+ return javaSdk, false
+ case sdkModule:
+ return javaModule, false
+ case sdkSystemServer:
+ return javaSystemServer, false
+ case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
+ return javaPlatform, false
+ }
+
+ if !ver.valid() {
+ panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
+ }
+ return javaSdk, false
}
func checkLinkType(ctx android.ModuleContext, from *Module, to linkTypeContext, tag dependencyTag) {
@@ -906,6 +945,12 @@
}
}
+ // 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 +970,7 @@
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 +1079,10 @@
}
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 +1462,19 @@
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 +1587,7 @@
// 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 +1595,7 @@
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
@@ -1703,7 +1745,7 @@
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJar() android.Path {
+func (j *Module) DexJarBuildPath() android.Path {
return j.dexJarFile
}
@@ -1754,6 +1796,7 @@
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 +1812,7 @@
}
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 +1846,17 @@
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 +1884,16 @@
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 +1901,7 @@
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
@@ -1906,7 +1962,7 @@
type librarySdkMemberProperties struct {
android.SdkMemberPropertiesBase
- JarToExport android.Path
+ JarToExport android.Path `android:"arch_variant"`
AidlIncludeDirs android.Paths
}
@@ -1979,6 +2035,8 @@
&module.Module.protoProperties,
&module.libraryProperties)
+ module.initModuleAndImport(&module.ModuleBase)
+
android.InitApexModule(module)
android.InitSdkAwareModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
@@ -2033,6 +2091,10 @@
// 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 +2449,9 @@
prebuilt android.Prebuilt
android.SdkBase
+ // Functionality common to Module and Import.
+ embeddableInModuleAndImport
+
properties ImportProperties
combinedClasspathFile android.Path
@@ -2444,6 +2509,12 @@
}
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)
@@ -2500,7 +2571,7 @@
return android.Paths{j.combinedClasspathFile}
}
-func (j *Import) DexJar() android.Path {
+func (j *Import) DexJarBuildPath() android.Path {
return nil
}
@@ -2521,11 +2592,7 @@
}
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 +2633,8 @@
module.AddProperties(&module.properties)
+ module.initModuleAndImport(&module.ModuleBase)
+
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
@@ -2628,6 +2697,10 @@
return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
}
+func (a *DexImport) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
func (j *DexImport) IsInstallable() bool {
return true
}
@@ -2682,10 +2755,10 @@
j.maybeStrippedDexJarFile = dexOutputFile
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- ctx.ModuleName()+".jar", dexOutputFile)
+ j.Stem()+".jar", dexOutputFile)
}
-func (j *DexImport) DexJar() android.Path {
+func (j *DexImport) DexJarBuildPath() android.Path {
return j.dexJarFile
}
@@ -2764,6 +2837,7 @@
&ImportProperties{},
&AARImportProperties{},
&sdkLibraryProperties{},
+ &commonToSdkLibraryAndImportProperties{},
&DexImportProperties{},
&android.ApexProperties{},
&RuntimeResourceOverlayProperties{},
diff --git a/java/java_test.go b/java/java_test.go
index e8a1a7c..8ea34d9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -19,6 +19,8 @@
"os"
"path/filepath"
"reflect"
+ "regexp"
+ "sort"
"strconv"
"strings"
"testing"
@@ -575,6 +577,7 @@
},
test: {
jars: ["c.jar"],
+ stub_srcs: ["c.java"],
},
}
`)
@@ -1035,7 +1038,7 @@
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 @@
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 @@
// 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,243 @@
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 {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ // Explicitly disable public to test the check that ensures the set of enabled
+ // scopes is consistent.
+ public: {
+ enabled: false,
+ },
+ system: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
+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 49e3de3..9f43887 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -72,6 +72,7 @@
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 03bc76b..999c72f 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 @@
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 @@
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 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 @@
if _, ok := mctx.Module().(*prebuiltApis); ok {
prebuiltApiFiles(mctx)
prebuiltSdkStubs(mctx)
+ prebuiltSdkSystemModules(mctx)
}
}
@@ -191,7 +218,9 @@
// 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 690451c..2a08f32 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -35,6 +35,7 @@
var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey")
var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
+var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
type sdkContext interface {
@@ -252,6 +253,20 @@
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 +385,16 @@
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,
}
}
@@ -427,7 +448,7 @@
return toModule([]string{"core.current.stubs"}, "", nil)
case sdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
case sdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
@@ -486,6 +507,7 @@
}
createSdkFrameworkAidl(ctx)
+ createNonUpdatableFrameworkAidl(ctx)
createAPIFingerprint(ctx)
}
@@ -497,6 +519,31 @@
"android_system_stubs_current",
}
+ combinedAidl := sdkFrameworkAidlPath(ctx)
+ tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+
+ rule := createFrameworkAidl(stubsModules, tempPath, ctx)
+
+ commitChangeForRestat(rule, tempPath, combinedAidl)
+
+ rule.Build(pctx, ctx, "framework_aidl", "generate framework.aidl")
+}
+
+// Creates a version of framework.aidl for the non-updatable part of the platform.
+func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
+ stubsModules := []string{"android_module_lib_stubs_current"}
+
+ combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
+ tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+
+ rule := createFrameworkAidl(stubsModules, tempPath, ctx)
+
+ commitChangeForRestat(rule, tempPath, combinedAidl)
+
+ rule.Build(pctx, ctx, "framework_non_updatable_aidl", "generate framework_non_updatable.aidl")
+}
+
+func createFrameworkAidl(stubsModules []string, path android.OutputPath, ctx android.SingletonContext) *android.RuleBuilder {
stubsJars := make([]android.Paths, len(stubsModules))
ctx.VisitAllModules(func(module android.Module) {
@@ -516,8 +563,7 @@
if ctx.Config().AllowMissingDependencies() {
missingDeps = append(missingDeps, stubsModules[i])
} else {
- ctx.Errorf("failed to find dex jar path for module %q",
- stubsModules[i])
+ ctx.Errorf("failed to find dex jar path for module %q", stubsModules[i])
}
}
}
@@ -541,20 +587,15 @@
}
}
- combinedAidl := sdkFrameworkAidlPath(ctx)
- tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
-
rule.Command().
- Text("rm -f").Output(tempPath)
+ Text("rm -f").Output(path)
rule.Command().
Text("cat").
Inputs(aidls).
Text("| sort -u >").
- Output(tempPath)
+ Output(path)
- commitChangeForRestat(rule, tempPath, combinedAidl)
-
- rule.Build(pctx, ctx, "framework_aidl", "generate framework.aidl")
+ return rule
}
func sdkFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
@@ -563,6 +604,12 @@
}).(android.OutputPath)
}
+func nonUpdatableFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
+ return ctx.Config().Once(nonUpdatableFrameworkAidlPathKey, func() interface{} {
+ return android.PathForOutput(ctx, "framework_non_updatable.aidl")
+ }).(android.OutputPath)
+}
+
// Create api_fingerprint.txt
func createAPIFingerprint(ctx android.SingletonContext) {
out := ApiFingerprintPath(ctx)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 4d480ee..de5ee03 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -19,6 +19,7 @@
"path"
"path/filepath"
"reflect"
+ "regexp"
"sort"
"strings"
"sync"
@@ -30,12 +31,8 @@
)
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` +
@@ -60,6 +57,17 @@
blueprint.BaseDependencyTag
name string
apiScope *apiScope
+
+ // Function for extracting appropriate path information from the dependency.
+ depInfoExtractor func(paths *scopePaths, dep android.Module) error
+}
+
+// Extract tag specific information from the dependency.
+func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) {
+ err := tag.depInfoExtractor(paths, dep)
+ if err != nil {
+ ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error())
+ }
}
// Provides information about an api scope, e.g. public, system, test.
@@ -70,15 +78,36 @@
// The api scope that this scope extends.
extends *apiScope
+ // The legacy enabled status for a specific scope can be dependent on other
+ // properties that have been specified on the library so it is provided by
+ // a function that can determine the status by examining those properties.
+ legacyEnabledStatus func(module *SdkLibrary) bool
+
+ // The default enabled status for non-legacy behavior, which is triggered by
+ // explicitly enabling at least one api scope.
+ defaultEnabledStatus bool
+
+ // Gets a pointer to the scope specific properties.
+ scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties
+
// 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
+ // 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
+
// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
apiFilePrefix string
@@ -94,30 +123,90 @@
// 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
}
// Initialize a scope, creating and adding appropriate dependency tags
func initApiScope(scope *apiScope) *apiScope {
- scope.fieldName = proptools.FieldNameForProperty(scope.name)
+ name := scope.name
+ scopeByName[name] = scope
+ allScopeNames = append(allScopeNames, name)
+ scope.propertyName = strings.ReplaceAll(name, "-", "_")
+ scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
scope.stubsTag = scopeDependencyTag{
- name: scope.name + "-stubs",
- apiScope: scope,
+ name: name + "-stubs",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
+ }
+ scope.stubsSourceTag = scopeDependencyTag{
+ name: name + "-stubs-source",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep,
}
scope.apiFileTag = scopeDependencyTag{
- name: scope.name + "-api",
- apiScope: scope,
+ 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) docsModuleName(baseName string) string {
- return baseName + sdkStubsSourceSuffix + scope.moduleSuffix
+func (scope *apiScope) stubsSourceModuleName(baseName string) string {
+ return baseName + ".stubs.source" + scope.moduleSuffix
+}
+
+func (scope *apiScope) apiModuleName(baseName string) string {
+ return baseName + ".api" + scope.moduleSuffix
+}
+
+func (scope *apiScope) String() string {
+ return scope.name
}
type apiScopes []*apiScope
@@ -131,31 +220,71 @@
}
var (
+ scopeByName = make(map[string]*apiScope)
+ allScopeNames []string
apiScopePublic = initApiScope(&apiScope{
- name: "public",
+ name: "public",
+
+ // Public scope is enabled by default for both legacy and non-legacy modes.
+ legacyEnabledStatus: func(module *SdkLibrary) bool {
+ return true
+ },
+ defaultEnabledStatus: true,
+
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.Public
+ },
sdkVersion: "current",
})
apiScopeSystem = initApiScope(&apiScope{
- name: "system",
- extends: apiScopePublic,
+ name: "system",
+ extends: apiScopePublic,
+ legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.System
+ },
apiFilePrefix: "system-",
- moduleSuffix: sdkSystemApiSuffix,
+ moduleSuffix: ".system",
sdkVersion: "system_current",
- droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"},
+ droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"},
})
apiScopeTest = initApiScope(&apiScope{
- name: "test",
- extends: apiScopePublic,
+ name: "test",
+ extends: apiScopePublic,
+ legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ 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",
+ extends: apiScopeSystem,
+ // Module_lib scope is disabled by default in legacy mode.
+ //
+ // Enabling this would break existing usages.
+ legacyEnabledStatus: func(module *SdkLibrary) bool {
+ return false
+ },
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.Module_lib
+ },
+ apiFilePrefix: "module-lib-",
+ moduleSuffix: ".module_lib",
+ sdkVersion: "module_current",
+ droidstubsArgs: []string{
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)",
+ },
+ })
allApiScopes = apiScopes{
apiScopePublic,
apiScopeSystem,
apiScopeTest,
+ apiScopeModuleLib,
}
)
@@ -190,7 +319,47 @@
ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
}
+// Properties associated with each api scope.
+type ApiScopeProperties struct {
+ // Indicates whether the api surface is generated.
+ //
+ // If this is set for any scope then all scopes must explicitly specify if they
+ // are enabled. This is to prevent new usages from depending on legacy behavior.
+ //
+ // 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
+
+ // Visibility for stubs source modules. If not specified then defaults to the
+ // visibility property.
+ Stubs_source_visibility []string
+
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
@@ -207,7 +376,10 @@
// 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.
@@ -232,27 +404,296 @@
// don't create dist rules.
No_dist *bool `blueprint:"mutated"`
- // indicates whether system and test apis should be managed.
- Has_system_and_test_apis bool `blueprint:"mutated"`
+ // indicates whether system and test apis should be generated.
+ Generate_system_and_test_apis bool `blueprint:"mutated"`
+
+ // The properties specific to the public api scope
+ //
+ // Unless explicitly specified by using public.enabled the public api scope is
+ // enabled by default in both legacy and non-legacy mode.
+ Public ApiScopeProperties
+
+ // The properties specific to the system api scope
+ //
+ // In legacy mode the system api scope is enabled by default when sdk_version
+ // is set to something other than "none".
+ //
+ // In non-legacy mode the system api scope is disabled by default.
+ System ApiScopeProperties
+
+ // The properties specific to the test api scope
+ //
+ // In legacy mode the test api scope is enabled by default when sdk_version
+ // is set to something other than "none".
+ //
+ // In non-legacy mode the test api scope is disabled by default.
+ Test ApiScopeProperties
+
+ // The properties specific to the module_lib api scope
+ //
+ // Unless explicitly specified by using test.enabled the module_lib api scope is
+ // 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 {
+ if lib, ok := dep.(Dependency); ok {
+ paths.stubsHeaderPath = lib.HeaderJars()
+ paths.stubsImplPath = lib.ImplementationJars()
+ return nil
+ } else {
+ return fmt.Errorf("expected module that implements Dependency, e.g. java_library")
+ }
+}
+
+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) getScopePaths(scope *apiScope) *scopePaths {
+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())
+}
+
+// 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)
}
@@ -265,23 +706,211 @@
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
sdkLibraryProperties sdkLibraryProperties
+ // Map from api scope to the scope specific property structure.
+ scopeToProperties map[*apiScope]*ApiScopeProperties
+
commonToSdkLibraryAndImport
}
var _ Dependency = (*SdkLibrary)(nil)
var _ SdkLibraryDependency = (*SdkLibrary)(nil)
-func (module *SdkLibrary) getActiveApiScopes() apiScopes {
- if module.sdkLibraryProperties.Has_system_and_test_apis {
- return allApiScopes
- } else {
- return apiScopes{apiScopePublic}
+func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
+ return module.sdkLibraryProperties.Generate_system_and_test_apis
+}
+
+func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
+ // Check to see if any scopes have been explicitly enabled. If any have then all
+ // must be.
+ anyScopesExplicitlyEnabled := false
+ for _, scope := range allApiScopes {
+ scopeProperties := module.scopeToProperties[scope]
+ if scopeProperties.Enabled != nil {
+ anyScopesExplicitlyEnabled = true
+ break
+ }
}
+
+ var generatedScopes apiScopes
+ enabledScopes := make(map[*apiScope]struct{})
+ for _, scope := range allApiScopes {
+ scopeProperties := module.scopeToProperties[scope]
+ // If any scopes are explicitly enabled then ignore the legacy enabled status.
+ // This is to ensure that any new usages of this module type do not rely on legacy
+ // behaviour.
+ defaultEnabledStatus := false
+ if anyScopesExplicitlyEnabled {
+ defaultEnabledStatus = scope.defaultEnabledStatus
+ } else {
+ defaultEnabledStatus = scope.legacyEnabledStatus(module)
+ }
+ enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus)
+ if enabled {
+ enabledScopes[scope] = struct{}{}
+ generatedScopes = append(generatedScopes, scope)
+ }
+ }
+
+ // Now check to make sure that any scope that is extended by an enabled scope is also
+ // enabled.
+ for _, scope := range allApiScopes {
+ if _, ok := enabledScopes[scope]; ok {
+ extends := scope.extends
+ if extends != nil {
+ if _, ok := enabledScopes[extends]; !ok {
+ ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends)
+ }
+ }
+ }
+ }
+
+ return generatedScopes
}
var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
@@ -293,26 +922,51 @@
return false
}
+var implLibraryTag = dependencyTag{name: "impl-library"}
+
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
- for _, apiScope := range module.getActiveApiScopes() {
+ 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 api file
- ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(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())
- module.Library.deps(ctx)
+ 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)
+ }
+}
+
+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)
}
@@ -320,33 +974,22 @@
// When this java_sdk_library is depended upon from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
ctx.VisitDirectDeps(func(to android.Module) {
- otherName := ctx.OtherModuleName(to)
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()
- scopePaths.stubsImplPath = lib.ImplementationJars()
- }
- }
- if doc, ok := to.(ApiStubsProvider); ok {
- if scopeTag, ok := tag.(scopeDependencyTag); ok {
- apiScope := scopeTag.apiScope
- scopePaths := module.getScopePaths(apiScope)
- scopePaths.currentApiFilePath = doc.ApiFilePath()
- scopePaths.removedApiFilePath = doc.RemovedApiFilePath()
- scopePaths.stubsSrcJar = doc.StubsSrcJar()
- } else {
- ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
- }
+ // 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 *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
- if proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ if !module.requiresRuntimeImplementationLibrary() {
return nil
}
entriesList := module.Library.AndroidMkEntries()
@@ -355,19 +998,9 @@
return entriesList
}
-// Module name of the stubs library
-func (module *SdkLibrary) stubsName(apiScope *apiScope) string {
- return apiScope.stubsModuleName(module.BaseModuleName())
-}
-
-// Module name of the docs
-func (module *SdkLibrary) docsName(apiScope *apiScope) string {
- return apiScope.docsModuleName(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
@@ -387,7 +1020,12 @@
}
// Get the sdk version for use when compiling the stubs library.
-func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, 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.
@@ -406,23 +1044,41 @@
return ":" + module.BaseModuleName() + "-removed.api." + apiScope.name + ".latest"
}
-// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) {
+// Creates the implementation java library
+func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
props := struct {
- Name *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
+ }{
+ 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
+ Compile_dex *bool
+ Java_version *string
+ Product_variables struct {
Pdk struct {
Enabled *bool
}
@@ -439,32 +1095,31 @@
}
}{}
- 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.
+ visibility := module.sdkLibraryProperties.Stubs_library_visibility
+ props.Visibility = visibility
+
// sources are generated from the droiddoc
- props.Srcs = []string{":" + module.docsName(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
+ // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
+ // interop with older developer tools that don't support 1.9.
+ props.Java_version = proptools.StringPtr("1.8")
+ 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"}
@@ -473,14 +1128,15 @@
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
-func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) {
+// files and also updates and checks the API specification files.
+func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, createStubSources, createApi bool, scopeSpecificDroidstubsArgs []string) {
props := struct {
Name *string
+ Visibility []string
Srcs []string
Installable *bool
Sdk_version *string
@@ -491,10 +1147,17 @@
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
@@ -513,18 +1176,24 @@
// * system_modules
// * libs (static_libs/libs)
- props.Name = proptools.StringPtr(module.docsName(apiScope))
- 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.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.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
@@ -551,38 +1220,64 @@
}
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)
+ 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)
+ // 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 !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)
- // 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"))
+ 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"))
+ }
}
mctx.CreateModule(DroidstubsFactory, &props)
@@ -597,31 +1292,17 @@
}
// Creates the xml file that publicizes the runtime library
-func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
+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)
}
@@ -652,41 +1333,50 @@
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
@@ -718,8 +1408,13 @@
// For a java_sdk_library module, create internal modules for stubs, docs,
// runtime libs and xml file. If requested, the stubs and docs are created twice
// once for public API level and once for system API level
-func (module *SdkLibrary) CreateInternalModules(mctx android.LoadHookContext) {
- if len(module.Library.Module.properties.Srcs) == 0 {
+func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
+ // If the module has been disabled then don't create any child modules.
+ if !module.Enabled() {
+ return
+ }
+
+ if len(module.properties.Srcs) == 0 {
mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
return
}
@@ -729,15 +1424,15 @@
// also assume it does not contribute to the dist build.
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
hasSystemAndTestApis := sdkDep.hasStandardLibs()
- module.sdkLibraryProperties.Has_system_and_test_apis = hasSystemAndTestApis
+ module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
missing_current_api := false
- activeScopes := module.getActiveApiScopes()
+ generatedScopes := module.getGeneratedApiScopes(mctx)
apiDir := module.getApiDir()
- for _, scope := range activeScopes {
+ for _, scope := range generatedScopes {
for _, api := range []string{"current.txt", "removed.txt"} {
path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api)
p := android.ExistentPathForSource(mctx, path)
@@ -760,18 +1455,45 @@
"You can update them by:\n"+
"%s %q %s && m update-api",
script, filepath.Join(mctx.ModuleDir(), apiDir),
- strings.Join(activeScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
+ strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
return
}
- for _, scope := range activeScopes {
+ 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.createStubsSources(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())
@@ -784,14 +1506,93 @@
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)
+
+func moduleStubLinkType(name string) (stub bool, ret linkType) {
+ // This suffix-based approach is fragile and could potentially mis-trigger.
+ // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
+ if strings.HasSuffix(name, ".stubs.public") || strings.HasSuffix(name, "-stubs-publicapi") {
+ return true, javaSdk
+ }
+ if strings.HasSuffix(name, ".stubs.system") || strings.HasSuffix(name, "-stubs-systemapi") {
+ return true, javaSystem
+ }
+ if strings.HasSuffix(name, ".stubs.module_lib") || strings.HasSuffix(name, "-stubs-module_libs_api") {
+ return true, javaModule
+ }
+ if strings.HasSuffix(name, ".stubs.test") {
+ return true, javaSystem
+ }
+ return false, javaPlatform
}
// java_sdk_library is a special Java library that provides optional platform APIs to apps.
@@ -801,10 +1602,43 @@
// 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)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.CreateInternalModules(ctx) })
+
+ // Initialize the map from scope to scope specific properties.
+ scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
+ for _, scope := range allApiScopes {
+ scopeToProperties[scope] = scope.scopeSpecificProperties(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) {
+ // 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
}
@@ -821,14 +1655,14 @@
// List of shared java libs that this module has dependencies to
Libs []string
- // The stub sources.
+ // The stubs source.
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 {
@@ -900,12 +1734,19 @@
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)
- android.AddLoadHook(module, func(mctx android.LoadHookContext) { module.createInternalModules(mctx) })
+ module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
+ if module.initCommonAfterDefaultsApplied(mctx) {
+ module.createInternalModules(mctx)
+ }
+ })
return module
}
@@ -917,7 +1758,7 @@
return module.prebuilt.Name(module.ModuleBase.Name())
}
-func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookContext) {
+func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
@@ -931,7 +1772,9 @@
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())
@@ -940,50 +1783,40 @@
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
-func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.LoadHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+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.LoadHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+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.docsModuleName(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) {
@@ -993,46 +1826,49 @@
}
// 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)
}
})
+
+ // Populate the scope paths with information from the properties.
+ for apiScope, scopeProperties := range module.scopeProperties {
+ if len(scopeProperties.Jars) == 0 {
+ continue
+ }
+
+ paths := module.getScopePathsCreateIfNeeded(apiScope)
+ paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api)
+ paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api)
+ }
}
-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)
- }
-
- var apiScope *apiScope
- switch sdkVersion.kind {
- case sdkSystem:
- apiScope = apiScopeSystem
- case sdkTest:
- apiScope = apiScopeTest
- default:
- apiScope = apiScopePublic
- }
-
- 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
@@ -1187,6 +2023,13 @@
// 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 {
@@ -1202,26 +2045,39 @@
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)
@@ -1247,7 +2103,7 @@
if properties.RemovedApiFile != nil {
removedApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"-removed.txt")
- ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, removedApiSnapshotPath)
+ ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 088db9e..e5d322c 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -83,6 +83,16 @@
},
{
+ 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 @@
},
{
+ 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"},
@@ -136,9 +156,9 @@
{
name: "nostdlib system_modules",
- properties: `sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules"`,
- system: "core-platform-api-stubs-system-modules",
- bootclasspath: []string{"core-platform-api-stubs-system-modules-lib"},
+ properties: `sdk_version: "none", system_modules: "legacy-core-platform-api-stubs-system-modules"`,
+ system: "legacy-core-platform-api-stubs-system-modules",
+ bootclasspath: []string{"legacy-core-platform-api-stubs-system-modules-lib"},
java8classpath: []string{},
},
{
@@ -176,12 +196,24 @@
},
{
+ 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 @@
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",
@@ -217,7 +252,7 @@
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
system: "core-current-stubs-system-modules",
java9classpath: []string{"android_module_lib_stubs_current"},
- aidl: "-p" + buildDir + "/framework.aidl",
+ aidl: "-p" + buildDir + "/framework_non_updatable.aidl",
},
{
name: "system_server_current",
@@ -292,12 +327,16 @@
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 6929bb7..f993f56 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -55,36 +55,54 @@
"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 @@
"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 @@
"cert/new_cert.x509.pem": nil,
"cert/new_cert.pk8": nil,
+ "lineage.bin": nil,
"testdata/data": nil,
@@ -152,7 +173,8 @@
"android_module_lib_stubs_current",
"android_system_server_stubs_current",
"core.current.stubs",
- "core.platform.api.stubs",
+ "legacy.core.platform.api.stubs",
+ "stable.core.platform.api.stubs",
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -165,7 +187,7 @@
name: "%s",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
}
`, extra)
}
@@ -175,7 +197,7 @@
name: "framework",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
aidl: {
export_include_dirs: ["framework/aidl"],
},
@@ -190,7 +212,7 @@
name: "android.hidl.base-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -198,7 +220,7 @@
name: "android.hidl.manager-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -206,14 +228,30 @@
name: "org.apache.http.legacy",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
+ installable: true,
+ }
+
+ java_library {
+ name: "android.test.base",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
+ installable: true,
+ }
+
+ java_library {
+ name: "android.test.mock",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
`
systemModules := []string{
"core-current-stubs-system-modules",
- "core-platform-api-stubs-system-modules",
+ "legacy-core-platform-api-stubs-system-modules",
}
for _, extra := range systemModules {
diff --git a/phony/Android.bp b/phony/Android.bp
new file mode 100644
index 0000000..2c423ef
--- /dev/null
+++ b/phony/Android.bp
@@ -0,0 +1,12 @@
+bootstrap_go_package {
+ name: "soong-phony",
+ pkgPath: "android/soong/phony",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "phony.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/python/Android.bp b/python/Android.bp
new file mode 100644
index 0000000..ffd03fe
--- /dev/null
+++ b/python/Android.bp
@@ -0,0 +1,24 @@
+bootstrap_go_package {
+ name: "soong-python",
+ pkgPath: "android/soong/python",
+ deps: [
+ "blueprint",
+ "soong-android",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "androidmk.go",
+ "binary.go",
+ "builder.go",
+ "defaults.go",
+ "installer.go",
+ "library.go",
+ "proto.go",
+ "python.go",
+ "test.go",
+ ],
+ testSrcs: [
+ "python_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/remoteexec/Android.bp b/remoteexec/Android.bp
new file mode 100644
index 0000000..fc2c0e3
--- /dev/null
+++ b/remoteexec/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+ name: "soong-remoteexec",
+ pkgPath: "android/soong/remoteexec",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "remoteexec.go",
+ ],
+ testSrcs: [
+ "remoteexec_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index 99e29dc..d6e2c0a 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -75,6 +75,9 @@
// 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 @@
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 @@
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 @@
}
// 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 @@
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/Android.bp b/rust/Android.bp
new file mode 100644
index 0000000..684db0b
--- /dev/null
+++ b/rust/Android.bp
@@ -0,0 +1,32 @@
+bootstrap_go_package {
+ name: "soong-rust",
+ pkgPath: "android/soong/rust",
+ deps: [
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-rust-config",
+ ],
+ srcs: [
+ "androidmk.go",
+ "compiler.go",
+ "coverage.go",
+ "binary.go",
+ "builder.go",
+ "library.go",
+ "prebuilt.go",
+ "proc_macro.go",
+ "rust.go",
+ "test.go",
+ "testing.go",
+ ],
+ testSrcs: [
+ "binary_test.go",
+ "compiler_test.go",
+ "coverage_test.go",
+ "library_test.go",
+ "rust_test.go",
+ "test_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
new file mode 100644
index 0000000..1a10312
--- /dev/null
+++ b/rust/config/Android.bp
@@ -0,0 +1,19 @@
+bootstrap_go_package {
+ name: "soong-rust-config",
+ pkgPath: "android/soong/rust/config",
+ deps: [
+ "soong-android",
+ "soong-cc-config",
+ ],
+ srcs: [
+ "arm_device.go",
+ "arm64_device.go",
+ "global.go",
+ "toolchain.go",
+ "whitelist.go",
+ "x86_darwin_host.go",
+ "x86_linux_host.go",
+ "x86_device.go",
+ "x86_64_device.go",
+ ],
+}
diff --git a/rust/config/x86_darwin_host.go b/rust/config/x86_darwin_host.go
index 7cfc59c..4c16693 100644
--- a/rust/config/x86_darwin_host.go
+++ b/rust/config/x86_darwin_host.go
@@ -62,7 +62,11 @@
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/rust/library.go b/rust/library.go
index 8aa033c..2e51266 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -329,12 +329,21 @@
return deps
}
+
+func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
+ return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+}
+
func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.baseModuleName())
flags = library.baseCompiler.compilerFlags(ctx, flags)
if library.shared() || library.static() {
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
}
+ if library.shared() {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ }
+
return flags
}
@@ -371,7 +380,7 @@
outputs := TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
library.coverageFile = outputs.coverageFile
} else if library.shared() {
- fileName := library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+ fileName := library.sharedLibFilename(ctx)
outputFile = android.PathForModuleOut(ctx, fileName)
outputs := TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
diff --git a/rust/library_test.go b/rust/library_test.go
index 9f9f374..37dd541 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -114,3 +114,17 @@
}`)
}
+
+func TestSharedLibraryFlags(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_host {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so")
+ if !strings.Contains(libfooShared.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
+ t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", libfooShared.Args["linkFlags"])
+ }
+}
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 770adc9..f836ea9 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -19,6 +19,7 @@
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 f982e82..d7e602f 100755
--- a/scripts/package-check.sh
+++ b/scripts/package-check.sh
@@ -52,6 +52,7 @@
# 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 @@
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/Android.bp b/sdk/Android.bp
new file mode 100644
index 0000000..cb93351
--- /dev/null
+++ b/sdk/Android.bp
@@ -0,0 +1,27 @@
+bootstrap_go_package {
+ name: "soong-sdk",
+ pkgPath: "android/soong/sdk",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-apex",
+ "soong-cc",
+ "soong-java",
+ ],
+ srcs: [
+ "bp.go",
+ "exports.go",
+ "sdk.go",
+ "update.go",
+ ],
+ testSrcs: [
+ "bp_test.go",
+ "cc_sdk_test.go",
+ "exports_test.go",
+ "java_sdk_test.go",
+ "sdk_test.go",
+ "testing.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index f89f38c..c630c25 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -57,7 +57,7 @@
contents := &generatedContents{}
outputPropertySet(contents, set)
- helper.AssertTrimmedStringEquals("removing property failed", "name: \"name\",\\n", contents.content.String())
+ helper.AssertTrimmedStringEquals("removing property failed", "name: \"name\",\n", contents.content.String())
}
func TestTransformRemovePropertySet(t *testing.T) {
@@ -72,5 +72,5 @@
contents := &generatedContents{}
outputPropertySet(contents, set)
- helper.AssertTrimmedStringEquals("removing property set failed", "name: \"name\",\\n", contents.content.String())
+ helper.AssertTrimmedStringEquals("removing property set failed", "name: \"name\",\n", contents.content.String())
}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 733f7ac..4a09081 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -401,7 +401,6 @@
"Test.cpp",
],
compile_multilib: "both",
- stl: "none",
}
`)
@@ -494,6 +493,7 @@
device_supported: false,
host_supported: true,
installable: false,
+ stl: "none",
target: {
linux_glibc: {
compile_multilib: "both",
@@ -518,6 +518,7 @@
prefer: false,
device_supported: false,
host_supported: true,
+ stl: "none",
target: {
linux_glibc: {
compile_multilib: "both",
@@ -557,6 +558,90 @@
)
}
+// 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 {
@@ -1805,3 +1890,89 @@
}
`))
}
+
+func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ host_supported: true,
+ native_shared_libs: ["stubslib"],
+ }
+
+ cc_library {
+ name: "internaldep",
+ host_supported: true,
+ }
+
+ cc_library {
+ name: "stubslib",
+ host_supported: true,
+ shared_libs: ["internaldep"],
+ stubs: {
+ symbol_file: "some/where/stubslib.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_stubslib@current",
+ sdk_member_name: "stubslib",
+ host_supported: true,
+ installable: false,
+ stubs: {
+ versions: ["3"],
+ },
+ target: {
+ android_arm64: {
+ srcs: ["android/arm64/lib/stubslib.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/stubslib.so"],
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
+ },
+ linux_glibc_x86: {
+ srcs: ["linux_glibc/x86/lib/stubslib.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "stubslib",
+ prefer: false,
+ host_supported: true,
+ stubs: {
+ versions: ["3"],
+ },
+ target: {
+ android_arm64: {
+ srcs: ["android/arm64/lib/stubslib.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/stubslib.so"],
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
+ },
+ linux_glibc_x86: {
+ srcs: ["linux_glibc/x86/lib/stubslib.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ host_supported: true,
+ native_shared_libs: ["mysdk_stubslib@current"],
+}
+`))
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 788d016..56706c7 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -32,6 +32,8 @@
"api/system-removed.txt": nil,
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
+ "api/module-lib-current.txt": nil,
+ "api/module-lib-removed.txt": nil,
"build/soong/scripts/gen-java-current-api-files.sh": nil,
}
@@ -41,10 +43,10 @@
name: "core-current-stubs-system-modules",
}
java_system_modules_import {
- name: "core-platform-api-stubs-system-modules",
+ name: "legacy-core-platform-api-stubs-system-modules",
}
java_import {
- name: "core.platform.api.stubs",
+ name: "legacy.core.platform.api.stubs",
}
java_import {
name: "android_stubs_current",
@@ -56,6 +58,9 @@
name: "android_test_stubs_current",
}
java_import {
+ name: "android_module_lib_stubs_current",
+}
+java_import {
name: "core-lambda-stubs",
sdk_version: "none",
}
@@ -984,6 +989,9 @@
apex_available: ["//apex_available:anyapex"],
srcs: ["Test.java"],
sdk_version: "current",
+ shared_library: false,
+ stubs_library_visibility: ["//other"],
+ stubs_source_visibility: ["//another"],
}
`)
@@ -995,6 +1003,7 @@
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"],
@@ -1022,6 +1031,7 @@
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"],
@@ -1053,13 +1063,13 @@
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
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
.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.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
.intermediates/myjavalib.stubs.test/android_common/javac/myjavalib.stubs.test.jar -> sdk_library/test/myjavalib-stubs.jar
.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
-.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_removed.txt -> sdk_library/test/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1067,3 +1077,392 @@
".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip"),
)
}
+
+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_removed.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_removed.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",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ system: {
+ 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"],
+ 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",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ sdk_version: "system_current",
+ },
+}
+
+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"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ sdk_version: "system_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_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.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_removed.txt -> sdk_library/system/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",
+ ),
+ )
+}
+
+func TestSnapshotWithJavaSdkLibrary_ModuleLib(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",
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ 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"],
+ 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",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ 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",
+ sdk_version: "module_current",
+ },
+}
+
+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"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ 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",
+ 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_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.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_removed.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.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_removed.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",
+ ),
+ )
+}
+
+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_removed.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 095f836..56be741 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -103,6 +103,7 @@
"myjavalib",
"mypublicjavalib",
"mydefaultedjavalib",
+ "myprivatejavalib",
],
}
@@ -140,6 +141,14 @@
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 @@
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 {
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",
],
}
`))
@@ -226,8 +262,8 @@
}
type EmbeddedPropertiesStruct struct {
- S_Embedded_Common string
- S_Embedded_Different string
+ S_Embedded_Common string `android:"arch_variant"`
+ S_Embedded_Different string `android:"arch_variant"`
}
type testPropertiesStruct struct {
@@ -235,11 +271,11 @@
private string
Public_Kept string `sdk:"keep"`
S_Common string
- S_Different string
+ S_Different string `android:"arch_variant"`
A_Common []string
- A_Different []string
+ A_Different []string `android:"arch_variant"`
F_Common *bool
- F_Different *bool
+ F_Different *bool `android:"arch_variant"`
EmbeddedPropertiesStruct
}
@@ -289,9 +325,12 @@
}
extractor := newCommonValueExtractor(common)
- extractor.extractCommonProperties(common, structs)
h := TestHelper{t}
+
+ err := extractor.extractCommonProperties(common, structs)
+ h.AssertDeepEquals("unexpected error", nil, err)
+
h.AssertDeepEquals("common properties not correct",
&testPropertiesStruct{
name: "common",
@@ -346,3 +385,26 @@
},
structs[1])
}
+
+func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) {
+ common := &testPropertiesStruct{name: "common"}
+ structs := []propertiesContainer{
+ &testPropertiesStruct{
+ name: "struct-0",
+ S_Common: "should-be-but-is-not-common0",
+ },
+ &testPropertiesStruct{
+ name: "struct-1",
+ S_Common: "should-be-but-is-not-common1",
+ },
+ }
+
+ extractor := newCommonValueExtractor(common)
+
+ h := TestHelper{t}
+
+ err := extractor.extractCommonProperties(common, structs)
+ h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
+ "struct-0" has value "should-be-but-is-not-common0"
+ "struct-1" has value "should-be-but-is-not-common1"`, err)
+}
diff --git a/sdk/testing.go b/sdk/testing.go
index 14a397c..4361754 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -207,7 +207,7 @@
// e.g. find the src/dest pairs from each cp command, the various zip files
// generated, etc.
func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
- androidBpContents := strings.NewReplacer("\\n", "\n").Replace(sdk.GetAndroidBpContentsForTests())
+ androidBpContents := sdk.GetAndroidBpContentsForTests()
info := &snapshotBuildInfo{
r: r,
diff --git a/sdk/update.go b/sdk/update.go
index 03a5c03..1ba5806 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -87,18 +87,23 @@
}
func (gc *generatedContents) Printfln(format string, args ...interface{}) {
- // ninja consumes newline characters in rspfile_content. Prevent it by
- // escaping the backslash in the newline character. The extra backslash
- // is removed when the rspfile is written to the actual script file
- fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format+"\\n", args...)
+ fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format+"\n", args...)
}
func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
rb := android.NewRuleBuilder()
- // convert \\n to \n
+
+ content := gf.content.String()
+
+ // ninja consumes newline characters in rspfile_content. Prevent it by
+ // escaping the backslash in the newline character. The extra backslash
+ // is removed when the rspfile is written to the actual script file
+ content = strings.ReplaceAll(content, "\n", "\\n")
+
rb.Command().
Implicits(implicits).
- Text("echo").Text(proptools.ShellEscape(gf.content.String())).
+ Text("echo").Text(proptools.ShellEscape(content)).
+ // convert \\n to \n
Text("| sed 's/\\\\n/\\n/g' >").Output(gf.path)
rb.Command().
Text("chmod a+x").Output(gf.path)
@@ -345,6 +350,9 @@
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
@@ -389,6 +397,36 @@
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 {
@@ -982,6 +1020,13 @@
}
}
+func (osInfo *osTypeSpecificInfo) isHostVariant() bool {
+ osClass := osInfo.osType.Class
+ return osClass == android.Host || osClass == android.HostCross
+}
+
+var _ isHostVariant = (*osTypeSpecificInfo)(nil)
+
func (osInfo *osTypeSpecificInfo) String() string {
return fmt.Sprintf("OsType{%s}", osInfo.osType)
}
@@ -1215,16 +1260,34 @@
// struct (or one of its embedded structs).
type fieldAccessorFunc func(structValue reflect.Value) reflect.Value
+// Checks the metadata to determine whether the property should be ignored for the
+// purposes of common value extraction or not.
+type extractorMetadataPredicate func(metadata propertiesContainer) bool
+
+// Indicates whether optimizable properties are provided by a host variant or
+// not.
+type isHostVariant interface {
+ isHostVariant() bool
+}
+
// A property that can be optimized by the commonValueExtractor.
type extractorProperty struct {
// The name of the field for this property.
name string
+ // Filter that can use metadata associated with the properties being optimized
+ // to determine whether the field should be ignored during common value
+ // optimization.
+ filter extractorMetadataPredicate
+
// Retrieves the value on which common value optimization will be performed.
getter fieldAccessorFunc
// The empty value for the field.
emptyValue reflect.Value
+
+ // True if the property can support arch variants false otherwise.
+ archVariant bool
}
func (p extractorProperty) String() string {
@@ -1270,6 +1333,20 @@
continue
}
+ var filter extractorMetadataPredicate
+
+ // Add a filter
+ if proptools.HasTag(field, "sdk", "ignored-on-host") {
+ filter = func(metadata propertiesContainer) bool {
+ if m, ok := metadata.(isHostVariant); ok {
+ if m.isHostVariant() {
+ return false
+ }
+ }
+ return true
+ }
+ }
+
// Save a copy of the field index for use in the function.
fieldIndex := f
@@ -1301,8 +1378,10 @@
} else {
property := extractorProperty{
name,
+ filter,
fieldGetter,
reflect.Zero(field.Type),
+ proptools.HasTag(field, "android", "arch_variant"),
}
e.properties = append(e.properties, property)
}
@@ -1368,17 +1447,38 @@
for _, property := range e.properties {
fieldGetter := property.getter
+ filter := property.filter
+ if filter == nil {
+ filter = func(metadata propertiesContainer) bool {
+ return true
+ }
+ }
// Check to see if all the structures have the same value for the field. The commonValue
- // is nil on entry to the loop and if it is nil on exit then there is no common value,
- // otherwise it points to the common value.
+ // is nil on entry to the loop and if it is nil on exit then there is no common value or
+ // all the values have been filtered out, otherwise it points to the common value.
var commonValue *reflect.Value
+ // Assume that all the values will be the same.
+ //
+ // While similar to this is not quite the same as commonValue == nil. If all the values
+ // have been filtered out then this will be false but commonValue == nil will be true.
+ valuesDiffer := false
+
for i := 0; i < sliceValue.Len(); i++ {
container := sliceValue.Index(i).Interface().(propertiesContainer)
itemValue := reflect.ValueOf(container.optimizableProperties())
fieldValue := fieldGetter(itemValue)
+ if !filter(container) {
+ expectedValue := property.emptyValue.Interface()
+ actualValue := fieldValue.Interface()
+ if !reflect.DeepEqual(expectedValue, actualValue) {
+ return fmt.Errorf("field %q is supposed to be ignored for %q but is set to %#v instead of %#v", property, container, actualValue, expectedValue)
+ }
+ continue
+ }
+
if commonValue == nil {
// Use the first value as the commonProperties value.
commonValue = &fieldValue
@@ -1387,12 +1487,13 @@
// no value in common so break out.
if !reflect.DeepEqual(fieldValue.Interface(), commonValue.Interface()) {
commonValue = nil
+ valuesDiffer = true
break
}
}
}
- // If the fields all have a common value then store it in the common struct field
+ // If the fields all have common value then store it in the common struct field
// and set the input struct's field to the empty value.
if commonValue != nil {
emptyValue := property.emptyValue
@@ -1404,6 +1505,21 @@
fieldValue.Set(emptyValue)
}
}
+
+ if valuesDiffer && !property.archVariant {
+ // The values differ but the property does not support arch variants so it
+ // is an error.
+ var details strings.Builder
+ for i := 0; i < sliceValue.Len(); i++ {
+ container := sliceValue.Index(i).Interface().(propertiesContainer)
+ itemValue := reflect.ValueOf(container.optimizableProperties())
+ fieldValue := fieldGetter(itemValue)
+
+ _, _ = fmt.Fprintf(&details, "\n %q has value %q", container.String(), fieldValue.Interface())
+ }
+
+ return fmt.Errorf("field %q is not tagged as \"arch_variant\" but has arch specific properties:%s", property.String(), details.String())
+ }
}
return nil
diff --git a/sh/Android.bp b/sh/Android.bp
new file mode 100644
index 0000000..0f40c5f
--- /dev/null
+++ b/sh/Android.bp
@@ -0,0 +1,17 @@
+bootstrap_go_package {
+ name: "soong-sh",
+ pkgPath: "android/soong/sh",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "sh_binary.go",
+ ],
+ testSrcs: [
+ "sh_binary_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
new file mode 100644
index 0000000..9276a62
--- /dev/null
+++ b/sh/sh_binary.go
@@ -0,0 +1,300 @@
+// Copyright 2019 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 sh
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/tradefed"
+)
+
+// sh_binary is for shell scripts (and batch files) that are installed as
+// executable files into .../bin/
+//
+// Do not use them for prebuilt C/C++/etc files. Use cc_prebuilt_binary
+// instead.
+
+var pctx = android.NewPackageContext("android/soong/sh")
+
+func init() {
+ pctx.Import("android/soong/android")
+
+ android.RegisterModuleType("sh_binary", ShBinaryFactory)
+ android.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+ android.RegisterModuleType("sh_test", ShTestFactory)
+ android.RegisterModuleType("sh_test_host", ShTestHostFactory)
+}
+
+type shBinaryProperties struct {
+ // Source file of this prebuilt.
+ Src *string `android:"path,arch_variant"`
+
+ // optional subdirectory under which this file is installed into
+ Sub_dir *string `android:"arch_variant"`
+
+ // optional name for the installed file. If unspecified, name of the module is used as the file name
+ Filename *string `android:"arch_variant"`
+
+ // when set to true, and filename property is not set, the name for the installed file
+ // is the same as the file name of the source file.
+ Filename_from_src *bool `android:"arch_variant"`
+
+ // Whether this module is directly installable to one of the partitions. Default: true.
+ Installable *bool
+
+ // install symlinks to the binary
+ Symlinks []string `android:"arch_variant"`
+}
+
+type TestProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // the name of the test configuration (for example "AndroidTest.xml") that should be
+ // installed with the module.
+ Test_config *string `android:"arch_variant"`
+
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test.
+ Data []string `android:"path,arch_variant"`
+
+ // Add RootTargetPreparer to auto generated test config. This guarantees the test to run
+ // with root permission.
+ Require_root *bool
+
+ // the name of the test configuration template (for example "AndroidTestTemplate.xml") that
+ // should be installed with the module.
+ Test_config_template *string `android:"path,arch_variant"`
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
+}
+
+type ShBinary struct {
+ android.ModuleBase
+
+ properties shBinaryProperties
+
+ sourceFilePath android.Path
+ outputFilePath android.OutputPath
+ installedFile android.InstallPath
+}
+
+var _ android.HostToolProvider = (*ShBinary)(nil)
+
+type ShTest struct {
+ ShBinary
+
+ testProperties TestProperties
+
+ data android.Paths
+ testConfig android.Path
+}
+
+func (s *ShBinary) HostToolPath() android.OptionalPath {
+ return android.OptionalPathForPath(s.installedFile)
+}
+
+func (s *ShBinary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if s.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ }
+}
+
+func (s *ShBinary) OutputFile() android.OutputPath {
+ return s.outputFilePath
+}
+
+func (s *ShBinary) SubDir() string {
+ return proptools.String(s.properties.Sub_dir)
+}
+
+func (s *ShBinary) Installable() bool {
+ return s.properties.Installable == nil || proptools.Bool(s.properties.Installable)
+}
+
+func (s *ShBinary) Symlinks() []string {
+ return s.properties.Symlinks
+}
+
+func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
+ s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
+ filename := proptools.String(s.properties.Filename)
+ filename_from_src := proptools.Bool(s.properties.Filename_from_src)
+ if filename == "" {
+ if filename_from_src {
+ filename = s.sourceFilePath.Base()
+ } else {
+ filename = ctx.ModuleName()
+ }
+ } else if filename_from_src {
+ ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+ return
+ }
+ s.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
+
+ // This ensures that outputFilePath has the correct name for others to
+ // use, as the source file may have a different name.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpExecutable,
+ Output: s.outputFilePath,
+ Input: s.sourceFilePath,
+ })
+}
+
+func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ s.generateAndroidBuildActions(ctx)
+ installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
+ s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
+}
+
+func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "EXECUTABLES",
+ OutputFile: android.OptionalPathForPath(s.outputFilePath),
+ Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ s.customAndroidMkEntries(entries)
+ },
+ },
+ }}
+}
+
+func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
+ entries.SetString("LOCAL_MODULE_SUFFIX", "")
+ entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
+ if len(s.properties.Symlinks) > 0 {
+ entries.SetString("LOCAL_MODULE_SYMLINKS", strings.Join(s.properties.Symlinks, " "))
+ }
+}
+
+func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ s.ShBinary.generateAndroidBuildActions(ctx)
+ testDir := "nativetest"
+ if ctx.Target().Arch.ArchType.Multilib == "lib64" {
+ testDir = "nativetest64"
+ }
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ testDir = filepath.Join(testDir, ctx.Target().NativeBridgeRelativePath)
+ } else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
+ testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
+ }
+ installDir := android.PathForModuleInstall(ctx, testDir, proptools.String(s.properties.Sub_dir))
+ s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
+
+ s.data = android.PathsForModuleSrc(ctx, s.testProperties.Data)
+
+ var configs []tradefed.Config
+ if Bool(s.testProperties.Require_root) {
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+ } else {
+ options := []tradefed.Option{{Name: "force-root", Value: "false"}}
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
+ }
+ s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config,
+ s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base())
+}
+
+func (s *ShTest) InstallInData() bool {
+ return true
+}
+
+func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "NATIVE_TESTS",
+ OutputFile: android.OptionalPathForPath(s.outputFilePath),
+ Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ s.customAndroidMkEntries(entries)
+
+ entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
+ if s.testProperties.Test_config != nil {
+ entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
+ } else {
+ if s.testConfig != nil {
+ entries.SetString("LOCAL_FULL_TEST_CONFIG", s.testConfig.String())
+ }
+ }
+ for _, d := range s.data {
+ rel := d.Rel()
+ path := d.String()
+ if !strings.HasSuffix(path, rel) {
+ panic(fmt.Errorf("path %q does not end with %q", path, rel))
+ }
+ path = strings.TrimSuffix(path, rel)
+ entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel)
+ }
+ },
+ },
+ }}
+}
+
+func InitShBinaryModule(s *ShBinary) {
+ s.AddProperties(&s.properties)
+}
+
+// sh_binary is for a shell script or batch file to be installed as an
+// executable binary to <partition>/bin.
+func ShBinaryFactory() android.Module {
+ module := &ShBinary{}
+ module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
+ return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
+ })
+ InitShBinaryModule(module)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
+ return module
+}
+
+// sh_binary_host is for a shell script to be installed as an executable binary
+// to $(HOST_OUT)/bin.
+func ShBinaryHostFactory() android.Module {
+ module := &ShBinary{}
+ InitShBinaryModule(module)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+// sh_test defines a shell script based test module.
+func ShTestFactory() android.Module {
+ module := &ShTest{}
+ InitShBinaryModule(&module.ShBinary)
+ module.AddProperties(&module.testProperties)
+
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
+ return module
+}
+
+// sh_test_host defines a shell script based test module that runs on a host.
+func ShTestHostFactory() android.Module {
+ module := &ShTest{}
+ InitShBinaryModule(&module.ShBinary)
+ module.AddProperties(&module.testProperties)
+
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+var Bool = proptools.Bool
diff --git a/android/sh_binary_test.go b/sh/sh_binary_test.go
similarity index 64%
rename from android/sh_binary_test.go
rename to sh/sh_binary_test.go
index 137e773..6c0d96a 100644
--- a/android/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -1,27 +1,56 @@
-package android
+package sh
import (
+ "io/ioutil"
+ "os"
"reflect"
"testing"
+
+ "android/soong/android"
)
-func testShBinary(t *testing.T, bp string) (*TestContext, Config) {
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_sh_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
fs := map[string][]byte{
"test.sh": nil,
"testdata/data1": nil,
"testdata/sub/data2": nil,
}
- config := TestArchConfig(buildDir, nil, bp, fs)
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := NewTestArchContext()
+ ctx := android.NewTestArchContext()
ctx.RegisterModuleType("sh_test", ShTestFactory)
ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
+ android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ android.FailIfErrored(t, errs)
return ctx, config
}
@@ -41,7 +70,7 @@
mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
- entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
expected := []string{":testdata/data1", ":testdata/sub/data2"}
actual := entries.EntryMap["LOCAL_TEST_DATA"]
if !reflect.DeepEqual(expected, actual) {
@@ -62,7 +91,7 @@
}
`)
- buildOS := BuildOs.String()
+ buildOS := android.BuildOs.String()
mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest)
if !mod.Host() {
t.Errorf("host bit is not set for a sh_test_host module.")
diff --git a/shared/Android.bp b/shared/Android.bp
new file mode 100644
index 0000000..07dfe11
--- /dev/null
+++ b/shared/Android.bp
@@ -0,0 +1,7 @@
+bootstrap_go_package {
+ name: "soong-shared",
+ pkgPath: "android/soong/shared",
+ srcs: [
+ "paths.go",
+ ],
+}
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
new file mode 100644
index 0000000..48094f1
--- /dev/null
+++ b/sysprop/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+ name: "soong-sysprop",
+ pkgPath: "android/soong/sysprop",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-java",
+ ],
+ srcs: [
+ "sysprop_library.go",
+ ],
+ testSrcs: [
+ "sysprop_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
new file mode 100644
index 0000000..6e5e533
--- /dev/null
+++ b/tradefed/Android.bp
@@ -0,0 +1,14 @@
+bootstrap_go_package {
+ name: "soong-tradefed",
+ pkgPath: "android/soong/tradefed",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "autogen.go",
+ "config.go",
+ "makevars.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index a46dce9..2829146 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -40,9 +40,9 @@
}
var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
- Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g' $template > $out",
+ Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g' $template > $out",
CommandDeps: []string{"$template"},
-}, "name", "template", "extraConfigs")
+}, "name", "template", "extraConfigs", "outputFileName")
func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) {
p := getTestConfig(ctx, prop)
@@ -64,12 +64,16 @@
type Option struct {
Name string
+ Key string
Value string
}
var _ Config = Option{}
func (o Option) Config() string {
+ if o.Key != "" {
+ return fmt.Sprintf(`<option name="%s" key="%s" value="%s" />`, o.Name, o.Key, o.Value)
+ }
return fmt.Sprintf(`<option name="%s" value="%s" />`, o.Name, o.Value)
}
@@ -104,10 +108,14 @@
}
func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
- autogenTemplateWithName(ctx, ctx.ModuleName(), output, template, configs)
+ autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
}
func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config) {
+ autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
+}
+
+func autogenTemplateWithNameAndOutputFile(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string) {
var configStrings []string
for _, config := range configs {
configStrings = append(configStrings, config.Config())
@@ -120,9 +128,10 @@
Description: "test config",
Output: output,
Args: map[string]string{
- "name": name,
- "template": template,
- "extraConfigs": extraConfigs,
+ "name": name,
+ "template": template,
+ "extraConfigs": extraConfigs,
+ "outputFileName": outputFileName,
},
})
}
@@ -146,6 +155,21 @@
return path
}
+func AutoGenShellTestConfig(ctx android.ModuleContext, testConfigProp *string,
+ testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool, outputFileName string) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
+ if autogenPath != nil {
+ templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+ if templatePath.Valid() {
+ autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, templatePath.String(), config, outputFileName)
+ } else {
+ autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, "${ShellTestConfigTemplate}", config, outputFileName)
+ }
+ return autogenPath
+ }
+ return path
+}
+
func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
@@ -215,31 +239,39 @@
}
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/tradefed/config.go b/tradefed/config.go
index a289073..34195c3 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -33,6 +33,7 @@
pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
pctx.SourcePathVariable("RustDeviceTestConfigTemplate", "build/make/core/rust_device_test_config_template.xml")
pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
+ pctx.SourcePathVariable("ShellTestConfigTemplate", "build/make/core/shell_test_config_template.xml")
pctx.SourcePathVariable("EmptyTestConfig", "build/make/core/empty_test_config.xml")
}
diff --git a/tradefed/makevars.go b/tradefed/makevars.go
index d4cf7a8..f9682e4 100644
--- a/tradefed/makevars.go
+++ b/tradefed/makevars.go
@@ -33,6 +33,7 @@
ctx.Strict("PYTHON_BINARY_HOST_TEST_CONFIG_TEMPLATE", "${PythonBinaryHostTestConfigTemplate}")
ctx.Strict("RUST_DEVICE_TEST_CONFIG_TEMPLATE", "${RustDeviceTestConfigTemplate}")
ctx.Strict("RUST_HOST_TEST_CONFIG_TEMPLATE", "${RustHostTestConfigTemplate}")
+ ctx.Strict("SHELL_TEST_CONFIG_TEMPLATE", "${ShellTestConfigTemplate}")
ctx.Strict("EMPTY_TEST_CONFIG", "${EmptyTestConfig}")
}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 2a5a51a..0a0bb16 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -56,12 +56,14 @@
"signal.go",
"soong.go",
"test_build.go",
+ "upload.go",
"util.go",
],
testSrcs: [
"cleanbuild_test.go",
"config_test.go",
"environment_test.go",
+ "upload_test.go",
"util_test.go",
"proc_sync_test.go",
],
diff --git a/ui/build/build.go b/ui/build/build.go
index 1122733..89c3fad 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -141,7 +141,26 @@
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/cleanbuild.go b/ui/build/cleanbuild.go
index 0bcdccb..e1123e0 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -104,6 +104,7 @@
productOut("*.img"),
productOut("*.zip"),
productOut("android-info.txt"),
+ productOut("misc_info.txt"),
productOut("apex"),
productOut("kernel"),
productOut("data"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 7fcc471..49f506e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -737,6 +737,9 @@
} 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
@@ -958,3 +961,14 @@
func (c *configImpl) IsPdkBuild() bool {
return c.pdkBuild
}
+
+func (c *configImpl) BuildDateTime() string {
+ return c.buildDateTime
+}
+
+func (c *configImpl) MetricsUploaderApp() string {
+ if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok {
+ return p
+ }
+ return ""
+}
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index df618c4..7b14c47 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -26,6 +26,7 @@
"testing"
"android/soong/ui/logger"
+ "android/soong/ui/status"
)
func testContext() Context {
@@ -33,6 +34,7 @@
Context: context.Background(),
Logger: logger.New(&bytes.Buffer{}),
Writer: &bytes.Buffer{},
+ Status: &status.Status{},
}}
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a559330..7dc4915 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -54,18 +54,16 @@
var ret map[string]string
if len(makeVars) > 0 {
+ // It's not safe to use the same TMPDIR as the build, as that can be removed.
tmpDir, err := ioutil.TempDir("", "dumpvars")
if err != nil {
return nil, err
}
defer os.RemoveAll(tmpDir)
- // It's not safe to use the same TMPDIR as the build, as that can be removed.
- config.Environment().Set("TMPDIR", tmpDir)
+ SetupLitePath(ctx, config, tmpDir)
- SetupLitePath(ctx, config)
-
- ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
+ ret, err = dumpMakeVars(ctx, config, goals, makeVars, false, tmpDir)
if err != nil {
return ret, err
}
@@ -82,7 +80,7 @@
return ret, nil
}
-func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
+func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool, tmpDir string) (map[string]string, error) {
ctx.BeginTrace(metrics.RunKati, "dumpvars")
defer ctx.EndTrace()
@@ -98,6 +96,9 @@
cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
}
cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " "))
+ if tmpDir != "" {
+ cmd.Environment.Set("TMPDIR", tmpDir)
+ }
cmd.Sandbox = dumpvarsSandbox
output := bytes.Buffer{}
cmd.Stdout = &output
@@ -253,7 +254,7 @@
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
}, exportEnvVars...), BannerVars...)
- make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
+ make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
if err != nil {
ctx.Fatalln("Error dumping make vars:", err)
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 1b13e5d..fa44cb1 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -39,6 +39,7 @@
args := []string{
"-d", "keepdepfile",
"-d", "keeprsp",
+ "-d", "stats",
"--frontend_file", fifo,
}
diff --git a/ui/build/path.go b/ui/build/path.go
index 7122927..6f5cf78 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -55,8 +55,9 @@
}
// A "lite" version of SetupPath used for dumpvars, or other places that need
-// minimal overhead (but at the expense of logging).
-func SetupLitePath(ctx Context, config Config) {
+// minimal overhead (but at the expense of logging). If tmpDir is empty, the
+// default TMPDIR is used from config.
+func SetupLitePath(ctx Context, config Config, tmpDir string) {
if config.pathReplaced {
return
}
@@ -65,8 +66,11 @@
defer ctx.EndTrace()
origPath, _ := config.Environment().Get("PATH")
- myPath, _ := config.Environment().Get("TMPDIR")
- myPath = filepath.Join(myPath, "path")
+
+ if tmpDir == "" {
+ tmpDir, _ = config.Environment().Get("TMPDIR")
+ }
+ myPath := filepath.Join(tmpDir, "path")
ensureEmptyDirectoriesExist(ctx, myPath)
os.Setenv("PATH", origPath)
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 2fbf381..6a12add 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -119,6 +119,7 @@
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/build/upload.go b/ui/build/upload.go
new file mode 100644
index 0000000..75a5e2f
--- /dev/null
+++ b/ui/build/upload.go
@@ -0,0 +1,80 @@
+// 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 build
+
+// This file contains the functionality to upload data from one location to
+// another.
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+
+ upload_proto "android/soong/ui/metrics/upload_proto"
+)
+
+const (
+ uploadPbFilename = ".uploader.pb"
+)
+
+// UploadMetrics uploads a set of metrics files to a server for analysis. An
+// uploader full path is required to be specified in order to upload the set
+// of metrics files. This is accomplished by defining the ANDROID_ENABLE_METRICS_UPLOAD
+// environment variable.
+func UploadMetrics(ctx Context, config Config, buildStartedMilli int64, files ...string) {
+ uploader := config.MetricsUploaderApp()
+ // No metrics to upload if the path to the uploader was not specified.
+ if uploader == "" {
+ return
+ }
+
+ // Some files may not exist. For example, build errors protobuf file
+ // may not exist since the build was successful.
+ var metricsFiles []string
+ for _, f := range files {
+ if _, err := os.Stat(f); err == nil {
+ metricsFiles = append(metricsFiles, f)
+ }
+ }
+
+ if len(metricsFiles) == 0 {
+ return
+ }
+
+ // For platform builds, the branch and target name is hardcoded to specific
+ // values for later extraction of the metrics in the data metrics pipeline.
+ data, err := proto.Marshal(&upload_proto.Upload{
+ CreationTimestampMs: proto.Uint64(uint64(buildStartedMilli)),
+ CompletionTimestampMs: proto.Uint64(uint64(time.Now().UnixNano() / int64(time.Millisecond))),
+ BranchName: proto.String("developer-metrics"),
+ TargetName: proto.String("platform-build-systems-metrics"),
+ MetricsFiles: metricsFiles,
+ })
+ if err != nil {
+ ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
+ }
+
+ pbFile := filepath.Join(config.OutDir(), uploadPbFilename)
+ if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
+ ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
+ }
+ // Remove the upload file as it's not longer needed after it has been processed by the uploader.
+ defer os.Remove(pbFile)
+
+ Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile).RunAndStreamOrFatal()
+}
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
new file mode 100644
index 0000000..adaa08d
--- /dev/null
+++ b/ui/build/upload_test.go
@@ -0,0 +1,120 @@
+// 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 build
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+
+ "android/soong/ui/logger"
+)
+
+func TestUploadMetrics(t *testing.T) {
+ ctx := testContext()
+ tests := []struct {
+ description string
+ uploader string
+ createFiles bool
+ files []string
+ }{{
+ description: "ANDROID_ENABLE_METRICS_UPLOAD not set",
+ }, {
+ description: "no metrics files to upload",
+ uploader: "fake",
+ }, {
+ description: "non-existent metrics files no upload",
+ uploader: "fake",
+ files: []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"},
+ }, {
+ description: "trigger upload",
+ uploader: "echo",
+ createFiles: true,
+ files: []string{"metrics_file_1", "metrics_file_2"},
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ defer logger.Recover(func(err error) {
+ t.Fatalf("got unexpected error: %v", err)
+ })
+
+ outDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create out directory: %v", outDir)
+ }
+ defer os.RemoveAll(outDir)
+
+ var metricsFiles []string
+ if tt.createFiles {
+ for _, f := range tt.files {
+ filename := filepath.Join(outDir, f)
+ metricsFiles = append(metricsFiles, filename)
+ if err := ioutil.WriteFile(filename, []byte("test file"), 0644); err != nil {
+ t.Fatalf("failed to create a fake metrics file %q for uploading: %v", filename, err)
+ }
+ }
+ }
+
+ config := Config{&configImpl{
+ environ: &Environment{
+ "OUT_DIR=" + outDir,
+ "ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader,
+ },
+ buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
+ }}
+
+ UploadMetrics(ctx, config, 1591031903, metricsFiles...)
+
+ if _, err := os.Stat(filepath.Join(outDir, uploadPbFilename)); err == nil {
+ t.Error("got true, want false for upload protobuf file to exist")
+ }
+ })
+ }
+}
+
+func TestUploadMetricsErrors(t *testing.T) {
+ expectedErr := "failed to write the marshaled"
+ defer logger.Recover(func(err error) {
+ got := err.Error()
+ if !strings.Contains(got, expectedErr) {
+ t.Errorf("got %q, want %q to be contained in error", got, expectedErr)
+ }
+ })
+
+ outDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create out directory: %v", outDir)
+ }
+ defer os.RemoveAll(outDir)
+
+ metricsFile := filepath.Join(outDir, "metrics_file_1")
+ if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
+ t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
+ }
+
+ config := Config{&configImpl{
+ environ: &Environment{
+ "ANDROID_ENABLE_METRICS_UPLOAD=fake",
+ "OUT_DIR=/bad",
+ }}}
+
+ UploadMetrics(testContext(), config, 1591031903, metricsFile)
+ t.Errorf("got nil, expecting %q as a failure", expectedErr)
+}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 9cf2f6a..a11774c 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -174,6 +174,8 @@
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 7c05eed..7ba9de2 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 @@
// 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 @@
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 @@
*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 @@
*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) 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) 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) 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) 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) 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 @@
// 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) 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 @@
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) 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 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 @@
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) }
+func init() {
+ proto.RegisterFile("frontend.proto", fileDescriptor_eca3873955a29cfe)
+}
-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,
+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 13fd535..baa0046 100644
--- a/ui/status/ninja_frontend/frontend.proto
+++ b/ui/status/ninja_frontend/frontend.proto
@@ -61,6 +61,10 @@
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 @@
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;
diff --git a/xml/Android.bp b/xml/Android.bp
new file mode 100644
index 0000000..cd25cff
--- /dev/null
+++ b/xml/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+ name: "soong-xml",
+ pkgPath: "android/soong/xml",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-etc",
+ ],
+ srcs: [
+ "xml.go",
+ ],
+ testSrcs: [
+ "xml_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/xml/xml.go b/xml/xml.go
index 3a680ec..8810ae4 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/etc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -62,7 +63,7 @@
}
type prebuiltEtcXml struct {
- android.PrebuiltEtc
+ etc.PrebuiltEtc
properties prebuiltEtcXmlProperties
}
@@ -121,7 +122,7 @@
func PrebuiltEtcXmlFactory() android.Module {
module := &prebuiltEtcXml{}
module.AddProperties(&module.properties)
- android.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
+ etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
diff --git a/xml/xml_test.go b/xml/xml_test.go
index f8ec823..abcb108 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -20,6 +20,7 @@
"testing"
"android/soong/android"
+ "android/soong/etc"
)
var buildDir string
@@ -57,7 +58,7 @@
}
config := android.TestArchConfig(buildDir, nil, bp, fs)
ctx := android.NewTestArchContext()
- ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
+ ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})