Merge "Clear apex.go entries for bluetooth libs" into tm-qpr-dev
diff --git a/android/apex.go b/android/apex.go
index 63cdaaf..20c78ee 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -454,6 +454,7 @@
}
return InList(what, apex_available) ||
(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
+ (what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) ||
(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
}
diff --git a/android/arch.go b/android/arch.go
index f732a7d..cbf77c7 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1832,10 +1832,10 @@
return ret
}
-// firstTarget takes a list of Targets and a list of multilib values and returns a list of Targets
+// FirstTarget takes a list of Targets and a list of multilib values and returns a list of Targets
// that contains zero or one Target for each OsType, selecting the one that matches the earliest
// filter.
-func firstTarget(targets []Target, filters ...string) []Target {
+func FirstTarget(targets []Target, filters ...string) []Target {
// find the first target from each OS
var ret []Target
hasHost := false
@@ -1865,9 +1865,9 @@
case "common_first":
buildTargets = getCommonTargets(targets)
if prefer32 {
- buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...)
+ buildTargets = append(buildTargets, FirstTarget(targets, "lib32", "lib64")...)
} else {
- buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...)
+ buildTargets = append(buildTargets, FirstTarget(targets, "lib64", "lib32")...)
}
case "both":
if prefer32 {
@@ -1883,12 +1883,12 @@
buildTargets = filterMultilibTargets(targets, "lib64")
case "first":
if prefer32 {
- buildTargets = firstTarget(targets, "lib32", "lib64")
+ buildTargets = FirstTarget(targets, "lib32", "lib64")
} else {
- buildTargets = firstTarget(targets, "lib64", "lib32")
+ buildTargets = FirstTarget(targets, "lib64", "lib32")
}
case "first_prefer32":
- buildTargets = firstTarget(targets, "lib32", "lib64")
+ buildTargets = FirstTarget(targets, "lib32", "lib64")
case "prefer32":
buildTargets = filterMultilibTargets(targets, "lib32")
if len(buildTargets) == 0 {
diff --git a/android/config.go b/android/config.go
index 250c312..ba95c5a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -410,7 +410,7 @@
config.BuildOSTarget = config.Targets[config.BuildOS][0]
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
- config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
+ config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
@@ -546,7 +546,7 @@
// Compilation targets for Android.
if len(config.Targets[Android]) > 0 {
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
- config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
+ config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
}
config.BazelContext, err = NewBazelContext(config)
diff --git a/android/deapexer.go b/android/deapexer.go
index 265f531..6a93f60 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -15,6 +15,8 @@
package android
import (
+ "strings"
+
"github.com/google/blueprint"
)
@@ -148,12 +150,19 @@
func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo {
var di *DeapexerInfo
ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
- p := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo)
+ c := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo)
+ p := &c
if di != nil {
+ // If two DeapexerInfo providers have been found then check if they are
+ // equivalent. If they are then use the selected one, otherwise fail.
+ if selected := equivalentDeapexerInfoProviders(di, p); selected != nil {
+ di = selected
+ return
+ }
ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s",
di.ApexModuleName(), p.ApexModuleName())
}
- di = &p
+ di = p
})
if di != nil {
return di
@@ -162,3 +171,33 @@
ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
return nil
}
+
+// removeCompressedApexSuffix removes the _compressed suffix from the name if present.
+func removeCompressedApexSuffix(name string) string {
+ return strings.TrimSuffix(name, "_compressed")
+}
+
+// equivalentDeapexerInfoProviders checks to make sure that the two DeapexerInfo structures are
+// equivalent.
+//
+// At the moment <x> and <x>_compressed APEXes are treated as being equivalent.
+//
+// If they are not equivalent then this returns nil, otherwise, this returns the DeapexerInfo that
+// should be used by the build, which is always the uncompressed one. That ensures that the behavior
+// of the build is not dependent on which prebuilt APEX is visited first.
+func equivalentDeapexerInfoProviders(p1 *DeapexerInfo, p2 *DeapexerInfo) *DeapexerInfo {
+ n1 := removeCompressedApexSuffix(p1.ApexModuleName())
+ n2 := removeCompressedApexSuffix(p2.ApexModuleName())
+
+ // If the names don't match then they are not equivalent.
+ if n1 != n2 {
+ return nil
+ }
+
+ // Select the uncompressed APEX.
+ if n1 == removeCompressedApexSuffix(n1) {
+ return p1
+ } else {
+ return p2
+ }
+}
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 6a5b0da..48c1383 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -105,7 +105,7 @@
if p := base.commonProperties.Effective_package_name; p != nil {
args = append(args,
- "-p "+proptools.NinjaAndShellEscape(*p))
+ `-p "`+proptools.NinjaAndShellEscape(*p)+`"`)
}
args = append(args,
diff --git a/android/makevars.go b/android/makevars.go
index ece7091..a74185a 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -472,7 +472,8 @@
fmt.Fprintf(buf, "\tchmod +x $@\n")
}
if extraFiles := install.extraFiles; extraFiles != nil {
- fmt.Fprintf(buf, "\tunzip -qDD -d '%s' '%s'\n", extraFiles.dir.String(), extraFiles.zip.String())
+ fmt.Fprintf(buf, "\t( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} ) || \\\n", extraFiles.dir.String(), extraFiles.zip.String())
+ fmt.Fprintf(buf, "\t ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )\n")
}
fmt.Fprintln(buf)
}
diff --git a/android/module.go b/android/module.go
index ab68e24..7285a2f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -3208,8 +3208,9 @@
extraCmds := ""
if extraZip != nil {
- extraCmds += fmt.Sprintf(" && unzip -qDD -d '%s' '%s'",
+ extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
extraZip.dir.String(), extraZip.zip.String())
+ extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
implicitDeps = append(implicitDeps, extraZip.zip)
}
diff --git a/android/notices.go b/android/notices.go
index 2a4c17c..b9c1682 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -15,31 +15,97 @@
package android
import (
+ "fmt"
+ "path/filepath"
"strings"
)
-// BuildNoticeTextOutputFromLicenseMetadata writes out a notice text file based on the module's
-// generated license metadata file.
-func BuildNoticeTextOutputFromLicenseMetadata(ctx ModuleContext, outputFile WritablePath) {
- depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
- rule := NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("textnotice").
- FlagWithOutput("-o ", outputFile).
- FlagWithDepFile("-d ", depsFile).
- Input(ctx.Module().base().licenseMetadataFile)
- rule.Build("text_notice", "container notice file")
+func modulesOutputDirs(ctx BuilderContext, modules ...Module) []string {
+ dirs := make([]string, 0, len(modules))
+ for _, module := range modules {
+ paths, err := outputFilesForModule(ctx, module, "")
+ if err != nil {
+ continue
+ }
+ for _, path := range paths {
+ if path != nil {
+ dirs = append(dirs, filepath.Dir(path.String()))
+ }
+ }
+ }
+ return SortedUniqueStrings(dirs)
}
-// BuildNoticeHtmlOutputFromLicenseMetadata writes out a notice text file based on the module's
-// generated license metadata file.
-func BuildNoticeHtmlOutputFromLicenseMetadata(ctx ModuleContext, outputFile WritablePath) {
+func modulesLicenseMetadata(ctx BuilderContext, modules ...Module) Paths {
+ result := make(Paths, 0, len(modules))
+ for _, module := range modules {
+ if mf := module.base().licenseMetadataFile; mf != nil {
+ result = append(result, mf)
+ }
+ }
+ return result
+}
+
+// buildNoticeOutputFromLicenseMetadata writes out a notice file.
+func buildNoticeOutputFromLicenseMetadata(
+ ctx BuilderContext, tool, ruleName string, outputFile WritablePath,
+ libraryName string, stripPrefix []string, modules ...Module) {
depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
rule := NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("htmlnotice").
+ if len(modules) == 0 {
+ if mctx, ok := ctx.(ModuleContext); ok {
+ modules = []Module{mctx.Module()}
+ } else {
+ panic(fmt.Errorf("%s %q needs a module to generate the notice for", ruleName, libraryName))
+ }
+ }
+ if libraryName == "" {
+ libraryName = modules[0].Name()
+ }
+ cmd := rule.Command().
+ BuiltTool(tool).
FlagWithOutput("-o ", outputFile).
- FlagWithDepFile("-d ", depsFile).
- Input(ctx.Module().base().licenseMetadataFile)
- rule.Build("html_notice", "container notice file")
+ FlagWithDepFile("-d ", depsFile)
+ if len(stripPrefix) > 0 {
+ cmd = cmd.FlagForEachArg("--strip_prefix ", stripPrefix)
+ }
+ outputs := modulesOutputDirs(ctx, modules...)
+ if len(outputs) > 0 {
+ cmd = cmd.FlagForEachArg("--strip_prefix ", outputs)
+ }
+ if libraryName != "" {
+ cmd = cmd.FlagWithArg("--product ", libraryName)
+ }
+ cmd = cmd.Inputs(modulesLicenseMetadata(ctx, modules...))
+ rule.Build(ruleName, "container notice file")
+}
+
+// BuildNoticeTextOutputFromLicenseMetadata writes out a notice text file based
+// on the license metadata files for the input `modules` defaulting to the
+// current context module if none given.
+func BuildNoticeTextOutputFromLicenseMetadata(
+ ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ stripPrefix []string, modules ...Module) {
+ buildNoticeOutputFromLicenseMetadata(ctx, "textnotice", "text_notice_"+ruleName,
+ outputFile, libraryName, stripPrefix, modules...)
+}
+
+// BuildNoticeHtmlOutputFromLicenseMetadata writes out a notice text file based
+// on the license metadata files for the input `modules` defaulting to the
+// current context module if none given.
+func BuildNoticeHtmlOutputFromLicenseMetadata(
+ ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ stripPrefix []string, modules ...Module) {
+ buildNoticeOutputFromLicenseMetadata(ctx, "htmlnotice", "html_notice_"+ruleName,
+ outputFile, libraryName, stripPrefix, modules...)
+}
+
+// BuildNoticeXmlOutputFromLicenseMetadata writes out a notice text file based
+// on the license metadata files for the input `modules` defaulting to the
+// current context module if none given.
+func BuildNoticeXmlOutputFromLicenseMetadata(
+ ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ stripPrefix []string, modules ...Module) {
+ buildNoticeOutputFromLicenseMetadata(ctx, "xmlnotice", "xml_notice_"+ruleName,
+ outputFile, libraryName, stripPrefix, modules...)
}
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index f050a2e..280dae8 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -107,6 +107,7 @@
func (s *sdkRepoHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
dir := android.PathForModuleOut(ctx, "zip")
+ outputZipFile := dir.Join(ctx, "output.zip")
builder := android.NewRuleBuilder(pctx, ctx).
Sbox(dir, android.PathForModuleOut(ctx, "out.sbox.textproto")).
SandboxInputs()
@@ -123,7 +124,12 @@
s.CopySpecsToDir(ctx, builder, packageSpecs, dir)
noticeFile := android.PathForModuleOut(ctx, "NOTICES.txt")
- android.BuildNoticeTextOutputFromLicenseMetadata(ctx, noticeFile)
+ android.BuildNoticeTextOutputFromLicenseMetadata(
+ ctx, noticeFile, "", "",
+ []string{
+ android.PathForModuleInstall(ctx, "sdk-repo").String() + "/",
+ outputZipFile.String(),
+ })
builder.Command().Text("cp").
Input(noticeFile).
Text(filepath.Join(dir.String(), "NOTICE.txt"))
@@ -209,7 +215,6 @@
}
// Zip up our temporary directory as the sdk-repo
- outputZipFile := dir.Join(ctx, "output.zip")
builder.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", outputZipFile).
diff --git a/apex/apex.go b/apex/apex.go
index 66a98c0..56ccd15 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2775,6 +2775,36 @@
//
// Module separator
//
+ m["com.android.btservices"] = []string{
+ "bluetooth-protos-lite",
+ "internal_include_headers",
+ "libaudio-a2dp-hw-utils",
+ "libaudio-hearing-aid-hw-utils",
+ "libbluetooth",
+ "libbluetooth-types",
+ "libbluetooth-types-header",
+ "libbluetooth_gd",
+ "libbluetooth_headers",
+ "libbluetooth_jni",
+ "libbt-audio-hal-interface",
+ "libbt-bta",
+ "libbt-common",
+ "libbt-hci",
+ "libbt-platform-protos-lite",
+ "libbt-protos-lite",
+ "libbt-sbc-decoder",
+ "libbt-sbc-encoder",
+ "libbt-stack",
+ "libbt-utils",
+ "libbtcore",
+ "libbtdevice",
+ "libbte",
+ "libbtif",
+ "libchrome",
+ }
+ //
+ // Module separator
+ //
m["com.android.bluetooth"] = []string{
// empty
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index bcb55af..b3036b1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7428,7 +7428,7 @@
return result.TestContext
}
-func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) {
+func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
preparers := android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
PrepareForTestWithApexBuildComponents,
@@ -7497,6 +7497,107 @@
})
}
+func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithApexBuildComponents,
+ )
+
+ bpBase := `
+ apex_set {
+ name: "com.android.myapex",
+ installable: true,
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ set: "myapex.apks",
+ }
+
+ apex_set {
+ name: "com.android.myapex_compressed",
+ apex_name: "com.android.myapex",
+ installable: true,
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ set: "myapex_compressed.apks",
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ apex_available: [
+ "com.android.myapex",
+ "com.android.myapex_compressed",
+ ],
+ hidden_api: {
+ annotation_flags: "annotation-flags.csv",
+ metadata: "metadata.csv",
+ index: "index.csv",
+ signature_patterns: "signature_patterns.csv",
+ },
+ %s
+ }
+ `
+
+ t.Run("java_import", func(t *testing.T) {
+ result := preparers.RunTestWithBp(t,
+ fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: [
+ "com.android.myapex",
+ "com.android.myapex_compressed",
+ ],
+ }
+ `)
+
+ module := result.Module("libfoo", "android_common_com.android.myapex")
+ usesLibraryDep := module.(java.UsesLibraryDependency)
+ android.AssertPathRelativeToTopEquals(t, "dex jar path",
+ "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
+ usesLibraryDep.DexJarBuildPath().Path())
+ })
+
+ t.Run("java_sdk_library_import", func(t *testing.T) {
+ result := preparers.RunTestWithBp(t,
+ fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
+ java_sdk_library_import {
+ name: "libfoo",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: [
+ "com.android.myapex",
+ "com.android.myapex_compressed",
+ ],
+ compile_dex: true,
+ }
+ `)
+
+ module := result.Module("libfoo", "android_common_com.android.myapex")
+ usesLibraryDep := module.(java.UsesLibraryDependency)
+ android.AssertPathRelativeToTopEquals(t, "dex jar path",
+ "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
+ usesLibraryDep.DexJarBuildPath().Path())
+ })
+
+ t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
+ _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
+ image_name: "art",
+ contents: ["libfoo"],
+ `)+`
+ java_sdk_library_import {
+ name: "libfoo",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: [
+ "com.android.myapex",
+ "com.android.myapex_compressed",
+ ],
+ compile_dex: true,
+ }
+ `)
+ })
+}
+
func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
apex {
diff --git a/apex/builder.go b/apex/builder.go
index abbf8ad..a21fcb8 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -618,7 +618,12 @@
// Create a NOTICE file, and embed it as an asset file in the APEX.
a.htmlGzNotice = android.PathForModuleOut(ctx, "NOTICE.html.gz")
- android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, a.htmlGzNotice)
+ android.BuildNoticeHtmlOutputFromLicenseMetadata(
+ ctx, a.htmlGzNotice, "", "",
+ []string{
+ android.PathForModuleInstall(ctx).String() + "/",
+ android.PathForModuleInPartitionInstall(ctx, "apex").String() + "/",
+ })
noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("cp").
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index dfe143f..66087e6 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -33,9 +33,7 @@
},
"armv8-a-branchprot": []string{
"-march=armv8-a",
- // Disable BTI until drm vendors stop using OS libraries as sources
- // of gadgets (https://issuetracker.google.com/216395195).
- "-mbranch-protection=pac-ret",
+ "-mbranch-protection=standard",
},
"armv8-2a": []string{
"-march=armv8.2-a",
diff --git a/java/app.go b/java/app.go
index d2eb357..41419ba 100755
--- a/java/app.go
+++ b/java/app.go
@@ -587,20 +587,18 @@
}
a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
+ a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
+ var noticeAssetPath android.WritablePath
if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
- noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
- android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, noticeFile)
- noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().Text("cp").
- Input(noticeFile).
- Output(noticeAssetPath)
- builder.Build("notice_dir", "Building notice dir")
+ // The rule to create the notice file can't be generated yet, as the final output path
+ // for the apk isn't known yet. Add the path where the notice file will be generated to the
+ // aapt rules now before calling aaptBuildActions, the rule to create the notice file will
+ // be generated later.
+ noticeAssetPath = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
}
- a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
-
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
@@ -675,6 +673,23 @@
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
}
+ if a.aapt.noticeFile.Valid() {
+ // Generating the notice file rule has to be here after a.outputFile is known.
+ noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
+ android.BuildNoticeHtmlOutputFromLicenseMetadata(
+ ctx, noticeFile, "", "",
+ []string{
+ a.installDir.String() + "/",
+ android.PathForModuleInstall(ctx).String() + "/",
+ a.outputFile.String(),
+ })
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("cp").
+ Input(noticeFile).
+ Output(noticeAssetPath)
+ builder.Build("notice_dir", "Building notice dir")
+ }
+
for _, split := range a.aapt.splits {
// Sign the split APKs
packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk")
diff --git a/java/java.go b/java/java.go
index b34d6de..c8fb93c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -855,7 +855,25 @@
Data_native_bins []string `android:"arch_variant"`
// list of device binary modules that should be installed alongside the test
- Data_device_bins []string `android:"arch_variant"`
+ // This property only adds the first variant of the dependency
+ Data_device_bins_first []string `android:"arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test
+ // This property adds 64bit AND 32bit variants of the dependency
+ Data_device_bins_both []string `android:"arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test
+ // This property only adds 64bit variants of the dependency
+ Data_device_bins_64 []string `android:"arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test
+ // This property adds 32bit variants of the dependency if available, or else
+ // defaults to the 64bit variant
+ Data_device_bins_prefer32 []string `android:"arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test
+ // This property only adds 32bit variants of the dependency
+ Data_device_bins_32 []string `android:"arch_variant"`
}
type testHelperLibraryProperties struct {
@@ -922,6 +940,83 @@
return true
}
+func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
+ if len(j.testHostProperties.Data_device_bins_first) > 0 {
+ deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
+ ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_first...)
+ }
+
+ var maybeAndroid32Target *android.Target
+ var maybeAndroid64Target *android.Target
+ android32TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib32")
+ android64TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib64")
+ if len(android32TargetList) > 0 {
+ maybeAndroid32Target = &android32TargetList[0]
+ }
+ if len(android64TargetList) > 0 {
+ maybeAndroid64Target = &android64TargetList[0]
+ }
+
+ if len(j.testHostProperties.Data_device_bins_both) > 0 {
+ if maybeAndroid32Target == nil && maybeAndroid64Target == nil {
+ ctx.PropertyErrorf("data_device_bins_both", "no device targets available. Targets: %q", ctx.Config().Targets)
+ return
+ }
+ if maybeAndroid32Target != nil {
+ ctx.AddFarVariationDependencies(
+ maybeAndroid32Target.Variations(),
+ dataDeviceBinsTag,
+ j.testHostProperties.Data_device_bins_both...,
+ )
+ }
+ if maybeAndroid64Target != nil {
+ ctx.AddFarVariationDependencies(
+ maybeAndroid64Target.Variations(),
+ dataDeviceBinsTag,
+ j.testHostProperties.Data_device_bins_both...,
+ )
+ }
+ }
+
+ if len(j.testHostProperties.Data_device_bins_prefer32) > 0 {
+ if maybeAndroid32Target != nil {
+ ctx.AddFarVariationDependencies(
+ maybeAndroid32Target.Variations(),
+ dataDeviceBinsTag,
+ j.testHostProperties.Data_device_bins_prefer32...,
+ )
+ } else {
+ if maybeAndroid64Target == nil {
+ ctx.PropertyErrorf("data_device_bins_prefer32", "no device targets available. Targets: %q", ctx.Config().Targets)
+ return
+ }
+ ctx.AddFarVariationDependencies(
+ maybeAndroid64Target.Variations(),
+ dataDeviceBinsTag,
+ j.testHostProperties.Data_device_bins_prefer32...,
+ )
+ }
+ }
+
+ if len(j.testHostProperties.Data_device_bins_32) > 0 {
+ if maybeAndroid32Target == nil {
+ ctx.PropertyErrorf("data_device_bins_32", "cannot find 32bit device target. Targets: %q", ctx.Config().Targets)
+ return
+ }
+ deviceVariations := maybeAndroid32Target.Variations()
+ ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_32...)
+ }
+
+ if len(j.testHostProperties.Data_device_bins_64) > 0 {
+ if maybeAndroid64Target == nil {
+ ctx.PropertyErrorf("data_device_bins_64", "cannot find 64bit device target. Targets: %q", ctx.Config().Targets)
+ return
+ }
+ deviceVariations := maybeAndroid64Target.Variations()
+ ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_64...)
+ }
+}
+
func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
if len(j.testHostProperties.Data_native_bins) > 0 {
for _, target := range ctx.MultiTargets() {
@@ -929,11 +1024,6 @@
}
}
- if len(j.testHostProperties.Data_device_bins) > 0 {
- deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
- ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins...)
- }
-
if len(j.testProperties.Jni_libs) > 0 {
for _, target := range ctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
@@ -941,6 +1031,8 @@
}
}
+ j.addDataDeviceBinsDeps(ctx)
+
j.deps(ctx)
}
@@ -948,17 +1040,40 @@
j.extraResources = append(j.extraResources, p)
}
+func (j *TestHost) dataDeviceBins() []string {
+ ret := make([]string, 0,
+ len(j.testHostProperties.Data_device_bins_first)+
+ len(j.testHostProperties.Data_device_bins_both)+
+ len(j.testHostProperties.Data_device_bins_prefer32)+
+ len(j.testHostProperties.Data_device_bins_32)+
+ len(j.testHostProperties.Data_device_bins_64),
+ )
+
+ ret = append(ret, j.testHostProperties.Data_device_bins_first...)
+ ret = append(ret, j.testHostProperties.Data_device_bins_both...)
+ ret = append(ret, j.testHostProperties.Data_device_bins_prefer32...)
+ ret = append(ret, j.testHostProperties.Data_device_bins_32...)
+ ret = append(ret, j.testHostProperties.Data_device_bins_64...)
+
+ return ret
+}
+
func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var configs []tradefed.Config
- if len(j.testHostProperties.Data_device_bins) > 0 {
+ dataDeviceBins := j.dataDeviceBins()
+ if len(dataDeviceBins) > 0 {
// add Tradefed configuration to push device bins to device for testing
remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name())
options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
- for _, bin := range j.testHostProperties.Data_device_bins {
+ for _, bin := range dataDeviceBins {
fullPath := filepath.Join(remoteDir, bin)
options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath})
}
- configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
+ configs = append(configs, tradefed.Object{
+ Type: "target_preparer",
+ Class: "com.android.tradefed.targetprep.PushFilePreparer",
+ Options: options,
+ })
}
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
diff --git a/java/java_test.go b/java/java_test.go
index 4c93824..af889cc 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1498,62 +1498,172 @@
}
func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
- bp := `
- java_test_host {
- name: "foo",
- srcs: ["test.java"],
- data_device_bins: ["bar"],
- }
-
- cc_binary {
- name: "bar",
- }
- `
-
- ctx := android.GroupFixturePreparers(
- PrepareForIntegrationTestWithJava,
- ).RunTestWithBp(t, bp)
-
- buildOS := ctx.Config.BuildOS.String()
- fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
- barVariant := ctx.ModuleForTests("bar", "android_arm64_armv8-a")
- fooMod := fooVariant.Module().(*TestHost)
-
- relocated := barVariant.Output("bar")
- expectedInput := "out/soong/.intermediates/bar/android_arm64_armv8-a/unstripped/bar"
- android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
-
- entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
- expectedData := []string{
- "out/soong/.intermediates/bar/android_arm64_armv8-a/bar:bar",
+ testCases := []struct {
+ dataDeviceBinType string
+ depCompileMultilib string
+ variants []string
+ expectedError string
+ }{
+ {
+ dataDeviceBinType: "first",
+ depCompileMultilib: "first",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ dataDeviceBinType: "first",
+ depCompileMultilib: "both",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ // this is true because our testing framework is set up with
+ // Targets ~ [<64bit target>, <32bit target>], where 64bit is "first"
+ dataDeviceBinType: "first",
+ depCompileMultilib: "32",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "first",
+ depCompileMultilib: "64",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ dataDeviceBinType: "both",
+ depCompileMultilib: "both",
+ variants: []string{
+ "android_arm_armv7-a-neon",
+ "android_arm64_armv8-a",
+ },
+ },
+ {
+ dataDeviceBinType: "both",
+ depCompileMultilib: "32",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "both",
+ depCompileMultilib: "64",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "both",
+ depCompileMultilib: "first",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "32",
+ depCompileMultilib: "32",
+ variants: []string{"android_arm_armv7-a-neon"},
+ },
+ {
+ dataDeviceBinType: "32",
+ depCompileMultilib: "first",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "32",
+ depCompileMultilib: "both",
+ variants: []string{"android_arm_armv7-a-neon"},
+ },
+ {
+ dataDeviceBinType: "32",
+ depCompileMultilib: "64",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "64",
+ depCompileMultilib: "64",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ dataDeviceBinType: "64",
+ depCompileMultilib: "both",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ dataDeviceBinType: "64",
+ depCompileMultilib: "first",
+ variants: []string{"android_arm64_armv8-a"},
+ },
+ {
+ dataDeviceBinType: "64",
+ depCompileMultilib: "32",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "prefer32",
+ depCompileMultilib: "32",
+ variants: []string{"android_arm_armv7-a-neon"},
+ },
+ {
+ dataDeviceBinType: "prefer32",
+ depCompileMultilib: "both",
+ variants: []string{"android_arm_armv7-a-neon"},
+ },
+ {
+ dataDeviceBinType: "prefer32",
+ depCompileMultilib: "first",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
+ {
+ dataDeviceBinType: "prefer32",
+ depCompileMultilib: "64",
+ expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
+ },
}
- actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
- android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
-}
-func TestDataDeviceBinsAutogenTradefedConfig(t *testing.T) {
- bp := `
+ bpTemplate := `
java_test_host {
name: "foo",
srcs: ["test.java"],
- data_device_bins: ["bar"],
+ data_device_bins_%s: ["bar"],
}
cc_binary {
name: "bar",
+ compile_multilib: "%s",
}
`
- ctx := android.GroupFixturePreparers(
- PrepareForIntegrationTestWithJava,
- ).RunTestWithBp(t, bp)
+ for _, tc := range testCases {
+ bp := fmt.Sprintf(bpTemplate, tc.dataDeviceBinType, tc.depCompileMultilib)
- buildOS := ctx.Config.BuildOS.String()
- fooModule := ctx.ModuleForTests("foo", buildOS+"_common")
- expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+ errorHandler := android.FixtureExpectsNoErrors
+ if tc.expectedError != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
+ }
- autogen := fooModule.Rule("autogen")
- if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
- t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
+ testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib)
+ t.Run(testName, func(t *testing.T) {
+ ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+ if tc.expectedError != "" {
+ return
+ }
+
+ buildOS := ctx.Config.BuildOS.String()
+ fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
+ fooMod := fooVariant.Module().(*TestHost)
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
+
+ expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+ autogen := fooVariant.Rule("autogen")
+ if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
+ t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
+ }
+
+ expectedData := []string{}
+ for _, variant := range tc.variants {
+ barVariant := ctx.ModuleForTests("bar", variant)
+ relocated := barVariant.Output("bar")
+ expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant)
+ android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
+
+ expectedData = append(expectedData, fmt.Sprintf("out/soong/.intermediates/bar/%s/bar:bar", variant))
+ }
+
+ actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
+ android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
+ })
}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index cd8e875..47ffc6a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2584,7 +2584,10 @@
`"current" is not an allowed value for this attribute`)
return ""
}
- return formattedOptionalAttribute(attrName, value)
+ // "safeValue" is safe because it translates finalized codenames to a string
+ // with their SDK int.
+ safeValue := apiLevel.String()
+ return formattedOptionalAttribute(attrName, &safeValue)
}
// formats an attribute for the xml permissions file if the value is not null