Merge "Dedup code for generating prebuilt_stubs_sources in snapshot"
diff --git a/README.md b/README.md
index 73aa1ed..37feb1d 100644
--- a/README.md
+++ b/README.md
@@ -36,13 +36,28 @@
For a list of valid module types and their properties see
[$OUT_DIR/soong/docs/soong_build.html](https://ci.android.com/builds/latest/branches/aosp-build-tools/targets/linux/view/soong_build.html).
-### Globs
+### File lists
-Properties that take a list of files can also take glob patterns. Glob
-patterns can contain the normal Unix wildcard `*`, for example "*.java". Glob
-patterns can also contain a single `**` wildcard as a path element, which will
-match zero or more path elements. For example, `java/**/*.java` will match
-`java/Main.java` and `java/com/android/Main.java`.
+Properties that take a list of files can also take glob patterns and output path
+expansions.
+
+* Glob patterns can contain the normal Unix wildcard `*`, for example `"*.java"`.
+
+ Glob patterns can also contain a single `**` wildcard as a path element, which
+ will match zero or more path elements. For example, `java/**/*.java` will match
+ `java/Main.java` and `java/com/android/Main.java`.
+
+* Output path expansions take the format `:module` or `:module{.tag}`, where
+ `module` is the name of a module that produces output files, and it expands to
+ a list of those output files. With the optional `{.tag}` suffix, the module
+ may produce a different list of outputs according to `tag`.
+
+ For example, a `droiddoc` module with the name "my-docs" would return its
+ `.stubs.srcjar` output with `":my-docs"`, and its `.doc.zip` file with
+ `":my-docs{.doc.zip}"`.
+
+ This is commonly used to reference `filegroup` modules, whose output files
+ consist of their `srcs`.
### Variables
@@ -64,6 +79,7 @@
referenced.
### Comments
+
Android.bp files can contain C-style multiline `/* */` and C++ style single-line
`//` comments.
diff --git a/android/module.go b/android/module.go
index 5b2f9d3..2ae2961 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1533,9 +1533,11 @@
}
func (m *ModuleBase) MakeAsSystemExt() {
- if !Bool(m.commonProperties.Vendor) && !Bool(m.commonProperties.Product_specific) {
- m.commonProperties.System_ext_specific = boolPtr(true)
- }
+ m.commonProperties.Vendor = boolPtr(false)
+ m.commonProperties.Proprietary = boolPtr(false)
+ m.commonProperties.Soc_specific = boolPtr(false)
+ m.commonProperties.Product_specific = boolPtr(false)
+ m.commonProperties.System_ext_specific = boolPtr(true)
}
// IsNativeBridgeSupported returns true if "native_bridge_supported" is explicitly set as "true"
diff --git a/apex/apex.go b/apex/apex.go
index 4c5e06b..45184b5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -178,7 +178,7 @@
modules[i].(*apexBundle).properties.ApexType = zipApex
case flattenedApexType:
modules[i].(*apexBundle).properties.ApexType = flattenedApex
- if !mctx.Config().FlattenApex() {
+ if !mctx.Config().FlattenApex() && ab.Platform() {
modules[i].(*apexBundle).MakeAsSystemExt()
}
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 51cb74e..a41f914 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2144,38 +2144,47 @@
ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
}
-func TestApexInProductPartition(t *testing.T) {
- ctx, _ := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- product_specific: true,
- file_contexts: "myapex_file_contexts",
- }
+func TestApexInVariousPartition(t *testing.T) {
+ testcases := []struct {
+ propName, parition, flattenedPartition string
+ }{
+ {"", "system", "system_ext"},
+ {"product_specific: true", "product", "product"},
+ {"soc_specific: true", "vendor", "vendor"},
+ {"proprietary: true", "vendor", "vendor"},
+ {"vendor: true", "vendor", "vendor"},
+ {"system_ext_specific: true", "system_ext", "system_ext"},
+ }
+ for _, tc := range testcases {
+ t.Run(tc.propName+":"+tc.parition, func(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ `+tc.propName+`
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- product_specific: true,
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- system_shared_libs: [],
- stl: "none",
- }
- `, withFiles(map[string][]byte{
- "myapex_file_contexts": nil,
- }))
+ apex := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ expected := buildDir + "/target/product/test_device/" + tc.parition + "/apex"
+ actual := apex.installDir.String()
+ if actual != expected {
+ t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
+ }
- apex := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
- expected := buildDir + "/target/product/test_device/product/apex"
- actual := apex.installDir.String()
- if actual != expected {
- t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
+ flattened := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle)
+ expected = buildDir + "/target/product/test_device/" + tc.flattenedPartition + "/apex"
+ actual = flattened.installDir.String()
+ if actual != expected {
+ t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
+ }
+ })
}
}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 46e0f0a..18a38fb 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -102,6 +102,13 @@
return true
}
+ // Don't preopt system server jars that are updatable.
+ for _, p := range global.UpdatableSystemServerJars {
+ if _, jar := SplitApexJarPair(p); jar == module.Name {
+ return true
+ }
+ }
+
// If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
// Also preopt system server jars since selinux prevents system server from loading anything from
// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
@@ -537,6 +544,16 @@
}
}
+// 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))
+ }
+ return apexJarPair[0], apexJarPair[1]
+}
+
func contains(l []string, s string) bool {
for _, e := range l {
if e == s {
diff --git a/java/aar.go b/java/aar.go
index d8db192..e0bea5d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -694,6 +694,10 @@
return nil
}
+func (d *AARImport) ExportedPlugins() (android.Paths, []string) {
+ return nil, nil
+}
+
func (a *AARImport) SrcJarArgs() ([]string, android.Paths) {
return nil, nil
}
diff --git a/java/app.go b/java/app.go
old mode 100644
new mode 100755
index c635703..c772e47
--- a/java/app.go
+++ b/java/app.go
@@ -974,7 +974,13 @@
jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
- installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
+ var installDir android.InstallPath
+ if Bool(a.properties.Privileged) {
+ installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
+ }
+
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
a.dexpreopter.isInstallable = true
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 14db521..1524418 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -162,6 +162,10 @@
return nil
}
+func (d *DeviceHostConverter) ExportedPlugins() (android.Paths, []string) {
+ return nil, nil
+}
+
func (d *DeviceHostConverter) SrcJarArgs() ([]string, android.Paths) {
return d.srcJarArgs, d.srcJarDeps
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 15f11e1..4747c64 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -15,7 +15,6 @@
package java
import (
- "fmt"
"path/filepath"
"strings"
@@ -66,16 +65,6 @@
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
-// 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))
- }
- return apexJarPair[0], apexJarPair[1]
-}
-
// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed
// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
// ctx.Config().
@@ -89,9 +78,9 @@
filepath.Join("/system/framework", m+".jar"))
}
for _, m := range global.UpdatableSystemServerJars {
- apex, jar := splitApexJarPair(m)
+ apex, jar := dexpreopt.SplitApexJarPair(m)
systemServerClasspathLocations = append(systemServerClasspathLocations,
- filepath.Join("/apex", apex, "javalib", jar + ".jar"))
+ filepath.Join("/apex", apex, "javalib", jar+".jar"))
}
return systemServerClasspathLocations
})
diff --git a/java/java.go b/java/java.go
index 1104785..1c52575 100644
--- a/java/java.go
+++ b/java/java.go
@@ -145,6 +145,9 @@
// List of modules to use as annotation processors
Plugins []string
+ // List of modules to export to libraries that directly depend on this library as annotation processors
+ Exported_plugins []string
+
// The number of Java source entries each Javac instance can process
Javac_shard_size *int64
@@ -360,10 +363,16 @@
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
- // list of SDK lib names that this java moudule is exporting
+ // list of SDK lib names that this java module is exporting
exportedSdkLibs []string
- // list of source files, collected from srcFiles with uniqie java and all kt files,
+ // list of plugins that this java module is exporting
+ exportedPluginJars android.Paths
+
+ // list of plugins that this java module is exporting
+ exportedPluginClasses []string
+
+ // list of source files, collected from srcFiles with unique java and all kt files,
// will be used by android.IDEInfo struct
expandIDEInfoCompiledSrcs []string
@@ -410,6 +419,7 @@
DexJar() android.Path
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
+ ExportedPlugins() (android.Paths, []string)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
}
@@ -452,6 +462,7 @@
libTag = dependencyTag{name: "javalib"}
java9LibTag = dependencyTag{name: "java9lib"}
pluginTag = dependencyTag{name: "plugin"}
+ exportedPluginTag = dependencyTag{name: "exported-plugin"}
bootClasspathTag = dependencyTag{name: "bootclasspath"}
systemModulesTag = dependencyTag{name: "system modules"}
frameworkResTag = dependencyTag{name: "framework-res"}
@@ -561,6 +572,7 @@
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
android.ProtoDeps(ctx, &j.protoProperties)
if j.hasSrcExt(".proto") {
@@ -800,6 +812,8 @@
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
+ pluginJars, pluginClasses := dep.ExportedPlugins()
+ addPlugins(&deps, pluginJars, pluginClasses...)
case java9LibTag:
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars()...)
case staticLibTag:
@@ -810,16 +824,31 @@
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
+ pluginJars, pluginClasses := dep.ExportedPlugins()
+ addPlugins(&deps, pluginJars, pluginClasses...)
case pluginTag:
if plugin, ok := dep.(*Plugin); ok {
- deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...)
if plugin.pluginProperties.Processor_class != nil {
- deps.processorClasses = append(deps.processorClasses, *plugin.pluginProperties.Processor_class)
+ addPlugins(&deps, plugin.ImplementationAndResourcesJars(), *plugin.pluginProperties.Processor_class)
+ } else {
+ addPlugins(&deps, plugin.ImplementationAndResourcesJars())
}
deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
} else {
ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
}
+ case exportedPluginTag:
+ if plugin, ok := dep.(*Plugin); ok {
+ if plugin.pluginProperties.Generates_api != nil && *plugin.pluginProperties.Generates_api {
+ ctx.PropertyErrorf("exported_plugins", "Cannot export plugins with generates_api = true, found %v", otherName)
+ }
+ j.exportedPluginJars = append(j.exportedPluginJars, plugin.ImplementationAndResourcesJars()...)
+ if plugin.pluginProperties.Processor_class != nil {
+ j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
+ }
+ } else {
+ ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
+ }
case frameworkApkTag:
if ctx.ModuleName() == "android_stubs_current" ||
ctx.ModuleName() == "android_system_stubs_current" ||
@@ -875,6 +904,11 @@
return deps
}
+func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
+ deps.processorPath = append(deps.processorPath, pluginJars...)
+ deps.processorClasses = append(deps.processorClasses, pluginClasses...)
+}
+
func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion {
v := sdkContext.sdkVersion()
// For PDK builds, use the latest SDK version instead of "current"
@@ -1569,6 +1603,10 @@
return j.exportedSdkLibs
}
+func (j *Module) ExportedPlugins() (android.Paths, []string) {
+ return j.exportedPluginJars, j.exportedPluginClasses
+}
+
func (j *Module) SrcJarArgs() ([]string, android.Paths) {
return j.srcJarArgs, j.srcJarDeps
}
@@ -2145,6 +2183,10 @@
return j.exportedSdkLibs
}
+func (j *Import) ExportedPlugins() (android.Paths, []string) {
+ return nil, nil
+}
+
func (j *Import) SrcJarArgs() ([]string, android.Paths) {
return nil, nil
}
diff --git a/java/java_test.go b/java/java_test.go
index efef7c1..dc498a4 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -332,6 +332,89 @@
}
}
+func TestExportedPlugins(t *testing.T) {
+ type Result struct {
+ library string
+ processors string
+ }
+ var tests = []struct {
+ name string
+ extra string
+ results []Result
+ }{
+ {
+ name: "Exported plugin is not a direct plugin",
+ extra: `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`,
+ results: []Result{{library: "exports", processors: "-proc:none"}},
+ },
+ {
+ name: "Exports plugin to dependee",
+ extra: `
+ java_library{name: "exports", exported_plugins: ["plugin"]}
+ java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
+ java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
+ `,
+ results: []Result{
+ {library: "foo", processors: "-processor com.android.TestPlugin"},
+ {library: "bar", processors: "-processor com.android.TestPlugin"},
+ },
+ },
+ {
+ name: "Exports plugin to android_library",
+ extra: `
+ java_library{name: "exports", exported_plugins: ["plugin"]}
+ android_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
+ android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
+ `,
+ results: []Result{
+ {library: "foo", processors: "-processor com.android.TestPlugin"},
+ {library: "bar", processors: "-processor com.android.TestPlugin"},
+ },
+ },
+ {
+ name: "Exports plugin is not propagated via transitive deps",
+ extra: `
+ java_library{name: "exports", exported_plugins: ["plugin"]}
+ java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
+ java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]}
+ `,
+ results: []Result{
+ {library: "foo", processors: "-processor com.android.TestPlugin"},
+ {library: "bar", processors: "-proc:none"},
+ },
+ },
+ {
+ name: "Exports plugin appends to plugins",
+ extra: `
+ java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"}
+ java_library{name: "exports", exported_plugins: ["plugin"]}
+ java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]}
+ `,
+ results: []Result{
+ {library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"},
+ },
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_plugin {
+ name: "plugin",
+ processor_class: "com.android.TestPlugin",
+ }
+ `+test.extra)
+
+ for _, want := range test.results {
+ javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac")
+ if javac.Args["processor"] != want.processors {
+ t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"])
+ }
+ }
+ })
+ }
+}
+
func TestSdkVersionByPartition(t *testing.T) {
testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
java_library {