Merge "Overriding placeholder version in updatable apks"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index aa4363c..79d4910 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -132,6 +132,7 @@
"external/libevent": Bp2BuildDefaultTrueRecursively,
"external/libgav1": Bp2BuildDefaultTrueRecursively,
"external/libhevc": Bp2BuildDefaultTrueRecursively,
+ "external/libjpeg-turbo": Bp2BuildDefaultTrueRecursively,
"external/libmpeg2": Bp2BuildDefaultTrueRecursively,
"external/libpng": Bp2BuildDefaultTrueRecursively,
"external/lz4/lib": Bp2BuildDefaultTrue,
@@ -217,6 +218,7 @@
"system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
"tools/apksig": Bp2BuildDefaultTrue,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
+ "tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
}
Bp2buildKeepExistingBuildFile = map[string]bool{
@@ -262,6 +264,7 @@
"prebuilts/gcc":/* recursive = */ true,
"prebuilts/build-tools":/* recursive = */ true,
"prebuilts/jdk/jdk11":/* recursive = */ false,
+ "prebuilts/misc":/* recursive = */ false, // not recursive because we need bp2build converted build files in prebuilts/misc/common/asm
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
"prebuilts/sdk/current/support":/* recursive = */ false,
@@ -377,15 +380,16 @@
"gen-kotlin-build-file.py", // TODO(b/198619163) module has same name as source
"libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support.
"linkerconfig", "mdnsd", // TODO(b/202876379): has arch-variant static_executable
- "linker", // TODO(b/228316882): cc_binary uses link_crt
- "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
- "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
- "libspeexresampler", // TODO(b/231995978): Filter out unknown cflags
- "libjpeg", "libvpx", // TODO(b/233948256): Convert .asm files
+ "linker", // TODO(b/228316882): cc_binary uses link_crt
+ "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
+ "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
+ "libspeexresampler", // TODO(b/231995978): Filter out unknown cflags
+ "libvpx", // TODO(b/240756936): Arm neon variant not supported
"art_libartbase_headers", // TODO(b/236268577): Header libraries do not support export_shared_libs_headers
"apexer_test", // Requires aapt2
"apexer_test_host_tools",
"host_apex_verifier",
+ "tjbench", // TODO(b/240563612): Stem property
// java bugs
"libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
@@ -526,5 +530,20 @@
"simpleperf_ndk",
"toybox-static",
"zlib_bench",
+
+ // java_import[_host] issues
+ // tradefed prebuilts depend on libprotobuf
+ "prebuilt_tradefed",
+ "prebuilt_tradefed-test-framework",
+ // handcrafted BUILD.bazel files in //prebuilts/...
+ "prebuilt_r8lib-prebuilt",
+ "prebuilt_sdk-core-lambda-stubs",
+ "prebuilt_android-support-collections-nodeps",
+ "prebuilt_android-arch-core-common-nodeps",
+ "prebuilt_android-arch-lifecycle-common-java8-nodeps",
+ "prebuilt_android-arch-lifecycle-common-nodeps",
+ "prebuilt_android-support-annotations-nodeps",
+ "prebuilt_android-arch-paging-common-nodeps",
+ "prebuilt_android-arch-room-common-nodeps",
}
)
diff --git a/android/bazel.go b/android/bazel.go
index 40f2917..183a2f3 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -35,6 +35,20 @@
Bp2BuildTopLevel = "."
)
+type BazelConversionStatus struct {
+ // Information about _all_ bp2build targets generated by this module. Multiple targets are
+ // supported as Soong handles some things within a single target that we may choose to split into
+ // multiple targets, e.g. renderscript, protos, yacc within a cc module.
+ Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
+
+ // UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
+ // Bazel
+ UnconvertedDeps []string `blueprint:"mutated"`
+
+ // MissingBp2buildDep stores the module names of direct dependency that were not found
+ MissingDeps []string `blueprint:"mutated"`
+}
+
type bazelModuleProperties struct {
// The label of the Bazel target replacing this Soong module. When run in conversion mode, this
// will import the handcrafted build target into the autogenerated file. Note: this may result in
diff --git a/android/module.go b/android/module.go
index 4dbfdd3..39f5ff9 100644
--- a/android/module.go
+++ b/android/module.go
@@ -909,17 +909,8 @@
// constants in image.go, but can also be set to a custom value by individual module types.
ImageVariation string `blueprint:"mutated"`
- // Information about _all_ bp2build targets generated by this module. Multiple targets are
- // supported as Soong handles some things within a single target that we may choose to split into
- // multiple targets, e.g. renderscript, protos, yacc within a cc module.
- Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
-
- // UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
- // Bazel
- UnconvertedBp2buildDeps []string `blueprint:"mutated"`
-
- // MissingBp2buildDep stores the module names of direct dependency that were not found
- MissingBp2buildDeps []string `blueprint:"mutated"`
+ // Bazel conversion status
+ BazelConversionStatus BazelConversionStatus `blueprint:"mutated"`
}
// CommonAttributes represents the common Bazel attributes from which properties
@@ -1489,40 +1480,40 @@
}
func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
- m.commonProperties.Bp2buildInfo = append(m.commonProperties.Bp2buildInfo, info)
+ m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
}
// IsConvertedByBp2build returns whether this module was converted via bp2build.
func (m *ModuleBase) IsConvertedByBp2build() bool {
- return len(m.commonProperties.Bp2buildInfo) > 0
+ return len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0
}
// Bp2buildTargets returns the Bazel targets bp2build generated for this module.
func (m *ModuleBase) Bp2buildTargets() []bp2buildInfo {
- return m.commonProperties.Bp2buildInfo
+ return m.commonProperties.BazelConversionStatus.Bp2buildInfo
}
// AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
- unconvertedDeps := &b.Module().base().commonProperties.UnconvertedBp2buildDeps
+ unconvertedDeps := &b.Module().base().commonProperties.BazelConversionStatus.UnconvertedDeps
*unconvertedDeps = append(*unconvertedDeps, dep)
}
// AddMissingBp2buildDep stores module name of a dependency that was not found in a Android.bp file.
func (b *baseModuleContext) AddMissingBp2buildDep(dep string) {
- missingDeps := &b.Module().base().commonProperties.MissingBp2buildDeps
+ missingDeps := &b.Module().base().commonProperties.BazelConversionStatus.MissingDeps
*missingDeps = append(*missingDeps, dep)
}
// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
// were not converted to Bazel.
func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.UnconvertedBp2buildDeps)
+ return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.UnconvertedDeps)
}
// GetMissingBp2buildDeps eturns the list of module names that were not found in Android.bp files.
func (m *ModuleBase) GetMissingBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.MissingBp2buildDeps)
+ return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.MissingDeps)
}
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
diff --git a/android/neverallow.go b/android/neverallow.go
index aa47bca..00078a0 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -212,11 +212,16 @@
}
func createMakefileGoalRules() []Rule {
+ allowlist := []string{
+ // libwifi_hal uses makefile_goal for its dependencies
+ "frameworks/opt/net/wifi/libwifi_hal",
+ }
return []Rule{
NeverAllow().
ModuleType("makefile_goal").
WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")).
- Because("Only boot images may be imported as a makefile goal."),
+ NotIn(allowlist...).
+ Because("Only boot images may be imported as a makefile goal if not in allowed projects"),
}
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 86f1a37..4772799 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -324,7 +324,32 @@
`),
},
expectedErrors: []string{
- "Only boot images may be imported as a makefile goal.",
+ "Only boot images.* may be imported as a makefile goal",
+ },
+ },
+ {
+ name: "disallowed makefile_goal outside external",
+ fs: map[string][]byte{
+ "project/Android.bp": []byte(`
+ makefile_goal {
+ name: "foo",
+ product_out_path: "obj/EXE/foo",
+ }
+ `),
+ },
+ expectedErrors: []string{
+ "not in allowed projects",
+ },
+ },
+ {
+ name: "allow makefile_goal within external",
+ fs: map[string][]byte{
+ "frameworks/opt/net/wifi/libwifi_hal/Android.bp": []byte(`
+ makefile_goal {
+ name: "foo",
+ product_out_path: "obj/EXE/foo",
+ }
+ `),
},
},
// Tests for the rule prohibiting the use of framework
diff --git a/bp2build/cc_yasm_conversion_test.go b/bp2build/cc_yasm_conversion_test.go
new file mode 100644
index 0000000..6114a49
--- /dev/null
+++ b/bp2build/cc_yasm_conversion_test.go
@@ -0,0 +1,179 @@
+// Copyright 2022 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 bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func runYasmTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, registerYasmModuleTypes, tc)
+}
+
+func registerYasmModuleTypes(ctx android.RegistrationContext) {
+ cc.RegisterCCBuildComponents(ctx)
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+ ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
+ ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
+ ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+}
+
+func TestYasmSimple(t *testing.T) {
+ runYasmTestCase(t, bp2buildTestCase{
+ description: "Simple yasm test",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{
+ "main.cpp": "",
+ "myfile.asm": "",
+ },
+ blueprint: `
+cc_library {
+ name: "foo",
+ srcs: ["main.cpp", "myfile.asm"],
+}`,
+ expectedBazelTargets: append([]string{
+ makeBazelTarget("yasm", "foo_yasm", map[string]string{
+ "include_dirs": `["."]`,
+ "srcs": `["myfile.asm"]`,
+ }),
+ }, makeCcLibraryTargets("foo", map[string]string{
+ "local_includes": `["."]`,
+ "srcs": `[
+ "main.cpp",
+ ":foo_yasm",
+ ]`,
+ })...),
+ })
+}
+
+func TestYasmWithIncludeDirs(t *testing.T) {
+ runYasmTestCase(t, bp2buildTestCase{
+ description: "Simple yasm test",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{
+ "main.cpp": "",
+ "myfile.asm": "",
+ "include1/foo/myinclude.inc": "",
+ "include2/foo/myinclude2.inc": "",
+ },
+ blueprint: `
+cc_library {
+ name: "foo",
+ local_include_dirs: ["include1/foo"],
+ export_include_dirs: ["include2/foo"],
+ srcs: ["main.cpp", "myfile.asm"],
+}`,
+ expectedBazelTargets: append([]string{
+ makeBazelTarget("yasm", "foo_yasm", map[string]string{
+ "include_dirs": `[
+ "include1/foo",
+ ".",
+ "include2/foo",
+ ]`,
+ "srcs": `["myfile.asm"]`,
+ }),
+ }, makeCcLibraryTargets("foo", map[string]string{
+ "local_includes": `[
+ "include1/foo",
+ ".",
+ ]`,
+ "export_includes": `["include2/foo"]`,
+ "srcs": `[
+ "main.cpp",
+ ":foo_yasm",
+ ]`,
+ })...),
+ })
+}
+
+func TestYasmConditionalBasedOnArch(t *testing.T) {
+ runYasmTestCase(t, bp2buildTestCase{
+ description: "Simple yasm test",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{
+ "main.cpp": "",
+ "myfile.asm": "",
+ },
+ blueprint: `
+cc_library {
+ name: "foo",
+ srcs: ["main.cpp"],
+ arch: {
+ x86: {
+ srcs: ["myfile.asm"],
+ },
+ },
+}`,
+ expectedBazelTargets: append([]string{
+ makeBazelTarget("yasm", "foo_yasm", map[string]string{
+ "include_dirs": `["."]`,
+ "srcs": `select({
+ "//build/bazel/platforms/arch:x86": ["myfile.asm"],
+ "//conditions:default": [],
+ })`,
+ }),
+ }, makeCcLibraryTargets("foo", map[string]string{
+ "local_includes": `["."]`,
+ "srcs": `["main.cpp"] + select({
+ "//build/bazel/platforms/arch:x86": [":foo_yasm"],
+ "//conditions:default": [],
+ })`,
+ })...),
+ })
+}
+
+func TestYasmPartiallyConditional(t *testing.T) {
+ runYasmTestCase(t, bp2buildTestCase{
+ description: "Simple yasm test",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{
+ "main.cpp": "",
+ "myfile.asm": "",
+ "mysecondfile.asm": "",
+ },
+ blueprint: `
+cc_library {
+ name: "foo",
+ srcs: ["main.cpp", "myfile.asm"],
+ arch: {
+ x86: {
+ srcs: ["mysecondfile.asm"],
+ },
+ },
+}`,
+ expectedBazelTargets: append([]string{
+ makeBazelTarget("yasm", "foo_yasm", map[string]string{
+ "include_dirs": `["."]`,
+ "srcs": `["myfile.asm"] + select({
+ "//build/bazel/platforms/arch:x86": ["mysecondfile.asm"],
+ "//conditions:default": [],
+ })`,
+ }),
+ }, makeCcLibraryTargets("foo", map[string]string{
+ "local_includes": `["."]`,
+ "srcs": `[
+ "main.cpp",
+ ":foo_yasm",
+ ]`,
+ })...),
+ })
+}
diff --git a/build_kzip.bash b/build_kzip.bash
index 6219021..fa616b9 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -44,14 +44,18 @@
declare -r go_root=$(realpath prebuilts/go/linux-x86)
declare -r source_root=$PWD
-# TODO(asmundak): Until b/182183061 is fixed, default corpus has to be specified
-# in the rules file. Generate this file on the fly with corpus value set from the
-# environment variable.
-for dir in blueprint soong; do
- (cd "build/$dir";
+# For the Go code, we invoke the extractor directly. The two caveats are that
+# the extractor's rewrite rules are generated on the fly as they depend on the XREF_CORPUS
+# value, and that the name of the kzip file is derived from the directory name
+# by replacing '/' with '_'.
+declare -ar go_modules=(build/blueprint build/soong
+ build/make/tools/canoninja build/make/tools/compliance build/make/tools/rbcrun)
+for dir in "${go_modules[@]}"; do
+ (cd "$dir";
+ outfile=$(echo "$dir" | sed -r 's|/|_|g;s|(.*)|\1.go.kzip|');
KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" \
--rules=<(printf '[{"pattern": "(.*)","vname": {"path": "@1@", "corpus":"%s"}}]' "${XREF_CORPUS}") \
- --canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
+ --canonicalize_package_corpus --output "${abspath_out}/soong/$outfile" ./...
)
done
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6cd6733..61a55ee 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -4,7 +4,7 @@
// 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
+// 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,
@@ -30,6 +30,7 @@
const (
cSrcPartition = "c"
asSrcPartition = "as"
+ asmSrcPartition = "asm"
lSrcPartition = "l"
llSrcPartition = "ll"
cppSrcPartition = "cpp"
@@ -81,6 +82,7 @@
protoSrcPartition: android.ProtoSrcLabelPartition,
cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
+ asmSrcPartition: bazel.LabelPartition{Extensions: []string{".asm"}},
// TODO(http://b/231968910): If there is ever a filegroup target that
// contains .l or .ll files we will need to find a way to add a
// LabelMapper for these that identifies these filegroups and
@@ -289,6 +291,7 @@
// Assembly options and sources
asFlags bazel.StringListAttribute
asSrcs bazel.LabelListAttribute
+ asmSrcs bazel.LabelListAttribute
// C options and sources
conlyFlags bazel.StringListAttribute
cSrcs bazel.LabelListAttribute
@@ -447,6 +450,7 @@
ca.srcs = partitionedSrcs[cppSrcPartition]
ca.cSrcs = partitionedSrcs[cSrcPartition]
ca.asSrcs = partitionedSrcs[asSrcPartition]
+ ca.asmSrcs = partitionedSrcs[asmSrcPartition]
ca.lSrcs = partitionedSrcs[lSrcPartition]
ca.llSrcs = partitionedSrcs[llSrcPartition]
@@ -527,6 +531,61 @@
return relative, absolute
}
+type YasmAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Flags bazel.StringListAttribute
+ Include_dirs bazel.StringListAttribute
+}
+
+func bp2BuildYasm(ctx android.Bp2buildMutatorContext, m *Module, ca compilerAttributes) *bazel.LabelAttribute {
+ if ca.asmSrcs.IsEmpty() {
+ return nil
+ }
+
+ // Yasm needs the include directories from both local_includes and
+ // export_include_dirs. We don't care about actually exporting them from the
+ // yasm rule though, because they will also be present on the cc_ rule that
+ // wraps this yasm rule.
+ includes := ca.localIncludes.Clone()
+ bp2BuildPropParseHelper(ctx, m, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
+ if len(flagExporterProperties.Export_include_dirs) > 0 {
+ x := bazel.StringListAttribute{}
+ x.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs)
+ includes.Append(x)
+ }
+ }
+ })
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "yasm",
+ Bzl_load_location: "//build/bazel/rules/cc:yasm.bzl",
+ },
+ android.CommonAttributes{Name: m.Name() + "_yasm"},
+ &YasmAttributes{
+ Srcs: ca.asmSrcs,
+ Flags: ca.asFlags,
+ Include_dirs: *includes,
+ })
+
+ // We only want to add a dependency on the _yasm target if there are asm
+ // sources in the current configuration. If there are unconfigured asm
+ // sources, always add the dependency. Otherwise, add the dependency only
+ // on the configuration axes and values that had asm sources.
+ if len(ca.asmSrcs.Value.Includes) > 0 {
+ return bazel.MakeLabelAttribute(":" + m.Name() + "_yasm")
+ }
+
+ ret := &bazel.LabelAttribute{}
+ for _, axis := range ca.asmSrcs.SortedConfigurationAxes() {
+ for config := range ca.asmSrcs.ConfigurableValues[axis] {
+ ret.SetSelectValue(axis, config, bazel.Label{Label: ":" + m.Name() + "_yasm"})
+ }
+ }
+ return ret
+}
+
// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module..
func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
@@ -612,6 +671,8 @@
(&compilerAttrs).finalize(ctx, implementationHdrs)
(&linkerAttrs).finalize(ctx)
+ (&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
+
protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
// bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
diff --git a/java/Android.bp b/java/Android.bp
index e25accf..9df4ab4 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -76,6 +76,7 @@
"tradefed.go",
],
testSrcs: [
+ "aar_test.go",
"androidmk_test.go",
"app_import_test.go",
"app_set_test.go",
diff --git a/java/aar.go b/java/aar.go
index e13ccb3..a59ecb8 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -572,12 +572,24 @@
a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
+
+ prebuiltJniPackages := android.Paths{}
+ ctx.VisitDirectDeps(func(module android.Module) {
+ if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
+ }
+ })
+ if len(prebuiltJniPackages) > 0 {
+ ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+ JniPackages: prebuiltJniPackages,
+ })
+ }
}
// android_library builds and links sources into a `.jar` file for the device along with Android resources.
//
// An android_library has a single variant that produces a `.jar` file containing `.class` files that were
-// compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled
+// compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled
// with aapt2. This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
// an android_app module.
func AndroidLibraryFactory() android.Module {
@@ -621,6 +633,10 @@
Libs []string
// If set to true, run Jetifier against .aar file. Defaults to false.
Jetifier *bool
+ // If true, extract JNI libs from AAR archive. These libs will be accessible to android_app modules and
+ // will be passed transitively through android_libraries to an android_app.
+ //TODO(b/241138093) evaluate whether we can have this flag default to true for Bazel conversion
+ Extract_jni *bool
}
type AARImport struct {
@@ -645,7 +661,8 @@
hideApexVariantFromMake bool
- aarPath android.Path
+ aarPath android.Path
+ jniPackages android.Paths
sdkVersion android.SdkSpec
minSdkVersion android.SdkSpec
@@ -753,6 +770,28 @@
ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
}
+type JniPackageInfo struct {
+ // List of zip files containing JNI libraries
+ // Zip files should have directory structure jni/<arch>/*.so
+ JniPackages android.Paths
+}
+
+var JniPackageProvider = blueprint.NewProvider(JniPackageInfo{})
+
+// Unzip an AAR and extract the JNI libs for $archString.
+var extractJNI = pctx.AndroidStaticRule("extractJNI",
+ blueprint.RuleParams{
+ Command: `rm -rf $out $outDir && touch $out && ` +
+ `unzip -qoDD -d $outDir $in "jni/${archString}/*" && ` +
+ `jni_files=$$(find $outDir/jni -type f) && ` +
+ // print error message if there are no JNI libs for this arch
+ `[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
+ `${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
+ `-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
+ CommandDeps: []string{"${config.SoongZipCmd}"},
+ },
+ "outDir", "archString")
+
// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
// touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule.
var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
@@ -860,6 +899,31 @@
ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
ImplementationJars: android.PathsIfNonNil(a.classpathFile),
})
+
+ if proptools.Bool(a.properties.Extract_jni) {
+ for _, t := range ctx.MultiTargets() {
+ arch := t.Arch.Abi[0]
+ path := android.PathForModuleOut(ctx, arch+"_jni.zip")
+ a.jniPackages = append(a.jniPackages, path)
+
+ outDir := android.PathForModuleOut(ctx, "aarForJni")
+ aarPath := android.PathForModuleSrc(ctx, a.properties.Aars[0])
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractJNI,
+ Input: aarPath,
+ Outputs: android.WritablePaths{path},
+ Description: "extract JNI from AAR",
+ Args: map[string]string{
+ "outDir": outDir.String(),
+ "archString": arch,
+ },
+ })
+ }
+
+ ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+ JniPackages: a.jniPackages,
+ })
+ }
}
func (a *AARImport) HeaderJars() android.Paths {
@@ -908,6 +972,6 @@
android.InitPrebuiltModule(module, &module.properties.Aars)
android.InitApexModule(module)
- InitJavaModule(module, android.DeviceSupported)
+ InitJavaModuleMultiTargets(module, android.DeviceSupported)
return module
}
diff --git a/java/aar_test.go b/java/aar_test.go
new file mode 100644
index 0000000..8afa039
--- /dev/null
+++ b/java/aar_test.go
@@ -0,0 +1,83 @@
+// Copyright 2022 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 java
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestAarImportProducesJniPackages(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_library_import {
+ name: "aar-no-jni",
+ aars: ["aary.aar"],
+ }
+ android_library_import {
+ name: "aar-jni",
+ aars: ["aary.aar"],
+ extract_jni: true,
+ }`)
+
+ testCases := []struct {
+ name string
+ hasPackage bool
+ }{
+ {
+ name: "aar-no-jni",
+ hasPackage: false,
+ },
+ {
+ name: "aar-jni",
+ hasPackage: true,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ appMod := ctx.Module(tc.name, "android_common")
+ appTestMod := ctx.ModuleForTests(tc.name, "android_common")
+
+ info, ok := ctx.ModuleProvider(appMod, JniPackageProvider).(JniPackageInfo)
+ if !ok {
+ t.Errorf("expected android_library_import to have JniPackageProvider")
+ }
+
+ if !tc.hasPackage {
+ if len(info.JniPackages) != 0 {
+ t.Errorf("expected JniPackages to be empty, but got %v", info.JniPackages)
+ }
+ outputFile := "arm64-v8a_jni.zip"
+ jniOutputLibZip := appTestMod.MaybeOutput(outputFile)
+ if jniOutputLibZip.Rule != nil {
+ t.Errorf("did not expect an output file, but found %v", outputFile)
+ }
+ return
+ }
+
+ if len(info.JniPackages) != 1 {
+ t.Errorf("expected a single JniPackage, but got %v", info.JniPackages)
+ }
+
+ outputFile := info.JniPackages[0].String()
+ jniOutputLibZip := appTestMod.Output(outputFile)
+ if jniOutputLibZip.Rule == nil {
+ t.Errorf("did not find output file %v", outputFile)
+ }
+ })
+ }
+}
diff --git a/java/app.go b/java/app.go
index 24f269c..5185959 100755
--- a/java/app.go
+++ b/java/app.go
@@ -475,14 +475,14 @@
return a.dexJarFile.PathOrNil()
}
-func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
+func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
var jniJarFile android.WritablePath
- if len(jniLibs) > 0 {
+ if len(jniLibs) > 0 || len(prebuiltJniPackages) > 0 {
a.jniLibs = jniLibs
if a.shouldEmbedJnis(ctx) {
jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
a.installPathForJNISymbols = a.installPath(ctx)
- TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
+ TransformJniLibsToJar(ctx, jniJarFile, jniLibs, prebuiltJniPackages, a.useEmbeddedNativeLibs(ctx))
for _, jni := range jniLibs {
if jni.coverageFile.Valid() {
// Only collect coverage for the first target arch if this is a multilib target.
@@ -626,8 +626,8 @@
dexJarFile := a.dexBuildActions(ctx)
- jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
- jniJarFile := a.jniBuildActions(jniLibs, ctx)
+ jniLibs, prebuiltJniPackages, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+ jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
if ctx.Failed() {
return
@@ -727,9 +727,10 @@
func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
shouldCollectRecursiveNativeDeps bool,
- checkNativeSdkVersion bool) ([]jniLib, []Certificate) {
+ checkNativeSdkVersion bool) ([]jniLib, android.Paths, []Certificate) {
var jniLibs []jniLib
+ var prebuiltJniPackages android.Paths
var certificates []Certificate
seenModulePaths := make(map[string]bool)
@@ -778,6 +779,10 @@
return shouldCollectRecursiveNativeDeps
}
+ if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
+ }
+
if tag == certificateTag {
if dep, ok := module.(*AndroidAppCertificate); ok {
certificates = append(certificates, dep.Certificate)
@@ -789,7 +794,7 @@
return false
})
- return jniLibs, certificates
+ return jniLibs, prebuiltJniPackages, certificates
}
func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
diff --git a/java/app_builder.go b/java/app_builder.go
index 4a18dca..4348644 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -218,8 +218,14 @@
})
}
-func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
- jniLibs []jniLib, uncompressJNI bool) {
+const jniJarOutputPathString = "jniJarOutput.zip"
+
+func TransformJniLibsToJar(
+ ctx android.ModuleContext,
+ outputFile android.WritablePath,
+ jniLibs []jniLib,
+ prebuiltJniPackages android.Paths,
+ uncompressJNI bool) {
var deps android.Paths
jarArgs := []string{
@@ -245,13 +251,20 @@
rule = zipRE
args["implicits"] = strings.Join(deps.Strings(), ",")
}
+ jniJarPath := android.PathForModuleOut(ctx, jniJarOutputPathString)
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "zip jni libs",
- Output: outputFile,
+ Output: jniJarPath,
Implicits: deps,
Args: args,
})
+ ctx.Build(pctx, android.BuildParams{
+ Rule: mergeAssetsRule,
+ Description: "merge prebuilt JNI packages",
+ Inputs: append(prebuiltJniPackages, jniJarPath),
+ Output: outputFile,
+ })
}
func targetToJniDir(target android.Target) string {
diff --git a/java/app_import.go b/java/app_import.go
index b017eca..9d199d6 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -256,7 +256,7 @@
ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
}
- _, certificates := collectAppDeps(ctx, a, false, false)
+ _, _, certificates := collectAppDeps(ctx, a, false, false)
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
diff --git a/java/app_test.go b/java/app_test.go
index c4ac4df..bb44803 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1218,7 +1218,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output("jnilibs.zip")
+ jniLibZip := app.Output(jniJarOutputPathString)
var abis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
@@ -1351,7 +1351,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.MaybeOutput("jnilibs.zip")
+ jniLibZip := app.MaybeOutput(jniJarOutputPathString)
if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
t.Errorf("expected jni packaged %v, got %v", w, g)
}
@@ -1442,7 +1442,7 @@
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.MaybeOutput("jnilibs.zip")
+ jniLibZip := app.MaybeOutput(jniJarOutputPathString)
if len(jniLibZip.Implicits) != 1 {
t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
}
@@ -2425,7 +2425,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output("jnilibs.zip")
+ jniLibZip := app.Output(jniJarOutputPathString)
var jnis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
@@ -3074,3 +3074,89 @@
}
android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
}
+
+func TestAppIncludesJniPackages(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_library_import {
+ name: "aary-nodeps",
+ aars: ["aary.aar"],
+ extract_jni: true,
+ }
+
+ android_library {
+ name: "aary-lib",
+ sdk_version: "current",
+ min_sdk_version: "21",
+ static_libs: ["aary-nodeps"],
+ }
+
+ android_app {
+ name: "aary-lib-dep",
+ sdk_version: "current",
+ min_sdk_version: "21",
+ manifest: "AndroidManifest.xml",
+ static_libs: ["aary-lib"],
+ use_embedded_native_libs: true,
+ }
+
+ android_app {
+ name: "aary-import-dep",
+ sdk_version: "current",
+ min_sdk_version: "21",
+ manifest: "AndroidManifest.xml",
+ static_libs: ["aary-nodeps"],
+ use_embedded_native_libs: true,
+ }
+
+ android_app {
+ name: "aary-no-use-embedded",
+ sdk_version: "current",
+ min_sdk_version: "21",
+ manifest: "AndroidManifest.xml",
+ static_libs: ["aary-nodeps"],
+ }`)
+
+ testCases := []struct {
+ name string
+ hasPackage bool
+ }{
+ {
+ name: "aary-import-dep",
+ hasPackage: true,
+ },
+ {
+ name: "aary-lib-dep",
+ hasPackage: true,
+ },
+ {
+ name: "aary-no-use-embedded",
+ hasPackage: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ app := ctx.ModuleForTests(tc.name, "android_common")
+
+ outputFile := "jnilibs.zip"
+ jniOutputLibZip := app.MaybeOutput(outputFile)
+ if jniOutputLibZip.Rule == nil && !tc.hasPackage {
+ return
+ }
+
+ jniPackage := "arm64-v8a_jni.zip"
+ inputs := jniOutputLibZip.Inputs
+ foundPackage := false
+ for i := 0; i < len(inputs); i++ {
+ if strings.Contains(inputs[i].String(), jniPackage) {
+ foundPackage = true
+ }
+ }
+ if foundPackage != tc.hasPackage {
+ t.Errorf("expected to find %v in %v inputs; inputs = %v", jniPackage, outputFile, inputs)
+ }
+ })
+ }
+}
diff --git a/java/java.go b/java/java.go
index dae69dc..f4ec04e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -24,6 +24,7 @@
"strings"
"android/soong/bazel"
+ "android/soong/bazel/cquery"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -1610,7 +1611,8 @@
}
}
-func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (j *Import) commonBuildActions(ctx android.ModuleContext) {
+ //TODO(b/231322772) these should come from Bazel once available
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
@@ -1621,6 +1623,10 @@
if ctx.Windows() {
j.HideFromMake()
}
+}
+
+func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.commonBuildActions(ctx)
jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
@@ -1662,19 +1668,7 @@
addCLCFromDep(ctx, module, j.classLoaderContexts)
})
- if Bool(j.properties.Installable) {
- var installDir android.InstallPath
- if ctx.InstallInTestcases() {
- var archDir string
- if !ctx.Host() {
- archDir = ctx.DeviceConfig().DeviceArch()
- }
- installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
- } else {
- installDir = android.PathForModuleInstall(ctx, "framework")
- }
- ctx.InstallFile(installDir, jarName, outputFile)
- }
+ j.maybeInstall(ctx, jarName, outputFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
@@ -1748,6 +1742,24 @@
})
}
+func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
+ if !Bool(j.properties.Installable) {
+ return
+ }
+
+ var installDir android.InstallPath
+ if ctx.InstallInTestcases() {
+ var archDir string
+ if !ctx.Host() {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ }
+ ctx.InstallFile(installDir, jarName, outputFile)
+}
+
func (j *Import) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "", ".jar":
@@ -2046,9 +2058,7 @@
return module
}
-//
// Defaults
-//
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
@@ -2063,29 +2073,29 @@
//
// Example:
//
-// java_defaults {
-// name: "example_defaults",
-// srcs: ["common/**/*.java"],
-// javacflags: ["-Xlint:all"],
-// aaptflags: ["--auto-add-overlay"],
-// }
+// java_defaults {
+// name: "example_defaults",
+// srcs: ["common/**/*.java"],
+// javacflags: ["-Xlint:all"],
+// aaptflags: ["--auto-add-overlay"],
+// }
//
-// java_library {
-// name: "example",
-// defaults: ["example_defaults"],
-// srcs: ["example/**/*.java"],
-// }
+// java_library {
+// name: "example",
+// defaults: ["example_defaults"],
+// srcs: ["example/**/*.java"],
+// }
//
// is functionally identical to:
//
-// java_library {
-// name: "example",
-// srcs: [
-// "common/**/*.java",
-// "example/**/*.java",
-// ],
-// javacflags: ["-Xlint:all"],
-// }
+// java_library {
+// name: "example",
+// srcs: [
+// "common/**/*.java",
+// "example/**/*.java",
+// ],
+// javacflags: ["-Xlint:all"],
+// }
func DefaultsFactory() android.Module {
module := &Defaults{}
@@ -2483,5 +2493,54 @@
props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+}
+var _ android.MixedBuildBuildable = (*Import)(nil)
+
+func (i *Import) getBazelModuleLabel(ctx android.BaseModuleContext) string {
+ return android.RemoveOptionalPrebuiltPrefixFromBazelLabel(i.GetBazelLabel(ctx, i))
+}
+
+func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
+ i.commonBuildActions(ctx)
+
+ bazelCtx := ctx.Config().BazelContext
+ filePaths, err := bazelCtx.GetOutputFiles(i.getBazelModuleLabel(ctx), android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+
+ bazelJars := android.Paths{}
+ for _, bazelOutputFile := range filePaths {
+ bazelJars = append(bazelJars, android.PathForBazelOut(ctx, bazelOutputFile))
+ }
+
+ jarName := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ".jar"
+ outputFile := android.PathForModuleOut(ctx, "bazelCombined", jarName)
+ TransformJarsToJar(ctx, outputFile, "combine prebuilt jars", bazelJars,
+ android.OptionalPath{}, // manifest
+ false, // stripDirEntries
+ []string{}, // filesToStrip
+ []string{}, // dirsToStrip
+ )
+ i.combinedClasspathFile = outputFile
+
+ ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
+ ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile),
+ //TODO(b/240308299) include AIDL information from Bazel
+ })
+
+ i.maybeInstall(ctx, jarName, outputFile)
+}
+
+func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(i.getBazelModuleLabel(ctx), cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+ return true
}
diff --git a/java/java_test.go b/java/java_test.go
index 32b0b0f..9e5cf0c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1667,3 +1667,48 @@
})
}
}
+
+func TestImportMixedBuild(t *testing.T) {
+ bp := `
+ java_import {
+ name: "baz",
+ jars: [
+ "test1.jar",
+ "test2.jar",
+ ],
+ bazel_module: { label: "//foo/bar:baz" },
+ }
+ `
+
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToOutputFiles: map[string][]string{
+ "//foo/bar:baz": []string{"test1.jar", "test2.jar"},
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ bazMod := ctx.ModuleForTests("baz", "android_common").Module()
+ producer := bazMod.(android.OutputFileProducer)
+ expectedOutputFiles := []string{".intermediates/baz/android_common/bazelCombined/baz.jar"}
+
+ outputFiles, err := producer.OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting java_import outputfiles %s", err)
+ }
+ actualOutputFiles := android.NormalizePathsForTesting(outputFiles)
+ android.AssertDeepEquals(t, "Output files are produced", expectedOutputFiles, actualOutputFiles)
+
+ javaInfoProvider := ctx.ModuleProvider(bazMod, JavaInfoProvider)
+ javaInfo, ok := javaInfoProvider.(JavaInfo)
+ if !ok {
+ t.Error("could not get JavaInfo from java_import module")
+ }
+ android.AssertDeepEquals(t, "Header JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.HeaderJars))
+ android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
+ android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
+}
diff --git a/java/rro.go b/java/rro.go
index 7952c2c..9c8c53b 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -142,7 +142,7 @@
r.aapt.buildActions(ctx, r, nil, nil, aaptLinkFlags...)
// Sign the built package
- _, certificates := collectAppDeps(ctx, r, 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")
var lineageFile android.Path