Merge "Extract PrepareForTestWithJavaSdkLibraryFiles from javaMockFS()"
diff --git a/android/apex.go b/android/apex.go
index a014592..79d8cdd 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -719,6 +719,8 @@
// Generate two module out files:
// 1. FullList with transitive deps and their parents in the dep graph
// 2. FlatList with a flat list of transitive deps
+// In both cases transitive deps of external deps are not included. Neither are deps that are only
+// available to APEXes; they are developed with updatability in mind and don't need manual approval.
func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
var fullContent strings.Builder
var flatContent strings.Builder
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3fde144..dd290d3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -127,6 +127,8 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
+var emptyFixtureFactory = android.NewFixtureFactory(&buildDir)
+
var apexFixtureFactory = android.NewFixtureFactory(
&buildDir,
// General preparers in alphabetical order as test infrastructure will enforce correct
@@ -520,7 +522,7 @@
}
rust_binary {
- name: "foo.rust",
+ name: "foo.rust",
srcs: ["foo.rs"],
rlibs: ["libfoo.rlib.rust"],
dylibs: ["libfoo.dylib.rust"],
@@ -528,14 +530,14 @@
}
rust_library_rlib {
- name: "libfoo.rlib.rust",
+ name: "libfoo.rlib.rust",
srcs: ["foo.rs"],
crate_name: "foo",
apex_available: ["myapex"],
}
rust_library_dylib {
- name: "libfoo.dylib.rust",
+ name: "libfoo.dylib.rust",
srcs: ["foo.rs"],
crate_name: "foo",
apex_available: ["myapex"],
@@ -730,14 +732,12 @@
fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex")
- ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex")
ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar")
ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
- ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)")
@@ -1236,13 +1236,9 @@
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
- ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex2")
- ensureListContains(t, fullDepsInfo, " libbaz(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib")
flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
- ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))")
- ensureListContains(t, flatDepsInfo, "libbaz(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
}
@@ -1316,9 +1312,10 @@
}
-func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
- ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
- bp := `
+var prepareForTestOfRuntimeApexWithHwasan = android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcBuildComponents,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureAddTextFile("bionic/apex/Android.bp", `
apex {
name: "com.android.runtime",
key: "com.android.runtime.key",
@@ -1331,7 +1328,12 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
+ `),
+ android.FixtureAddFile("system/sepolicy/apex/com.android.runtime-file_contexts", nil),
+)
+func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
+ result := emptyFixtureFactory.Extend(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
cc_library {
name: "libc",
no_libcrt: true,
@@ -1358,12 +1360,8 @@
sanitize: {
never: true,
},
- }
- `
- // override bp to use hard-coded names: com.android.runtime and libc
- fs["Android.bp"] = []byte(bp)
- fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil
- })
+ } `)
+ ctx := result.TestContext
ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
"lib64/bionic/libc.so",
@@ -1381,21 +1379,12 @@
}
func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
- ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
- bp := `
- apex {
- name: "com.android.runtime",
- key: "com.android.runtime.key",
- native_shared_libs: ["libc"],
- updatable: false,
- }
-
- apex_key {
- name: "com.android.runtime.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
+ result := emptyFixtureFactory.Extend(
+ prepareForTestOfRuntimeApexWithHwasan,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"hwaddress"}
+ }),
+ ).RunTestWithBp(t, `
cc_library {
name: "libc",
no_libcrt: true,
@@ -1419,13 +1408,8 @@
never: true,
},
}
- `
- // override bp to use hard-coded names: com.android.runtime and libc
- fs["Android.bp"] = []byte(bp)
- fs["system/sepolicy/apex/com.android.runtime-file_contexts"] = nil
-
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- })
+ `)
+ ctx := result.TestContext
ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
"lib64/bionic/libc.so",
@@ -2049,7 +2033,7 @@
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "core_platform",
+ sdk_version: "test_current",
apex_available: ["myapex"],
}
`,
@@ -2096,13 +2080,16 @@
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "core_platform",
+ sdk_version: "test_current",
apex_available: ["myapex"],
}
`,
},
{
- name: "Updatable apex with non-stable transitive dep",
+ name: "Updatable apex with non-stable transitive dep",
+ // This is not actually detecting that the transitive dependency is unstable, rather it is
+ // detecting that the transitive dependency is building against a wider API surface than the
+ // module that depends on it is using.
expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against private API.",
bp: `
apex {
diff --git a/apex/builder.go b/apex/builder.go
index 2663a67..da800d4 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -926,9 +926,15 @@
return !externalDep
}
+ // Skip dependencies that are only available to APEXes; they are developed with updatability
+ // in mind and don't need manual approval.
+ if to.(android.ApexModule).NotAvailableForPlatform() {
+ return !externalDep
+ }
+
depTag := ctx.OtherModuleDependencyTag(to)
+ // Check to see if dependency been marked to skip the dependency check
if skipDepCheck, ok := depTag.(android.SkipApexAllowedDependenciesCheck); ok && skipDepCheck.SkipApexAllowedDependenciesCheck() {
- // Check to see if dependency been marked to skip the dependency check
return !externalDep
}
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 117fd46..b7c185a 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -12,6 +12,7 @@
],
testSrcs: [
"aquery_test.go",
+ "properties_test.go",
],
pluginFor: [
"soong_build",
diff --git a/bazel/properties.go b/bazel/properties.go
index a5ffa55..cb47758 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,7 +14,10 @@
package bazel
-import "fmt"
+import (
+ "fmt"
+ "sort"
+)
type bazelModuleProperties struct {
// The label of the Bazel target replacing this Soong module.
@@ -66,6 +69,28 @@
}
}
+func UniqueBazelLabels(originalLabels []Label) []Label {
+ uniqueLabelsSet := make(map[Label]bool)
+ for _, l := range originalLabels {
+ uniqueLabelsSet[l] = true
+ }
+ var uniqueLabels []Label
+ for l, _ := range uniqueLabelsSet {
+ uniqueLabels = append(uniqueLabels, l)
+ }
+ sort.SliceStable(uniqueLabels, func(i, j int) bool {
+ return uniqueLabels[i].Label < uniqueLabels[j].Label
+ })
+ return uniqueLabels
+}
+
+func UniqueBazelLabelList(originalLabelList LabelList) LabelList {
+ var uniqueLabelList LabelList
+ uniqueLabelList.Includes = UniqueBazelLabels(originalLabelList.Includes)
+ uniqueLabelList.Excludes = UniqueBazelLabels(originalLabelList.Excludes)
+ return uniqueLabelList
+}
+
// StringListAttribute corresponds to the string_list Bazel attribute type with
// support for additional metadata, like configurations.
type StringListAttribute struct {
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
new file mode 100644
index 0000000..0fcb904
--- /dev/null
+++ b/bazel/properties_test.go
@@ -0,0 +1,89 @@
+// Copyright 2021 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 bazel
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestUniqueBazelLabels(t *testing.T) {
+ testCases := []struct {
+ originalLabels []Label
+ expectedUniqueLabels []Label
+ }{
+ {
+ originalLabels: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "a"},
+ {Label: "c"},
+ },
+ expectedUniqueLabels: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "c"},
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabels := UniqueBazelLabels(tc.originalLabels)
+ if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels)
+ }
+ }
+}
+
+func TestUniqueBazelLabelList(t *testing.T) {
+ testCases := []struct {
+ originalLabelList LabelList
+ expectedUniqueLabelList LabelList
+ }{
+ {
+ originalLabelList: LabelList{
+ Includes: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "a"},
+ {Label: "c"},
+ },
+ Excludes: []Label{
+ {Label: "x"},
+ {Label: "x"},
+ {Label: "y"},
+ {Label: "z"},
+ },
+ },
+ expectedUniqueLabelList: LabelList{
+ Includes: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "c"},
+ },
+ Excludes: []Label{
+ {Label: "x"},
+ {Label: "y"},
+ {Label: "z"},
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabelList := UniqueBazelLabelList(tc.originalLabelList)
+ if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
+ }
+ }
+}
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 876e189..372a610 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -62,6 +62,10 @@
// Optional kernel commandline
Cmdline *string
+ // File that contains bootconfig parameters. This can be set only when `vendor_boot` is true
+ // and `header_version` is greater than or equal to 4.
+ Bootconfig *string `android:"arch_variant,path"`
+
// When set to true, sign the image with avbtool. Default is false.
Use_avb *bool
@@ -189,6 +193,19 @@
return output
}
+ bootconfig := proptools.String(b.properties.Bootconfig)
+ if bootconfig != "" {
+ if !vendor {
+ ctx.PropertyErrorf("bootconfig", "requires vendor_boot: true")
+ return output
+ }
+ if verNum < 4 {
+ ctx.PropertyErrorf("bootconfig", "requires header_version: 4 or later")
+ return output
+ }
+ cmd.FlagWithInput("--vendor_bootconfig ", android.PathForModuleSrc(ctx, bootconfig))
+ }
+
flag := "--output "
if vendor {
flag = "--vendor_boot "
diff --git a/java/app.go b/java/app.go
index e98fe31..eef627c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -812,6 +812,13 @@
depsInfo := android.DepNameToDepInfoMap{}
a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
depName := to.Name()
+
+ // Skip dependencies that are only available to APEXes; they are developed with updatability
+ // in mind and don't need manual approval.
+ if to.(android.ApexModule).NotAvailableForPlatform() {
+ return true
+ }
+
if info, exist := depsInfo[depName]; exist {
info.From = append(info.From, from.Name())
info.IsExternal = info.IsExternal && externalDep
diff --git a/java/java.go b/java/java.go
index 567ebbb..036c7af 100644
--- a/java/java.go
+++ b/java/java.go
@@ -122,7 +122,16 @@
if sdkVersion.stable() {
return nil
}
- return fmt.Errorf("non stable SDK %v", sdkVersion)
+ if sdkVersion.kind == sdkCorePlatform {
+ if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
+ return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
+ } else {
+ // Treat stable core platform as stable.
+ return nil
+ }
+ } else {
+ return fmt.Errorf("non stable SDK %v", sdkVersion)
+ }
}
func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 874338d..cae9dc5 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -108,7 +108,7 @@
"PrintSpooler",
"RollbackTest",
"service-blobstore",
- "service-connectivity",
+ "service-connectivity-pre-jarjar",
"service-jobscheduler",
"services",
"services.accessibility",
@@ -160,7 +160,11 @@
}
func useLegacyCorePlatformApi(ctx android.EarlyModuleContext) bool {
- _, found := legacyCorePlatformApiLookup[ctx.ModuleName()]
+ return useLegacyCorePlatformApiByName(ctx.ModuleName())
+}
+
+func useLegacyCorePlatformApiByName(name string) bool {
+ _, found := legacyCorePlatformApiLookup[name]
return found
}
diff --git a/rust/builder.go b/rust/builder.go
index 6326124..9d462d4 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -194,8 +194,7 @@
}
if len(deps.SrcDeps) > 0 {
- genSubDir := "out/"
- moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
+ moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
var outputs android.WritablePaths
for _, genSrc := range deps.SrcDeps {
@@ -208,7 +207,7 @@
ctx.Build(pctx, android.BuildParams{
Rule: cp,
- Description: "cp " + moduleGenDir.Rel(),
+ Description: "cp " + moduleGenDir.Path().Rel(),
Outputs: outputs,
Inputs: deps.SrcDeps,
Args: map[string]string{
diff --git a/rust/compiler.go b/rust/compiler.go
index c26f208..98ad7ad 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -60,6 +60,7 @@
InstallInData = iota
incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
+ genSubDir = "out/"
)
type BaseCompilerProperties struct {
@@ -154,6 +155,10 @@
distFile android.OptionalPath
// Stripped output file. If Valid(), this file will be installed instead of outputFile.
strippedOutputFile android.OptionalPath
+
+ // If a crate has a source-generated dependency, a copy of the source file
+ // will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
+ cargoOutDir android.ModuleOutPath
}
func (compiler *baseCompiler) Disabled() bool {
@@ -243,6 +248,14 @@
panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
}
+func (compiler *baseCompiler) initialize(ctx ModuleContext) {
+ compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir)
+}
+
+func (compiler *baseCompiler) CargoOutDir() android.OptionalPath {
+ return android.OptionalPathForPath(compiler.cargoOutDir)
+}
+
func (compiler *baseCompiler) isDependencyRoot() bool {
return false
}
diff --git a/rust/project_json.go b/rust/project_json.go
index 32ce6f4..8d3d250 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -45,11 +45,12 @@
}
type rustProjectCrate struct {
- DisplayName string `json:"display_name"`
- RootModule string `json:"root_module"`
- Edition string `json:"edition,omitempty"`
- Deps []rustProjectDep `json:"deps"`
- Cfgs []string `json:"cfgs"`
+ DisplayName string `json:"display_name"`
+ RootModule string `json:"root_module"`
+ Edition string `json:"edition,omitempty"`
+ Deps []rustProjectDep `json:"deps"`
+ Cfgs []string `json:"cfgs"`
+ Env map[string]string `json:"env"`
}
type rustProjectJson struct {
@@ -136,7 +137,7 @@
}
})
if !foundSource {
- fmt.Errorf("No valid source for source provider found: %v\n", rModule)
+ ctx.Errorf("No valid source for source provider found: %v\n", rModule)
}
return sourceSrc, foundSource
}
@@ -220,7 +221,7 @@
func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (int, bool) {
rootModule, ok := crateSource(ctx, rModule, comp)
if !ok {
- fmt.Errorf("Unable to find source for valid module: %v", rModule)
+ ctx.Errorf("Unable to find source for valid module: %v", rModule)
return 0, false
}
@@ -230,6 +231,11 @@
Edition: comp.edition(),
Deps: make([]rustProjectDep, 0),
Cfgs: make([]string, 0),
+ Env: make(map[string]string),
+ }
+
+ if comp.CargoOutDir().Valid() {
+ crate.Env["OUT_DIR"] = comp.CargoOutDir().String()
}
deps := make(map[string]int)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index ba66215..289bcb8 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -190,8 +190,8 @@
}
}
}
- // Check that liba depends on libbindings1
if strings.Contains(rootModule, "d/src/lib.rs") {
+ // Check that libd depends on libbindings1
found := false
for _, depName := range validateDependencies(t, crate) {
if depName == "bindings1" {
@@ -200,8 +200,17 @@
}
}
if !found {
- t.Errorf("liba does not depend on libbindings1: %v", crate)
+ t.Errorf("libd does not depend on libbindings1: %v", crate)
}
+ // Check that OUT_DIR is populated.
+ env, ok := crate["env"].(map[string]interface{})
+ if !ok {
+ t.Errorf("libd does not have its environment variables set: %v", crate)
+ }
+ if _, ok = env["OUT_DIR"]; !ok {
+ t.Errorf("libd does not have its OUT_DIR set: %v", env)
+ }
+
}
}
}
diff --git a/rust/rust.go b/rust/rust.go
index dc23abb..8ebdb72 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -320,12 +320,16 @@
}
type compiler interface {
+ initialize(ctx ModuleContext)
compilerFlags(ctx ModuleContext, flags Flags) Flags
compilerProps() []interface{}
compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path
compilerDeps(ctx DepsContext, deps Deps) Deps
crateName() string
+ // Output directory in which source-generated code from dependencies is
+ // copied. This is equivalent to Cargo's OUT_DIR variable.
+ CargoOutDir() android.OptionalPath
inData() bool
install(ctx ModuleContext)
relativeInstallPath() string
@@ -711,6 +715,7 @@
}
if mod.compiler != nil && !mod.compiler.Disabled() {
+ mod.compiler.initialize(ctx)
outputFile := mod.compiler.compile(ctx, flags, deps)
mod.outputFile = android.OptionalPathForPath(outputFile)