Support test runnner option in auto generated test configs am: 5bde2e2ca9
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/26053802
Change-Id: Id8b68d57d95bb72df1e1ff6bf40ec6d35e3bed70
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/aidl_library/Android.bp b/aidl_library/Android.bp
new file mode 100644
index 0000000..ec21504
--- /dev/null
+++ b/aidl_library/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-aidl-library",
+ pkgPath: "android/soong/aidl_library",
+ deps: [
+ "soong-android",
+ ],
+ srcs: [
+ "aidl_library.go",
+ ],
+ testSrcs: [
+ "aidl_library_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
new file mode 100644
index 0000000..5985103
--- /dev/null
+++ b/aidl_library/aidl_library.go
@@ -0,0 +1,187 @@
+// Copyright 2023 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 aidl_library
+
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var PrepareForTestWithAidlLibrary = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ registerAidlLibraryBuildComponents(ctx)
+})
+
+func init() {
+ registerAidlLibraryBuildComponents(android.InitRegistrationContext)
+}
+
+func registerAidlLibraryBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("aidl_library", AidlLibraryFactory)
+}
+
+type aidlLibraryProperties struct {
+ // srcs lists files that are included in this module for aidl compilation
+ Srcs []string `android:"path"`
+
+ // hdrs lists the headers that are imported by srcs but are not compiled by aidl to language binding code
+ // hdrs is provided to support Bazel migration. It is a no-op until
+ // we enable input sandbox in aidl compilation action
+ Hdrs []string `android:"path"`
+
+ // The prefix to strip from the paths of the .aidl files
+ // The remaining path is the package path of the aidl interface
+ Strip_import_prefix *string
+
+ // List of aidl files or aidl_library depended on by the module
+ Deps []string `android:"arch_variant"`
+}
+
+type AidlLibrary struct {
+ android.ModuleBase
+ android.BazelModuleBase
+ properties aidlLibraryProperties
+}
+
+type bazelAidlLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
+ Strip_import_prefix *string
+ Deps bazel.LabelListAttribute
+}
+
+func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ srcs := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(
+ ctx,
+ lib.properties.Srcs,
+ ),
+ )
+
+ hdrs := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(
+ ctx,
+ lib.properties.Hdrs,
+ ),
+ )
+
+ tags := []string{"apex_available=//apex_available:anyapex"}
+ deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, lib.properties.Deps))
+
+ attrs := &bazelAidlLibraryAttributes{
+ Srcs: srcs,
+ Hdrs: hdrs,
+ Strip_import_prefix: lib.properties.Strip_import_prefix,
+ Deps: deps,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "aidl_library",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: lib.Name(),
+ Tags: bazel.MakeStringListAttribute(tags),
+ },
+ attrs,
+ )
+}
+
+type AidlLibraryInfo struct {
+ // The direct aidl files of the module
+ Srcs android.Paths
+ // The include dirs to the direct aidl files and those provided from transitive aidl_library deps
+ IncludeDirs android.DepSet
+ // The direct hdrs and hdrs from transitive deps
+ Hdrs android.DepSet
+}
+
+// AidlLibraryProvider provides the srcs and the transitive include dirs
+var AidlLibraryProvider = blueprint.NewProvider(AidlLibraryInfo{})
+
+func (lib *AidlLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ includeDirsDepSetBuilder := android.NewDepSetBuilder(android.PREORDER)
+ hdrsDepSetBuilder := android.NewDepSetBuilder(android.PREORDER)
+
+ if len(lib.properties.Srcs) == 0 && len(lib.properties.Hdrs) == 0 {
+ ctx.ModuleErrorf("at least srcs or hdrs prop must be non-empty")
+ }
+
+ srcs := android.PathsForModuleSrc(ctx, lib.properties.Srcs)
+ hdrs := android.PathsForModuleSrc(ctx, lib.properties.Hdrs)
+
+ if lib.properties.Strip_import_prefix != nil {
+ srcs = android.PathsWithModuleSrcSubDir(
+ ctx,
+ srcs,
+ android.String(lib.properties.Strip_import_prefix),
+ )
+
+ hdrs = android.PathsWithModuleSrcSubDir(
+ ctx,
+ hdrs,
+ android.String(lib.properties.Strip_import_prefix),
+ )
+ }
+ hdrsDepSetBuilder.Direct(hdrs...)
+
+ includeDir := android.PathForModuleSrc(
+ ctx,
+ proptools.StringDefault(lib.properties.Strip_import_prefix, ""),
+ )
+ includeDirsDepSetBuilder.Direct(includeDir)
+
+ for _, dep := range ctx.GetDirectDepsWithTag(aidlLibraryTag) {
+ if ctx.OtherModuleHasProvider(dep, AidlLibraryProvider) {
+ info := ctx.OtherModuleProvider(dep, AidlLibraryProvider).(AidlLibraryInfo)
+ includeDirsDepSetBuilder.Transitive(&info.IncludeDirs)
+ hdrsDepSetBuilder.Transitive(&info.Hdrs)
+ }
+ }
+
+ ctx.SetProvider(AidlLibraryProvider, AidlLibraryInfo{
+ Srcs: srcs,
+ IncludeDirs: *includeDirsDepSetBuilder.Build(),
+ Hdrs: *hdrsDepSetBuilder.Build(),
+ })
+}
+
+// aidl_library contains a list of .aidl files and the strip_import_prefix to
+// to strip from the paths of the .aidl files. The sub-path left-over after stripping
+// corresponds to the aidl package path the aidl interfaces are scoped in
+func AidlLibraryFactory() android.Module {
+ module := &AidlLibrary{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ android.InitBazelModule(module)
+ return module
+}
+
+type aidlDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var aidlLibraryTag = aidlDependencyTag{}
+
+func (lib *AidlLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ for _, dep := range lib.properties.Deps {
+ ctx.AddDependency(lib, aidlLibraryTag, dep)
+ }
+}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
new file mode 100644
index 0000000..d9dd245
--- /dev/null
+++ b/aidl_library/aidl_library_test.go
@@ -0,0 +1,136 @@
+// Copyright 2023 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 aidl_library
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestAidlLibrary(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ strip_import_prefix: "x",
+ }
+ `),
+ }.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ hdrs: ["a/Header.aidl"],
+ strip_import_prefix: "a",
+ deps: ["bar"],
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+ android.AssertArrayString(
+ t,
+ "aidl include dirs",
+ []string{"package_foo/a", "package_bar/x"},
+ actualInfo.IncludeDirs.ToList().Strings(),
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl srcs paths",
+ []string{"package_foo/a/b/Foo.aidl"},
+ actualInfo.Srcs,
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl hdrs paths",
+ []string{"package_foo/a/Header.aidl"},
+ actualInfo.Hdrs.ToList(),
+ )
+}
+
+func TestAidlLibraryWithoutStripImportPrefix(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ hdrs: ["BarHeader.aidl"],
+ }
+ `),
+ }.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ deps: ["bar"],
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+ android.AssertArrayString(
+ t,
+ "aidl include dirs",
+ []string{"package_foo", "package_bar"},
+ actualInfo.IncludeDirs.ToList().Strings(),
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl srcs paths",
+ []string{"package_foo/a/b/Foo.aidl"},
+ actualInfo.Srcs,
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl hdrs paths",
+ []string{"package_bar/BarHeader.aidl"},
+ actualInfo.Hdrs.ToList(),
+ )
+}
+
+func TestAidlLibraryWithNoSrcsHdrsDeps(t *testing.T) {
+ t.Parallel()
+ android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ }
+ `),
+ }.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("at least srcs or hdrs prop must be non-empty")).
+ RunTest(t)
+}
diff --git a/android/Android.bp b/android/Android.bp
index 641c438..b13d7cd 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -11,6 +11,7 @@
"blueprint-metrics",
"sbox_proto",
"soong",
+ "soong-android_team_proto",
"soong-android-soongconfig",
"soong-bazel",
"soong-cquery",
@@ -28,6 +29,7 @@
"androidmk-parser",
],
srcs: [
+ "all_teams.go",
"androidmk.go",
"apex.go",
"api_domain.go",
@@ -88,6 +90,7 @@
"singleton.go",
"singleton_module.go",
"soong_config_modules.go",
+ "team.go",
"test_asserts.go",
"test_suites.go",
"testing.go",
diff --git a/android/all_teams.go b/android/all_teams.go
new file mode 100644
index 0000000..d061649
--- /dev/null
+++ b/android/all_teams.go
@@ -0,0 +1,151 @@
+package android
+
+import (
+ "android/soong/android/team_proto"
+ "path/filepath"
+
+ "github.com/google/blueprint/proptools"
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+)
+
+const ownershipDirectory = "ownership"
+const allTeamsFile = "all_teams.pb"
+
+func AllTeamsFactory() Singleton {
+ return &allTeamsSingleton{}
+}
+
+func init() {
+ registerAllTeamBuildComponents(InitRegistrationContext)
+}
+
+func registerAllTeamBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterSingletonType("all_teams", AllTeamsFactory)
+}
+
+// For each module, list the team or the bpFile the module is defined in.
+type moduleTeamInfo struct {
+ teamName string
+ bpFile string
+}
+
+type allTeamsSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath OutputPath
+
+ // Map of all package modules we visit during GenerateBuildActions
+ packages map[string]packageProperties
+ // Map of all team modules we visit during GenerateBuildActions
+ teams map[string]teamProperties
+ // Keeps track of team information or bp file for each module we visit.
+ teams_for_mods map[string]moduleTeamInfo
+}
+
+// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
+// If not ascend up to the parent directory and do the same.
+func (this *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
+ // return the Default_team listed in the package if is there.
+ if p, ok := this.packages[bpFilePath]; ok {
+ if t := p.Default_team; t != nil {
+ return this.teams[*p.Default_team], true
+ }
+ }
+ // Strip a directory and go up.
+ // Does android/paths.go basePath,SourcePath help?
+ current, base := filepath.Split(bpFilePath)
+ current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
+ parent, _ := filepath.Split(current)
+ if current == "." {
+ return teamProperties{}, false
+ }
+ return this.lookupDefaultTeam(filepath.Join(parent, base))
+}
+
+// Create a rule to run a tool to collect all the intermediate files
+// which list the team per module into one proto file.
+func (this *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ this.packages = make(map[string]packageProperties)
+ this.teams = make(map[string]teamProperties)
+ this.teams_for_mods = make(map[string]moduleTeamInfo)
+
+ ctx.VisitAllModules(func(module Module) {
+ if !module.Enabled() {
+ return
+ }
+
+ bpFile := ctx.BlueprintFile(module)
+
+ // Package Modules and Team Modules are stored in a map so we can look them up by name for
+ // modules without a team.
+ if pack, ok := module.(*packageModule); ok {
+ // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in this context.
+ pkgKey := bpFile
+ this.packages[pkgKey] = pack.properties
+ return
+ }
+ if team, ok := module.(*teamModule); ok {
+ this.teams[team.Name()] = team.properties
+ return
+ }
+
+ // If a team name is given for a module, store it.
+ // Otherwise store the bpFile so we can do a package walk later.
+ if module.base().Team() != "" {
+ this.teams_for_mods[module.Name()] = moduleTeamInfo{teamName: module.base().Team(), bpFile: bpFile}
+ } else {
+ this.teams_for_mods[module.Name()] = moduleTeamInfo{bpFile: bpFile}
+ }
+ })
+
+ // Visit all modules again and lookup the team name in the package or parent package if the team
+ // isn't assignged at the module level.
+ allTeams := this.lookupTeamForAllModules()
+
+ this.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
+ // udc branch diff, use textproto and encode it.
+ data, err := prototext.Marshal(allTeams)
+ if err != nil {
+ ctx.Errorf("Unable to marshal team data. %s", err)
+ }
+
+ WriteFileRuleVerbatim(ctx, this.outputPath, proptools.NinjaEscape(string(data)))
+ ctx.Phony("all_teams", this.outputPath)
+}
+
+func (this *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
+ ctx.DistForGoal("all_teams", this.outputPath)
+}
+
+// Visit every (non-package, non-team) module and write out a proto containing
+// either the declared team data for that module or the package default team data for that module.
+func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
+ teamsProto := make([]*team_proto.Team, len(this.teams_for_mods))
+ i := 0
+ for moduleName, m := range this.teams_for_mods {
+ teamName := m.teamName
+ var teamProperties teamProperties
+ found := false
+ if teamName != "" {
+ teamProperties, found = this.teams[teamName]
+ } else {
+ teamProperties, found = this.lookupDefaultTeam(m.bpFile)
+ }
+
+ // udc branch diff, only write modules with teams to keep ninja file smaller.
+ if found {
+ trendy_team_id := *teamProperties.Trendy_team_id
+ var files []string
+ teamData := new(team_proto.Team)
+ *teamData = team_proto.Team{
+ TrendyTeamId: proto.String(trendy_team_id),
+ TargetName: proto.String(moduleName),
+ Path: proto.String(m.bpFile),
+ File: files,
+ }
+ teamsProto[i] = teamData
+ i++
+ }
+ }
+ return &team_proto.AllTeams{Teams: teamsProto[:i]}
+}
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
new file mode 100644
index 0000000..6302d86
--- /dev/null
+++ b/android/all_teams_test.go
@@ -0,0 +1,208 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package android
+
+import (
+ "android/soong/android/team_proto"
+ "log"
+ "testing"
+
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestAllTeams(t *testing.T) {
+ t.Parallel()
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ ctx.RegisterSingletonType("all_teams", AllTeamsFactory)
+ }),
+ ).RunTestWithBp(t, `
+ fake {
+ name: "main_test",
+ team: "someteam",
+ }
+ team {
+ name: "someteam",
+ trendy_team_id: "cool_team",
+ }
+
+ team {
+ name: "team2",
+ trendy_team_id: "22222",
+ }
+
+ fake {
+ name: "tool",
+ team: "team2",
+ }
+
+ fake {
+ name: "noteam",
+ }
+ `)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "main_test": proto.String("cool_team"),
+ "tool": proto.String("22222"),
+ }
+
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
+func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams {
+ teams := new(team_proto.AllTeams)
+ config := ctx.SingletonForTests("all_teams")
+ allOutputs := config.AllOutputs()
+
+ protoPath := allOutputs[0]
+
+ out := config.MaybeOutput(protoPath)
+ outProto := []byte(ContentFromFileRuleForTests(t, out))
+ // udc diff
+ if err := prototext.Unmarshal(outProto, teams); err != nil {
+ log.Fatalln("Failed to parse teams proto:", err)
+ }
+ return teams
+}
+
+// Android.bp
+//
+// team: team_top
+//
+// # dir1 has no modules with teams,
+// # but has a dir with no Android.bp
+// dir1/Android.bp
+//
+// module_dir1
+//
+// # dirs without and Android.bp should be fine.
+// dir1/dir2/dir3/Android.bp
+//
+// package {}
+// module_dir123
+//
+// teams_dir/Android.bp
+//
+// module_with_team1: team1
+// team1: 111
+//
+// # team comes from upper package default
+// teams_dir/deeper/Android.bp
+//
+// module2_with_team1: team1
+//
+// package_defaults/Android.bp
+// package_defaults/pd2/Android.bp
+//
+// package{ default_team: team_top}
+// module_pd2 ## should get team_top
+//
+// package_defaults/pd2/pd3/Android.bp
+//
+// module_pd3 ## should get team_top
+func TestPackageLookup(t *testing.T) {
+ t.Parallel()
+ rootBp := `
+ team {
+ name: "team_top",
+ trendy_team_id: "trendy://team_top",
+ } `
+
+ dir1Bp := `
+ fake {
+ name: "module_dir1",
+ } `
+ dir3Bp := `
+ package {}
+ fake {
+ name: "module_dir123",
+ } `
+ teamsDirBp := `
+ fake {
+ name: "module_with_team1",
+ team: "team1"
+
+ }
+ team {
+ name: "team1",
+ trendy_team_id: "111",
+ } `
+ teamsDirDeeper := `
+ fake {
+ name: "module2_with_team1",
+ team: "team1"
+ } `
+ // create an empty one.
+ packageDefaultsBp := ""
+ packageDefaultspd2 := `
+ package { default_team: "team_top"}
+ fake {
+ name: "modulepd2",
+ } `
+
+ packageDefaultspd3 := `
+ fake {
+ name: "modulepd3",
+ }
+ fake {
+ name: "modulepd3b",
+ team: "team1"
+ } `
+
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ ctx.RegisterSingletonType("all_teams", AllTeamsFactory)
+ }),
+ FixtureAddTextFile("Android.bp", rootBp),
+ FixtureAddTextFile("dir1/Android.bp", dir1Bp),
+ FixtureAddTextFile("dir1/dir2/dir3/Android.bp", dir3Bp),
+ FixtureAddTextFile("teams_dir/Android.bp", teamsDirBp),
+ FixtureAddTextFile("teams_dir/deeper/Android.bp", teamsDirDeeper),
+ FixtureAddTextFile("package_defaults/Android.bp", packageDefaultsBp),
+ FixtureAddTextFile("package_defaults/pd2/Android.bp", packageDefaultspd2),
+ FixtureAddTextFile("package_defaults/pd2/pd3/Android.bp", packageDefaultspd3),
+ ).RunTest(t)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "module_with_team1": proto.String("111"),
+ "module2_with_team1": proto.String("111"),
+ "modulepd2": proto.String("trendy://team_top"),
+ "modulepd3": proto.String("trendy://team_top"),
+ "modulepd3b": proto.String("111"),
+ // udc diff, no nil teams
+ }
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 63d4e11..5ccffc3 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -201,6 +201,7 @@
"frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
+ "frameworks/base/libs/services": Bp2BuildDefaultTrue,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
"frameworks/base/proto": Bp2BuildDefaultTrue,
@@ -384,7 +385,7 @@
"tools/apifinder": Bp2BuildDefaultTrue,
"tools/apksig": Bp2BuildDefaultTrue,
"tools/external_updater": Bp2BuildDefaultTrueRecursively,
- "tools/metalava": Bp2BuildDefaultTrue,
+ "tools/metalava": Bp2BuildDefaultTrueRecursively,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
}
@@ -559,6 +560,9 @@
//external/fec
"libfec_rs",
+ //frameworks/base/core/java
+ "IDropBoxManagerService_aidl",
+
//system/core/libsparse
"libsparse",
diff --git a/android/apex.go b/android/apex.go
index c9b4a0b..5a25297 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -451,6 +451,14 @@
AvailableToGkiApex = "com.android.gki.*"
)
+var (
+ AvailableToRecognziedWildcards = []string{
+ AvailableToPlatform,
+ AvailableToAnyApex,
+ AvailableToGkiApex,
+ }
+)
+
// CheckAvailableForApex provides the default algorithm for checking the apex availability. When the
// availability is empty, it defaults to ["//apex_available:platform"] which means "available to the
// platform but not available to any APEX". When the list is not empty, `what` is matched against
@@ -909,3 +917,22 @@
return true
})
}
+
+// Construct ApiLevel object from min_sdk_version string value
+func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
+ if value == "" {
+ return NoneApiLevel
+ }
+ apiLevel, err := ApiLevelFromUser(ctx, value)
+ if err != nil {
+ ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
+ return NoneApiLevel
+ }
+ return apiLevel
+}
+
+// Implemented by apexBundle.
+type ApexTestInterface interface {
+ // Return true if the apex bundle is an apex_test
+ IsTestApex() bool
+}
diff --git a/android/arch.go b/android/arch.go
index 4b4691b..d3e7d2a 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -446,8 +446,10 @@
}
}
+ createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+
// If there are no supported OSes then disable the module.
- if len(moduleOSList) == 0 {
+ if len(moduleOSList) == 0 && !createCommonOSVariant {
base.Disable()
return
}
@@ -458,7 +460,6 @@
osNames[i] = os.String()
}
- createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
if createCommonOSVariant {
// A CommonOS variant was requested so add it to the list of OS variants to
// create. It needs to be added to the end because it needs to depend on the
diff --git a/android/config.go b/android/config.go
index 980460a..dfbb46f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -702,6 +702,14 @@
return path
}
+func (c *config) HostCcSharedLibPath(ctx PathContext, lib string) Path {
+ libDir := "lib"
+ if ctx.Config().BuildArch.Multilib == "lib64" {
+ libDir = "lib64"
+ }
+ return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, libDir, false, lib+".so")
+}
+
// PrebuiltOS returns the name of the host OS used in prebuilts directories.
func (c *config) PrebuiltOS() string {
switch runtime.GOOS {
diff --git a/android/filegroup.go b/android/filegroup.go
index f30ee51..66aa154 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -82,7 +82,6 @@
type bazelAidlLibraryAttributes struct {
Srcs bazel.LabelListAttribute
Strip_import_prefix *string
- Deps bazel.LabelListAttribute
}
// api srcs can be contained in filegroups.
@@ -121,12 +120,9 @@
// and then convert
if fg.ShouldConvertToAidlLibrary(ctx) {
tags := []string{"apex_available=//apex_available:anyapex"}
- deps := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, fg.properties.Aidl.Deps))
-
attrs := &bazelAidlLibraryAttributes{
Srcs: srcs,
Strip_import_prefix: fg.properties.Path,
- Deps: deps,
}
props := bazel.BazelTargetModuleProperties{
@@ -192,14 +188,6 @@
// Create a make variable with the specified name that contains the list of files in the
// filegroup, relative to the root of the source tree.
Export_to_make_var *string
-
- // aidl is explicitly provided for implicit aidl dependencies
- // TODO(b/278298615): aidl prop is a no-op in Soong and is an escape hatch
- // to include implicit aidl dependencies for bazel migration compatibility
- Aidl struct {
- // List of aidl files or filegroup depended on by srcs
- Deps []string `android:"path"`
- }
}
type fileGroup struct {
@@ -249,6 +237,7 @@
if fg.properties.Path != nil {
fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
}
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
}
func (fg *fileGroup) Srcs() Paths {
diff --git a/android/module.go b/android/module.go
index 76b4e3d..05f7682 100644
--- a/android/module.go
+++ b/android/module.go
@@ -953,6 +953,10 @@
// Bazel conversion status
BazelConversionStatus BazelConversionStatus `blueprint:"mutated"`
+
+ // The team (defined by the owner/vendor) who owns the property.
+ Team *string `android:"path"`
+
}
// CommonAttributes represents the common Bazel attributes from which properties
@@ -995,6 +999,12 @@
Dists []Dist `android:"arch_variant"`
}
+type TeamDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var teamDepTag = TeamDepTagType{}
+
// CommonTestOptions represents the common `test_options` properties in
// Android.bp.
type CommonTestOptions struct {
@@ -1699,6 +1709,12 @@
func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
+func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) {
+ if m.Team() != "" {
+ ctx.AddDependency(ctx.Module(), teamDepTag, m.Team())
+ }
+}
+
// AddProperties "registers" the provided props
// each value in props MUST be a pointer to a struct
func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -2136,6 +2152,10 @@
return String(m.commonProperties.Owner)
}
+func (m *ModuleBase) Team() string {
+ return String(m.commonProperties.Team)
+}
+
func (m *ModuleBase) setImageVariation(variant string) {
m.commonProperties.ImageVariation = variant
}
diff --git a/android/mutator.go b/android/mutator.go
index 4ec9604..0afa767 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -681,6 +681,7 @@
func depsMutator(ctx BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
+ m.base().baseDepsMutator(ctx)
m.DepsMutator(ctx)
}
}
@@ -758,6 +759,35 @@
return attr
}
+func ApexAvailableTagsWithoutTestApexes(ctx BaseModuleContext, mod Module) bazel.StringListAttribute {
+ attr := bazel.StringListAttribute{}
+ if am, ok := mod.(ApexModule); ok {
+ apexAvailableWithoutTestApexes := removeTestApexes(ctx, am.apexModuleBase().ApexAvailable())
+ // If a user does not specify apex_available in Android.bp, then soong provides a default.
+ // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
+ if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
+ apexAvailableWithoutTestApexes = []string{}
+ }
+ attr.Value = ConvertApexAvailableToTags(apexAvailableWithoutTestApexes)
+ }
+ return attr
+}
+
+func removeTestApexes(ctx BaseModuleContext, apex_available []string) []string {
+ testApexes := []string{}
+ for _, aa := range apex_available {
+ // ignore the wildcards
+ if InList(aa, AvailableToRecognziedWildcards) {
+ continue
+ }
+ mod, _ := ctx.ModuleFromName(aa)
+ if apex, ok := mod.(ApexTestInterface); ok && apex.IsTestApex() {
+ testApexes = append(testApexes, aa)
+ }
+ }
+ return RemoveListFromList(CopyOf(apex_available), testApexes)
+}
+
func ConvertApexAvailableToTags(apexAvailable []string) []string {
if len(apexAvailable) == 0 {
// We need nil specifically to make bp2build not add the tags property at all,
@@ -771,6 +801,13 @@
return result
}
+// ConvertApexAvailableToTagsWithoutTestApexes converts a list of apex names to a list of bazel tags
+// This function drops any test apexes from the input.
+func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvailable []string) []string {
+ noTestApexes := removeTestApexes(ctx, apexAvailable)
+ return ConvertApexAvailableToTags(noTestApexes)
+}
+
func (t *topDownMutatorContext) createBazelTargetModule(
bazelProps bazel.BazelTargetModuleProperties,
commonAttrs CommonAttributes,
diff --git a/android/package.go b/android/package.go
index 7fbc700..682b350 100644
--- a/android/package.go
+++ b/android/package.go
@@ -38,6 +38,7 @@
Default_visibility []string
// Specifies the default license terms for all modules defined in this package.
Default_applicable_licenses []string
+ Default_team *string `android:"path"`
}
type bazelPackageAttributes struct {
@@ -90,6 +91,13 @@
// Nothing to do.
}
+func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) {
+ // Add the dependency to do a validity check
+ if p.properties.Default_team != nil {
+ ctx.AddDependency(ctx.Module(), nil, *p.properties.Default_team)
+ }
+}
+
func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
// Nothing to do.
}
diff --git a/android/proto.go b/android/proto.go
index 09e50c8..cebbd59 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -234,7 +234,7 @@
}
}
- tags := ApexAvailableTags(ctx.Module())
+ tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
diff --git a/android/team.go b/android/team.go
new file mode 100644
index 0000000..df61f40
--- /dev/null
+++ b/android/team.go
@@ -0,0 +1,58 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+func init() {
+ RegisterTeamBuildComponents(InitRegistrationContext)
+}
+
+func RegisterTeamBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("team", TeamFactory)
+}
+
+var PrepareForTestWithTeamBuildComponents = GroupFixturePreparers(
+ FixtureRegisterWithContext(RegisterTeamBuildComponents),
+)
+
+type teamProperties struct {
+ Trendy_team_id *string `json:"trendy_team_id"`
+}
+
+type teamModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties teamProperties
+}
+
+// Real work is done for the module that depends on us.
+// If needed, the team can serialize the config to json/proto file as well.
+func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
+
+func (t *teamModule) TrendyTeamId(ctx ModuleContext) string {
+ return *t.properties.Trendy_team_id
+}
+
+func TeamFactory() Module {
+ module := &teamModule{}
+
+ base := module.base()
+ module.AddProperties(&base.nameProperties, &module.properties)
+
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+
+ return module
+}
diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp
new file mode 100644
index 0000000..061e77e
--- /dev/null
+++ b/android/team_proto/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-android_team_proto",
+ pkgPath: "android/soong/android/team_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "team.pb.go",
+ ],
+}
diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS
new file mode 100644
index 0000000..2beb4f4
--- /dev/null
+++ b/android/team_proto/OWNERS
@@ -0,0 +1,5 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
+rbraunstein@google.com
diff --git a/android/team_proto/regen.sh b/android/team_proto/regen.sh
new file mode 100755
index 0000000..63b2016
--- /dev/null
+++ b/android/team_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. team.proto
diff --git a/android/team_proto/team.pb.go b/android/team_proto/team.pb.go
new file mode 100644
index 0000000..61260cf
--- /dev/null
+++ b/android/team_proto/team.pb.go
@@ -0,0 +1,253 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: team.proto
+
+package team_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Team struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: Files directly owned by this module.
+ File []string `protobuf:"bytes,4,rep,name=file" json:"file,omitempty"`
+}
+
+func (x *Team) Reset() {
+ *x = Team{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_team_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Team) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Team) ProtoMessage() {}
+
+func (x *Team) ProtoReflect() protoreflect.Message {
+ mi := &file_team_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Team.ProtoReflect.Descriptor instead.
+func (*Team) Descriptor() ([]byte, []int) {
+ return file_team_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Team) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *Team) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *Team) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *Team) GetFile() []string {
+ if x != nil {
+ return x.File
+ }
+ return nil
+}
+
+type AllTeams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Teams []*Team `protobuf:"bytes,1,rep,name=teams" json:"teams,omitempty"`
+}
+
+func (x *AllTeams) Reset() {
+ *x = AllTeams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_team_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AllTeams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AllTeams) ProtoMessage() {}
+
+func (x *AllTeams) ProtoReflect() protoreflect.Message {
+ mi := &file_team_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AllTeams.ProtoReflect.Descriptor instead.
+func (*AllTeams) Descriptor() ([]byte, []int) {
+ return file_team_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *AllTeams) GetTeams() []*Team {
+ if x != nil {
+ return x.Teams
+ }
+ return nil
+}
+
+var File_team_proto protoreflect.FileDescriptor
+
+var file_team_proto_rawDesc = []byte{
+ 0x0a, 0x0a, 0x74, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65,
+ 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f,
+ 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74,
+ 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66,
+ 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22,
+ 0x32, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74,
+ 0x65, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61,
+ 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65,
+ 0x61, 0x6d, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61,
+ 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_team_proto_rawDescOnce sync.Once
+ file_team_proto_rawDescData = file_team_proto_rawDesc
+)
+
+func file_team_proto_rawDescGZIP() []byte {
+ file_team_proto_rawDescOnce.Do(func() {
+ file_team_proto_rawDescData = protoimpl.X.CompressGZIP(file_team_proto_rawDescData)
+ })
+ return file_team_proto_rawDescData
+}
+
+var file_team_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_team_proto_goTypes = []interface{}{
+ (*Team)(nil), // 0: team_proto.Team
+ (*AllTeams)(nil), // 1: team_proto.AllTeams
+}
+var file_team_proto_depIdxs = []int32{
+ 0, // 0: team_proto.AllTeams.teams:type_name -> team_proto.Team
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_team_proto_init() }
+func file_team_proto_init() {
+ if File_team_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_team_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Team); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_team_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AllTeams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_team_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_team_proto_goTypes,
+ DependencyIndexes: file_team_proto_depIdxs,
+ MessageInfos: file_team_proto_msgTypes,
+ }.Build()
+ File_team_proto = out.File
+ file_team_proto_rawDesc = nil
+ file_team_proto_goTypes = nil
+ file_team_proto_depIdxs = nil
+}
diff --git a/android/team_proto/team.proto b/android/team_proto/team.proto
new file mode 100644
index 0000000..401eccc
--- /dev/null
+++ b/android/team_proto/team.proto
@@ -0,0 +1,34 @@
+// 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.
+
+syntax = "proto2";
+package team_proto;
+option go_package = "android/soong/android/team_proto";
+
+message Team {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: Files directly owned by this module.
+ repeated string file = 4;
+}
+
+message AllTeams {
+ repeated Team teams = 1;
+}
diff --git a/android/team_test.go b/android/team_test.go
new file mode 100644
index 0000000..75b3e9f
--- /dev/null
+++ b/android/team_test.go
@@ -0,0 +1,99 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package android
+
+import (
+ "testing"
+)
+
+type fakeModuleForTests struct {
+ ModuleBase
+}
+
+func fakeModuleFactory() Module {
+ module := &fakeModuleForTests{}
+ InitAndroidModule(module)
+ return module
+}
+
+func (*fakeModuleForTests) GenerateAndroidBuildActions(ModuleContext) {}
+
+func TestTeam(t *testing.T) {
+ t.Parallel()
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).RunTestWithBp(t, `
+ fake {
+ name: "main_test",
+ team: "someteam",
+ }
+ team {
+ name: "someteam",
+ trendy_team_id: "cool_team",
+ }
+
+ team {
+ name: "team2",
+ trendy_team_id: "22222",
+ }
+
+ fake {
+ name: "tool",
+ team: "team2",
+ }
+ `)
+
+ // Assert the rule from GenerateAndroidBuildActions exists.
+ m := ctx.ModuleForTests("main_test", "")
+ AssertStringEquals(t, "msg", m.Module().base().Team(), "someteam")
+ m = ctx.ModuleForTests("tool", "")
+ AssertStringEquals(t, "msg", m.Module().base().Team(), "team2")
+}
+
+func TestMissingTeamFails(t *testing.T) {
+ t.Parallel()
+ GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
+ RunTestWithBp(t, `
+ fake {
+ name: "you_cannot_pass",
+ team: "ring-bearer",
+ }
+ `)
+}
+
+func TestPackageBadTeamNameFails(t *testing.T) {
+ t.Parallel()
+ GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
+ RunTestWithBp(t, `
+ package {
+ default_team: "ring-bearer",
+ }
+ `)
+}
diff --git a/android/test_asserts.go b/android/test_asserts.go
index 4143f15..5cc7e4a 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "regexp"
"strings"
"testing"
)
@@ -137,6 +138,20 @@
}
}
+// AssertStringMatches checks if the string matches the given regular expression. If it does not match,
+// then an error is reported with the supplied message including a reason for why it failed.
+func AssertStringMatches(t *testing.T, message, s, expectedRex string) {
+ t.Helper()
+ ok, err := regexp.MatchString(expectedRex, s)
+ if err != nil {
+ t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", s, expectedRex, err)
+ return
+ }
+ if !ok {
+ t.Errorf("%s does not match regular expression %s", s, expectedRex)
+ }
+}
+
// AssertStringListContains checks if the list of strings contains the expected string. If it does
// not then it reports an error prefixed with the supplied message and including a reason for why it
// failed.
diff --git a/android/updatable_modules.go b/android/updatable_modules.go
index e6ad3fe..db45637 100644
--- a/android/updatable_modules.go
+++ b/android/updatable_modules.go
@@ -29,8 +29,8 @@
// based on the branch such that the builds from testing and development
// branches will have a version higher than the prebuilts.
// Versions per branch:
-// * x-dev - xx2090000 (where xx is the branch SDK level)
+// * x-dev - xx0090000 (where xx is the branch SDK level)
// * AOSP - xx9990000
// * x-mainline-prod - xx9990000
// * master - 990090000
-const DefaultUpdatableModuleVersion = "342090000"
+const DefaultUpdatableModuleVersion = "349990000"
diff --git a/apex/apex.go b/apex/apex.go
index c1c9e5c..1f2da5f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -220,6 +220,13 @@
// imageApex or flattenedApex depending on Config.FlattenApex(). When payload_type is zip,
// this becomes zipApex.
ApexType apexPackaging `blueprint:"mutated"`
+
+ // Name that dependencies can specify in their apex_available properties to refer to this module.
+ // If not specified, this defaults to Soong module name.
+ Apex_available_name *string
+
+ // Variant version of the mainline module. Must be an integer between 0-9
+ Variant_version *string
}
type ApexNativeDependencies struct {
@@ -1823,6 +1830,7 @@
Certificate() java.Certificate
BaseModuleName() string
LintDepSets() java.LintDepSets
+ PrivAppAllowlist() android.OptionalPath
}
var _ androidApp = (*java.AndroidApp)(nil)
@@ -1843,7 +1851,7 @@
return buildId
}
-func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile {
+func apexFilesForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) []apexFile {
appDir := "app"
if aapp.Privileged() {
appDir = "priv-app"
@@ -1865,7 +1873,18 @@
}); ok {
af.overriddenPackageName = app.OverriddenManifestPackageName()
}
- return af
+
+ apexFiles := []apexFile{}
+
+ if allowlist := aapp.PrivAppAllowlist(); allowlist.Valid() {
+ dirInApex := filepath.Join("etc", "permissions")
+ privAppAllowlist := newApexFile(ctx, allowlist.Path(), aapp.BaseModuleName()+"_privapp", dirInApex, etc, aapp)
+ apexFiles = append(apexFiles, privAppAllowlist)
+ }
+
+ apexFiles = append(apexFiles, af)
+
+ return apexFiles
}
func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
@@ -2198,6 +2217,9 @@
// If a module is directly included and also transitively depended on
// consider it as directly included.
e.transitiveDep = e.transitiveDep && f.transitiveDep
+ // If a module is added as both a JNI library and a regular shared library, consider it as a
+ // JNI library.
+ e.isJniLib = e.isJniLib || f.isJniLib
encountered[dest] = e
}
}
@@ -2310,12 +2332,12 @@
case androidAppTag:
switch ap := child.(type) {
case *java.AndroidApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
return true // track transitive dependencies
case *java.AndroidAppImport:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
case *java.AndroidTestHelperApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
case *java.AndroidAppSet:
appDir := "app"
if ap.Privileged() {
@@ -2924,13 +2946,13 @@
// Only override the minSdkVersion value on Apexes which already specify
// a min_sdk_version (it's optional for non-updatable apexes), and that its
// min_sdk_version value is lower than the one to override with.
- minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
+ minApiLevel := android.MinSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
if minApiLevel.IsNone() {
return ""
}
overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
- overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
+ overrideApiLevel := android.MinSdkVersionFromValue(ctx, overrideMinSdkValue)
if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
minApiLevel = overrideApiLevel
}
@@ -2945,20 +2967,7 @@
// Returns apex's min_sdk_version ApiLevel, honoring overrides
func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- return minSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
-}
-
-// Construct ApiLevel object from min_sdk_version string value
-func minSdkVersionFromValue(ctx android.EarlyModuleContext, value string) android.ApiLevel {
- if value == "" {
- return android.NoneApiLevel
- }
- apiLevel, err := android.ApiLevelFromUser(ctx, value)
- if err != nil {
- ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
- return android.NoneApiLevel
- }
- return apiLevel
+ return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
}
// Ensures that a lib providing stub isn't statically linked
@@ -3083,6 +3092,13 @@
}
apexName := ctx.ModuleName()
+ for _, props := range ctx.Module().GetProperties() {
+ if apexProps, ok := props.(*apexBundleProperties); ok {
+ if apexProps.Apex_available_name != nil {
+ apexName = *apexProps.Apex_available_name
+ }
+ }
+ }
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
@@ -3790,3 +3806,7 @@
func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
}
+
+func (a *apexBundle) IsTestApex() bool {
+ return a.testApex
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e12f758..38d9106 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6166,6 +6166,7 @@
sdk_version: "current",
system_modules: "none",
privileged: true,
+ privapp_allowlist: "privapp_allowlist_com.android.AppFooPriv.xml",
stl: "none",
apex_available: [ "myapex" ],
}
@@ -6195,6 +6196,7 @@
ensureContains(t, copyCmds, "image.apex/app/AppFoo@TEST.BUILD_ID/AppFoo.apk")
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@TEST.BUILD_ID/AppFooPriv.apk")
+ ensureContains(t, copyCmds, "image.apex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
// JNI libraries are uncompressed
@@ -6209,6 +6211,18 @@
// ... and not directly inside the APEX
ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
}
+
+ apexBundle := module.Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, ctx, apexBundle)
+ var builder strings.Builder
+ data.Custom(&builder, apexBundle.Name(), "TARGET_", "", data)
+ androidMk := builder.String()
+ ensureContains(t, androidMk, "LOCAL_MODULE := AppFooPriv.myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := AppFoo.myapex")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFooPriv.apk")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFoo.apk")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := \\S+AppFooPriv.apk")
+ ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := privapp_allowlist_com.android.AppFooPriv.xml:$(PRODUCT_OUT)/apex/myapex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
}
func TestApexWithAppImportBuildId(t *testing.T) {
@@ -6543,6 +6557,266 @@
}`)
}
+func TestApexAvailable_ApexAvailableNameWithVersionCodeError(t *testing.T) {
+ t.Run("negative variant_version produces error", func(t *testing.T) {
+ testApexError(t, "expected an integer between 0-9; got -1", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apex_available_name: "com.android.foo",
+ variant_version: "-1",
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+ })
+
+ t.Run("variant_version greater than 9 produces error", func(t *testing.T) {
+ testApexError(t, "expected an integer between 0-9; got 10", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apex_available_name: "com.android.foo",
+ variant_version: "10",
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+ })
+}
+
+func TestApexAvailable_ApexAvailableNameWithVersionCode(t *testing.T) {
+ context := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/foo-file_contexts": nil,
+ "system/sepolicy/apex/bar-file_contexts": nil,
+ }),
+ )
+ result := context.RunTestWithBp(t, `
+ apex {
+ name: "foo",
+ key: "myapex.key",
+ apex_available_name: "com.android.foo",
+ variant_version: "0",
+ updatable: false,
+ }
+ apex {
+ name: "bar",
+ key: "myapex.key",
+ apex_available_name: "com.android.foo",
+ variant_version: "3",
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+
+ fooManifestRule := result.ModuleForTests("foo", "android_common_foo_image").Rule("apexManifestRule")
+ fooExpectedDefaultVersion := android.DefaultUpdatableModuleVersion
+ fooActualDefaultVersion := fooManifestRule.Args["default_version"]
+ if fooActualDefaultVersion != fooExpectedDefaultVersion {
+ t.Errorf("expected to find defaultVersion %q; got %q", fooExpectedDefaultVersion, fooActualDefaultVersion)
+ }
+
+ barManifestRule := result.ModuleForTests("bar", "android_common_bar_image").Rule("apexManifestRule")
+ defaultVersionInt, _ := strconv.Atoi(android.DefaultUpdatableModuleVersion)
+ barExpectedDefaultVersion := fmt.Sprint(defaultVersionInt + 3)
+ barActualDefaultVersion := barManifestRule.Args["default_version"]
+ if barActualDefaultVersion != barExpectedDefaultVersion {
+ t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
+ }
+}
+
+func TestApexAvailable_ApexAvailableName(t *testing.T) {
+ t.Run("using name of apex that sets apex_available_name is not allowed", func(t *testing.T) {
+ testApexError(t, "Consider adding \"myapex\" to 'apex_available' property of \"AppFoo\"", `
+ apex {
+ name: "myapex_sminus",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ apex_available_name: "myapex",
+ updatable: false,
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex_sminus" ],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+ }),
+ )
+ })
+
+ t.Run("apex_available_name allows module to be used in two different apexes", func(t *testing.T) {
+ testApex(t, `
+ apex {
+ name: "myapex_sminus",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ apex_available_name: "myapex",
+ updatable: false,
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+ }),
+ )
+ })
+
+ t.Run("override_apexes work with apex_available_name", func(t *testing.T) {
+ testApex(t, `
+ override_apex {
+ name: "myoverrideapex_sminus",
+ base: "myapex_sminus",
+ key: "myapex.key",
+ apps: ["AppFooOverride"],
+ }
+ override_apex {
+ name: "myoverrideapex",
+ base: "myapex",
+ key: "myapex.key",
+ apps: ["AppFooOverride"],
+ }
+ apex {
+ name: "myapex_sminus",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ apex_available_name: "myapex",
+ updatable: false,
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ android_app {
+ name: "AppFooOverride",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+ }),
+ )
+ })
+}
+
+func TestApexAvailable_ApexAvailableNameWithOverrides(t *testing.T) {
+ context := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ PrepareForTestWithApexBuildComponents,
+ java.PrepareForTestWithDexpreopt,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildId = proptools.StringPtr("buildid")
+ }),
+ )
+ context.RunTestWithBp(t, `
+ override_apex {
+ name: "myoverrideapex_sminus",
+ base: "myapex_sminus",
+ }
+ override_apex {
+ name: "myoverrideapex",
+ base: "myapex",
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ updatable: false,
+ }
+ apex {
+ name: "myapex_sminus",
+ apex_available_name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo_sminus"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }
+ android_app {
+ name: "AppFoo_sminus",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ min_sdk_version: "29",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }`)
+}
+
func TestApexAvailable_CheckForPlatform(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -7569,7 +7843,8 @@
apex {
name: "myapex",
key: "myapex.key",
- jni_libs: ["mylib", "libfoo.rust"],
+ binaries: ["mybin"],
+ jni_libs: ["mylib", "mylib3", "libfoo.rust"],
updatable: false,
}
@@ -7596,6 +7871,24 @@
apex_available: [ "myapex" ],
}
+ // Used as both a JNI library and a regular shared library.
+ cc_library {
+ name: "mylib3",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_binary {
+ name: "mybin",
+ srcs: ["mybin.cpp"],
+ shared_libs: ["mylib3"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
rust_ffi_shared {
name: "libfoo.rust",
crate_name: "foo",
@@ -7619,10 +7912,12 @@
rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
// Notice mylib2.so (transitive dep) is not added as a jni_lib
- ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so")
+ ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so mylib3.so")
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "bin/mybin",
"lib64/mylib.so",
"lib64/mylib2.so",
+ "lib64/mylib3.so",
"lib64/libfoo.rust.so",
"lib64/libc++.so", // auto-added to libfoo.rust by Soong
"lib64/liblog.so", // auto-added to libfoo.rust by Soong
diff --git a/apex/builder.go b/apex/builder.go
index 3c7671b..f49bed9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -275,6 +275,22 @@
manifestJsonFullOut := android.PathForModuleOut(ctx, "apex_manifest_full.json")
defaultVersion := android.DefaultUpdatableModuleVersion
+ if a.properties.Variant_version != nil {
+ defaultVersionInt, err := strconv.Atoi(defaultVersion)
+ if err != nil {
+ ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to be an int, but got %s", defaultVersion)
+ }
+ if defaultVersionInt%10 != 0 {
+ ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to end in a zero, but got %s", defaultVersion)
+ }
+ variantVersion := []rune(*a.properties.Variant_version)
+ if len(variantVersion) != 1 || variantVersion[0] < '0' || variantVersion[0] > '9' {
+ ctx.PropertyErrorf("variant_version", "expected an integer between 0-9; got %s", *a.properties.Variant_version)
+ }
+ defaultVersionRunes := []rune(defaultVersion)
+ defaultVersionRunes[len(defaultVersion)-1] = []rune(variantVersion)[0]
+ defaultVersion = string(defaultVersionRunes)
+ }
if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" {
defaultVersion = override
}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b6635c4..9ec3a40 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
"testing.go",
],
deps: [
+ "soong-aidl-library",
"soong-android",
"soong-android-allowlists",
"soong-android-soongconfig",
@@ -37,6 +38,7 @@
],
testSrcs: [
"aar_conversion_test.go",
+ "aidl_library_conversion_test.go",
"android_app_certificate_conversion_test.go",
"android_app_conversion_test.go",
"apex_conversion_test.go",
diff --git a/bp2build/aidl_library_conversion_test.go b/bp2build/aidl_library_conversion_test.go
new file mode 100644
index 0000000..0522da4
--- /dev/null
+++ b/bp2build/aidl_library_conversion_test.go
@@ -0,0 +1,119 @@
+// Copyright 2023 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/aidl_library"
+ "android/soong/android"
+)
+
+func runAidlLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "aidl_library"
+ (&tc).ModuleTypeUnderTestFactory = aidl_library.AidlLibraryFactory
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestAidlLibrary(t *testing.T) {
+ testcases := []struct {
+ name string
+ bp string
+ expectedBazelAttrs AttrNameToString
+ }{
+ {
+ name: "aidl_library with strip_import_prefix",
+ bp: `
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/foo.aidl"],
+ hdrs: ["aidl/header.aidl"],
+ strip_import_prefix: "aidl",
+ }`,
+ expectedBazelAttrs: AttrNameToString{
+ "srcs": `["aidl/foo.aidl"]`,
+ "hdrs": `["aidl/header.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ },
+ },
+ {
+ name: "aidl_library without strip_import_prefix",
+ bp: `
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/foo.aidl"],
+ hdrs: ["aidl/header.aidl"],
+ }`,
+ expectedBazelAttrs: AttrNameToString{
+ "srcs": `["aidl/foo.aidl"]`,
+ "hdrs": `["aidl/header.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ },
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
+ }
+ runAidlLibraryTestCase(t, Bp2buildTestCase{
+ Description: test.name,
+ Blueprint: test.bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestAidlLibraryWithDeps(t *testing.T) {
+ bp := `
+ aidl_library {
+ name: "bar",
+ srcs: ["Bar.aidl"],
+ hdrs: ["aidl/BarHeader.aidl"],
+ }
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/Foo.aidl"],
+ hdrs: ["aidl/FooHeader.aidl"],
+ strip_import_prefix: "aidl",
+ deps: ["bar"],
+ }`
+
+ t.Run("aidl_library with deps", func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
+ "srcs": `["Bar.aidl"]`,
+ "hdrs": `["aidl/BarHeader.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
+ "srcs": `["aidl/Foo.aidl"]`,
+ "hdrs": `["aidl/FooHeader.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "deps": `[":bar"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ }
+ runAidlLibraryTestCase(t, Bp2buildTestCase{
+ Description: "aidl_library with deps",
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 7165ac4..86aa4aa 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -18,6 +18,7 @@
"fmt"
"testing"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/cc"
)
@@ -63,6 +64,7 @@
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+ ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
}
func TestCcLibrarySimple(t *testing.T) {
@@ -3310,6 +3312,51 @@
})
}
+func TestCcLibraryWithAidlLibrary(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with aidl_library",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+aidl_library {
+ name: "A_aidl",
+ srcs: ["aidl/A.aidl"],
+ hdrs: ["aidl/Header.aidl"],
+ strip_import_prefix: "aidl",
+}
+cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["A_aidl"],
+ },
+ export_include_dirs: ["include"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
+ "srcs": `["aidl/A.aidl"]`,
+ "hdrs": `["aidl/Header.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":A_aidl"]`,
+ "local_includes": `["."]`,
+ "export_includes": `["include"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ "export_includes": `["include"]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ "export_includes": `["include"]`,
+ }),
+ },
+ })
+}
+
func TestCcLibraryWithAidlSrcs(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "cc_library with aidl srcs",
@@ -3338,6 +3385,7 @@
"srcs": `["B.aidl"]`,
}),
MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "local_includes": `["."]`,
"deps": `[
":A_aidl",
":foo_aidl_library",
@@ -3377,7 +3425,8 @@
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "deps": `["//path/to/A:A_aidl"]`,
+ "local_includes": `["."]`,
+ "deps": `["//path/to/A:A_aidl"]`,
}),
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
@@ -3392,37 +3441,78 @@
}
func TestCcLibraryWithExportAidlHeaders(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with export aidl headers",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: [
- "Foo.aidl",
- ],
- aidl: {
- export_aidl_headers: true,
- }
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["Foo.aidl"]`,
- }),
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "deps": `[":foo_aidl_library"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
+ t.Parallel()
+
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "local_includes": `["."]`,
+ "deps": `[":foo_aidl_library"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ }
+ testCases := []struct {
+ description string
+ bp string
+ expectedBazelTargets []string
+ }{
+ {
+ description: "cc_library with aidl srcs and aidl.export_aidl_headers set",
+ bp: `
+ cc_library {
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ aidl: {
+ export_aidl_headers: true,
+ }
+ }`,
+ expectedBazelTargets: append(
+ expectedBazelTargets,
+ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ })),
},
- })
+ {
+ description: "cc_library with aidl.libs and aidl.export_aidl_headers set",
+ bp: `
+ aidl_library {
+ name: "foo_aidl_library",
+ srcs: ["Foo.aidl"],
+ }
+ cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["foo_aidl_library"],
+ export_aidl_headers: true,
+ }
+ }`,
+ expectedBazelTargets: append(
+ expectedBazelTargets,
+ MakeBazelTargetNoRestrictions("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ ),
+ },
+ }
+
+ for _, testCase := range testCases {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with export aidl headers",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: testCase.bp,
+ ExpectedBazelTargets: testCase.expectedBazelTargets,
+ })
+ }
}
func TestCcLibraryWithTargetApex(t *testing.T) {
@@ -3637,7 +3727,8 @@
"srcs": `["Foo.aidl"]`,
}),
MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "deps": `[":foo_aidl_library"]`,
+ "local_includes": `["."]`,
+ "deps": `[":foo_aidl_library"]`,
"implementation_deps": `[
":baz-static",
":bar-static",
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index 273d556..7ce559d 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -105,42 +105,6 @@
}
}
-func TestFilegroupWithAidlDeps(t *testing.T) {
- bp := `
- filegroup {
- name: "bar",
- srcs: ["bar.aidl"],
- }
- filegroup {
- name: "foo",
- srcs: ["aidl/foo.aidl"],
- path: "aidl",
- aidl: {
- deps: [":bar"],
- }
- }`
-
- t.Run("filegroup with aidl deps", func(t *testing.T) {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
- "srcs": `["bar.aidl"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
- "srcs": `["aidl/foo.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "deps": `[":bar"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- }
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup with aidl deps",
- Blueprint: bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
-}
-
func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) {
runFilegroupTestCase(t, Bp2buildTestCase{
Description: "filegroup with aidl and non-aidl srcs",
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 45009c1..710d9cd 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -153,7 +153,9 @@
// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
"-isystem bionic/libc/kernel/uapi/asm-arm64",
"-isystem bionic/libc/kernel/android/uapi",
+ // TODO(b/296014682): Remove after the bpf_headers is moved to Connectivity
"-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
+ "-I packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf",
// TODO(b/149785767): only give access to specific file with AID_* constants
"-I system/core/libcutils/include",
"-I " + ctx.ModuleDir(),
@@ -206,6 +208,7 @@
}
}
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
}
func (bpf *bpf) AndroidMk() android.AndroidMkData {
diff --git a/cc/Android.bp b/cc/Android.bp
index be2cc5a..b12bdce 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-aidl-library",
"soong-android",
"soong-bazel",
"soong-cc-config",
@@ -17,12 +18,12 @@
"soong-genrule",
"soong-multitree",
"soong-snapshot",
+ "soong-testing",
"soong-tradefed",
],
srcs: [
"afdo.go",
"fdo_profile.go",
-
"androidmk.go",
"api_level.go",
"bp2build.go",
diff --git a/cc/binary.go b/cc/binary.go
index 097f822..98b9923 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -661,7 +661,7 @@
// shared with cc_test
binaryAttrs := binaryBp2buildAttrs(ctx, m)
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary",
Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index adf5a08..5e1c2d3 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -268,7 +268,7 @@
attrs.Srcs_c = partitionedSrcs[cSrcPartition]
attrs.Srcs_as = partitionedSrcs[asSrcPartition]
- attrs.Apex_available = android.ConvertApexAvailableToTags(apexAvailable)
+ attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable)
if !partitionedSrcs[protoSrcPartition].IsEmpty() {
// TODO(b/208815215): determine whether this is used and add support if necessary
@@ -717,6 +717,8 @@
compilerAttrs := compilerAttributes{}
linkerAttrs := linkerAttributes{}
+ var aidlLibs bazel.LabelList
+
// Iterate through these axes in a deterministic order. This is required
// because processing certain dependencies may result in concatenating
// elements along other axes. (For example, processing NoConfig may result
@@ -732,6 +734,7 @@
compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
}
(&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps)
+ aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs))
}
var exportHdrs []string
@@ -804,7 +807,15 @@
(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
- aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs)
+ aidlDep := bp2buildCcAidlLibrary(
+ ctx, module,
+ compilerAttrs.aidlSrcs,
+ bazel.LabelListAttribute{
+ Value: aidlLibs,
+ },
+ linkerAttrs,
+ compilerAttrs,
+ )
if aidlDep != nil {
if lib, ok := module.linker.(*libraryDecorator); ok {
if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
@@ -900,11 +911,16 @@
func bp2buildCcAidlLibrary(
ctx android.Bp2buildMutatorContext,
m *Module,
- aidlLabelList bazel.LabelListAttribute,
+ aidlSrcs bazel.LabelListAttribute,
+ aidlLibs bazel.LabelListAttribute,
linkerAttrs linkerAttributes,
+ compilerAttrs compilerAttributes,
) *bazel.LabelAttribute {
- if !aidlLabelList.IsEmpty() {
- aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
+ var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+
+ if !aidlSrcs.IsEmpty() {
+ aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool {
if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
fg.ShouldConvertToAidlLibrary(ctx) {
return true
@@ -912,57 +928,71 @@
return false
})
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
- sdkAttrs := bp2BuildParseSdkAttributes(m)
-
- if !aidlSrcs.IsEmpty() {
+ if !aidlFiles.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
- android.CommonAttributes{Name: aidlLibName},
- &aidlLibraryAttributes{
- Srcs: aidlSrcs,
+ android.CommonAttributes{
+ Name: aidlLibName,
Tags: apexAvailableTags,
},
- )
- aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
- }
-
- if !aidlLibs.IsEmpty() {
- ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
- // Since parent cc_library already has these dependencies, we can add them as implementation
- // deps so that they don't re-export
- implementationDeps := linkerAttrs.deps.Clone()
- implementationDeps.Append(linkerAttrs.implementationDeps)
- implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
- implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_aidl_library",
- Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
- },
- android.CommonAttributes{Name: ccAidlLibrarylabel},
- &ccAidlLibraryAttributes{
- Deps: aidlLibs,
- Implementation_deps: *implementationDeps,
- Implementation_dynamic_deps: *implementationDynamicDeps,
- Tags: apexAvailableTags,
- sdkAttributes: sdkAttrs,
+ &aidlLibraryAttributes{
+ Srcs: aidlFiles,
},
)
- label := &bazel.LabelAttribute{
- Value: &bazel.Label{
- Label: ":" + ccAidlLibrarylabel,
- },
- }
- return label
+ aidlLibsFromSrcs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
}
}
+ allAidlLibs := aidlLibs.Clone()
+ allAidlLibs.Append(aidlLibsFromSrcs)
+
+ if !allAidlLibs.IsEmpty() {
+ ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+ // Since parent cc_library already has these dependencies, we can add them as implementation
+ // deps so that they don't re-export
+ implementationDeps := linkerAttrs.deps.Clone()
+ implementationDeps.Append(linkerAttrs.implementationDeps)
+ implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
+ implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
+
+ sdkAttrs := bp2BuildParseSdkAttributes(m)
+
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, m, &compilerAttrs.includes)
+ includeAttrs := includesAttributes{
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_aidl_library",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+ },
+ android.CommonAttributes{Name: ccAidlLibrarylabel},
+ &ccAidlLibraryAttributes{
+ Deps: *allAidlLibs,
+ Implementation_deps: *implementationDeps,
+ Implementation_dynamic_deps: *implementationDynamicDeps,
+ Tags: apexAvailableTags,
+ sdkAttributes: sdkAttrs,
+ includesAttributes: includeAttrs,
+ },
+ )
+ label := &bazel.LabelAttribute{
+ Value: &bazel.Label{
+ Label: ":" + ccAidlLibrarylabel,
+ },
+ }
+ return label
+ }
+
return nil
}
diff --git a/cc/cc.go b/cc/cc.go
index 0addb60..c40c5a6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -24,9 +24,11 @@
"strconv"
"strings"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/bazel/cquery"
"android/soong/cc/config"
@@ -110,6 +112,9 @@
// Used by DepsMutator to pass system_shared_libs information to check_elf_file.py.
SystemSharedLibs []string
+ // Used by DepMutator to pass aidl_library modules to aidl compiler
+ AidlLibs []string
+
// If true, statically link the unwinder into native libraries/binaries.
StaticUnwinderIfLegacy bool
@@ -182,6 +187,9 @@
// For Darwin builds, the path to the second architecture's output that should
// be combined with this architectures's output into a FAT MachO file.
DarwinSecondArchOutput android.OptionalPath
+
+ // Paths to direct srcs and transitive include dirs from direct aidl_library deps
+ AidlLibraryInfos []aidl_library.AidlLibraryInfo
}
// LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
@@ -765,6 +773,7 @@
stubImplDepTag = dependencyTag{name: "stub_impl"}
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
FdoProfileTag = dependencyTag{name: "fdo_profile"}
+ aidlLibraryTag = dependencyTag{name: "aidl_library"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
@@ -827,9 +836,10 @@
Properties BaseProperties
// initialize before calling Init
- hod android.HostOrDeviceSupported
- multilib android.Multilib
- bazelable bool
+ hod android.HostOrDeviceSupported
+ multilib android.Multilib
+ bazelable bool
+ testModule bool
// Allowable SdkMemberTypes of this module type.
sdkMemberTypes []android.SdkMemberType
@@ -2096,6 +2106,10 @@
}
}
}
+ if c.testModule {
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ }
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()})
c.maybeInstall(ctx, apexInfo)
}
@@ -2685,6 +2699,14 @@
}
}
+ if len(deps.AidlLibs) > 0 {
+ actx.AddDependency(
+ c,
+ aidlLibraryTag,
+ deps.AidlLibs...,
+ )
+ }
+
updateImportedLibraryDependency(ctx)
}
@@ -2989,6 +3011,17 @@
return
}
+ if depTag == aidlLibraryTag {
+ if ctx.OtherModuleHasProvider(dep, aidl_library.AidlLibraryProvider) {
+ depPaths.AidlLibraryInfos = append(
+ depPaths.AidlLibraryInfos,
+ ctx.OtherModuleProvider(
+ dep,
+ aidl_library.AidlLibraryProvider).(aidl_library.AidlLibraryInfo),
+ )
+ }
+ }
+
ccDep, ok := dep.(LinkableInterface)
if !ok {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3ae4b15..d6b969a 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -24,6 +24,7 @@
"strings"
"testing"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/bazel/cquery"
)
@@ -4419,9 +4420,80 @@
}
}
+func TestAidlLibraryWithHeaders(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ hdrs: ["x/HeaderBar.aidl"],
+ strip_import_prefix: "x",
+ }
+ `)}.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ hdrs: ["a/HeaderFoo.aidl"],
+ strip_import_prefix: "a",
+ deps: ["bar"],
+ }
+ cc_library {
+ name: "libfoo",
+ aidl: {
+ libs: ["foo"],
+ }
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl headers",
+ []string{
+ "package_bar/x/HeaderBar.aidl",
+ "package_foo/a/HeaderFoo.aidl",
+ "package_foo/a/b/Foo.aidl",
+ "out/soong/.intermediates/package_foo/libfoo/android_arm64_armv8-a_static/gen/aidl_library.sbox.textproto",
+ },
+ libfoo.Rule("aidl_library").Implicits,
+ )
+
+ manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl_library.sbox.textproto"))
+ aidlCommand := manifest.Commands[0].GetCommand()
+
+ expectedAidlFlags := "-Ipackage_foo/a -Ipackage_bar/x"
+ if !strings.Contains(aidlCommand, expectedAidlFlags) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlags)
+ }
+
+ outputs := strings.Join(libfoo.AllOutputs(), " ")
+
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/BpFoo.h")
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/BnFoo.h")
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/Foo.h")
+ android.AssertStringDoesContain(t, "aidl-generated cpp", outputs, "b/Foo.cpp")
+ // Confirm that the aidl header doesn't get compiled to cpp and h files
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/BpBar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/BnBar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/Bar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated cpp", outputs, "y/Bar.cpp")
+}
+
func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
t.Parallel()
- ctx := testCc(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ ).RunTestWithBp(t, `
cc_library {
name: "libfoo",
srcs: ["a/Foo.aidl"],
@@ -4491,6 +4563,55 @@
}
}
+func TestInvalidAidlProp(t *testing.T) {
+ t.Parallel()
+
+ testCases := []struct {
+ description string
+ bp string
+ }{
+ {
+ description: "Invalid use of aidl.libs and aidl.include_dirs",
+ bp: `
+ cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["foo_aidl"],
+ include_dirs: ["bar/include"],
+ }
+ }
+ `,
+ },
+ {
+ description: "Invalid use of aidl.libs and aidl.local_include_dirs",
+ bp: `
+ cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["foo_aidl"],
+ local_include_dirs: ["include"],
+ }
+ }
+ `,
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.description, func(t *testing.T) {
+ bp := `
+ aidl_library {
+ name: "foo_aidl",
+ srcs: ["Foo.aidl"],
+ } ` + testCase.bp
+ android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("For aidl headers, please only use aidl.libs prop")),
+ ).RunTestWithBp(t, bp)
+ })
+ }
+}
+
func TestMinSdkVersionInClangTriple(t *testing.T) {
t.Parallel()
ctx := testCc(t, `
@@ -4706,7 +4827,15 @@
})
t.Run("ensure only aidl headers are exported", func(t *testing.T) {
- ctx := testCc(t, genRuleModules+`
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ ).RunTestWithBp(t, `
+ aidl_library {
+ name: "libfoo_aidl",
+ srcs: ["x/y/Bar.aidl"],
+ strip_import_prefix: "x",
+ }
cc_library_shared {
name: "libfoo",
srcs: [
@@ -4715,25 +4844,33 @@
"a.proto",
],
aidl: {
+ libs: ["libfoo_aidl"],
export_aidl_headers: true,
}
}
- `)
+ `).TestContext
foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library
`),
expectedSystemIncludeDirs(``),
expectedGeneratedHeaders(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/Bar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BnBar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BpBar.h
`),
expectedOrderOnlyDeps(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/Bar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BnBar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BpBar.h
`),
)
})
diff --git a/cc/compiler.go b/cc/compiler.go
index 88985b6..16f4a6e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -120,6 +120,9 @@
Lex *LexProperties
Aidl struct {
+ // List of aidl_library modules
+ Libs []string
+
// list of directories that will be added to the aidl include paths.
Include_dirs []string
@@ -272,6 +275,7 @@
deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
deps.GeneratedSources = removeListFromList(deps.GeneratedSources, compiler.Properties.Exclude_generated_sources)
deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
+ deps.AidlLibs = append(deps.AidlLibs, compiler.Properties.Aidl.Libs...)
android.ProtoDeps(ctx, &compiler.Proto)
if compiler.hasSrcExt(".proto") {
@@ -561,7 +565,12 @@
"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
}
- if compiler.hasSrcExt(".aidl") {
+ if len(compiler.Properties.Aidl.Libs) > 0 &&
+ (len(compiler.Properties.Aidl.Include_dirs) > 0 || len(compiler.Properties.Aidl.Local_include_dirs) > 0) {
+ ctx.ModuleErrorf("aidl.libs and (aidl.include_dirs or aidl.local_include_dirs) can't be set at the same time. For aidl headers, please only use aidl.libs prop")
+ }
+
+ if compiler.hasAidl(deps) {
flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
@@ -572,6 +581,14 @@
flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
}
+ var rootAidlIncludeDirs android.Paths
+ for _, aidlLibraryInfo := range deps.AidlLibraryInfos {
+ rootAidlIncludeDirs = append(rootAidlIncludeDirs, aidlLibraryInfo.IncludeDirs.ToList()...)
+ }
+ if len(rootAidlIncludeDirs) > 0 {
+ flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
+ }
+
if proptools.BoolDefault(compiler.Properties.Aidl.Generate_traces, true) {
flags.aidlFlags = append(flags.aidlFlags, "-t")
}
@@ -582,8 +599,14 @@
}
flags.aidlFlags = append(flags.aidlFlags, "--min_sdk_version="+aidlMinSdkVersion)
- flags.Local.CommonFlags = append(flags.Local.CommonFlags,
- "-I"+android.PathForModuleGen(ctx, "aidl").String())
+ if compiler.hasSrcExt(".aidl") {
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags,
+ "-I"+android.PathForModuleGen(ctx, "aidl").String())
+ }
+ if len(deps.AidlLibraryInfos) > 0 {
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags,
+ "-I"+android.PathForModuleGen(ctx, "aidl_library").String())
+ }
}
if compiler.hasSrcExt(".rscript") || compiler.hasSrcExt(".fs") {
@@ -660,6 +683,10 @@
return nil
}
+func (compiler *baseCompiler) hasAidl(deps PathDeps) bool {
+ return len(deps.AidlLibraryInfos) > 0 || compiler.hasSrcExt(".aidl")
+}
+
func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
pathDeps := deps.GeneratedDeps
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
@@ -668,7 +695,7 @@
srcs := append(android.Paths(nil), compiler.srcsBeforeGen...)
- srcs, genDeps, info := genSources(ctx, srcs, buildFlags)
+ srcs, genDeps, info := genSources(ctx, deps.AidlLibraryInfos, srcs, buildFlags)
pathDeps = append(pathDeps, genDeps...)
compiler.pathDeps = pathDeps
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 7aa8b91..452cf35 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -95,6 +95,7 @@
// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
func LibFuzzFactory() android.Module {
module := NewFuzzer(android.HostAndDeviceSupported)
+ module.testModule = true
return module.Init()
}
diff --git a/cc/gen.go b/cc/gen.go
index dfbb177..b15f164 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -18,7 +18,9 @@
"path/filepath"
"strings"
+ "android/soong/aidl_library"
"android/soong/bazel"
+
"github.com/google/blueprint"
"android/soong/android"
@@ -105,7 +107,14 @@
return ret
}
-func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, aidlFlags string) (cppFile android.OutputPath, headerFiles android.Paths) {
+func genAidl(
+ ctx android.ModuleContext,
+ rule *android.RuleBuilder,
+ outDirBase string,
+ aidlFile android.Path,
+ aidlHdrs android.Paths,
+ aidlFlags string,
+) (cppFile android.OutputPath, headerFiles android.Paths) {
aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base())
baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext())
shortName := baseName
@@ -117,20 +126,17 @@
shortName = strings.TrimPrefix(baseName, "I")
}
- outDir := android.PathForModuleGen(ctx, "aidl")
+ outDir := android.PathForModuleGen(ctx, outDirBase)
cppFile = outDir.Join(ctx, aidlPackage, baseName+".cpp")
depFile := outDir.Join(ctx, aidlPackage, baseName+".cpp.d")
headerI := outDir.Join(ctx, aidlPackage, baseName+".h")
headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h")
headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
- baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel())
- if baseDir != "" {
- aidlFlags += " -I" + baseDir
- }
-
cmd := rule.Command()
cmd.BuiltTool("aidl-cpp").
+ // libc++ is default stl for aidl-cpp (a cc_binary_host module)
+ ImplicitTool(ctx.Config().HostCcSharedLibPath(ctx, "libc++")).
FlagWithDepFile("-d", depFile).
Flag("--ninja").
Flag(aidlFlags).
@@ -143,6 +149,10 @@
headerBp,
})
+ if aidlHdrs != nil {
+ cmd.Implicits(aidlHdrs)
+ }
+
return cppFile, android.Paths{
headerI,
headerBn,
@@ -282,15 +292,23 @@
syspropOrderOnlyDeps android.Paths
}
-func genSources(ctx android.ModuleContext, srcFiles android.Paths,
- buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) {
+func genSources(
+ ctx android.ModuleContext,
+ aidlLibraryInfos []aidl_library.AidlLibraryInfo,
+ srcFiles android.Paths,
+ buildFlags builderFlags,
+) (android.Paths, android.Paths, generatedSourceInfo) {
var info generatedSourceInfo
var deps android.Paths
var rsFiles android.Paths
+ // aidlRule supports compiling aidl files from srcs prop while aidlLibraryRule supports
+ // compiling aidl files from aidl_library modules specified in aidl.libs prop.
+ // The rules are separated so that they don't wipe out the other's outputDir
var aidlRule *android.RuleBuilder
+ var aidlLibraryRule *android.RuleBuilder
var yaccRule_ *android.RuleBuilder
yaccRule := func() *android.RuleBuilder {
@@ -330,7 +348,15 @@
aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
}
- cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags)
+ baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
+ cppFile, aidlHeaders := genAidl(
+ ctx,
+ aidlRule,
+ "aidl",
+ srcFile,
+ nil,
+ buildFlags.aidlFlags+" -I"+baseDir,
+ )
srcFiles[i] = cppFile
info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
@@ -352,10 +378,40 @@
}
}
+ for _, aidlLibraryInfo := range aidlLibraryInfos {
+ if aidlLibraryRule == nil {
+ aidlLibraryRule = android.NewRuleBuilder(pctx, ctx).Sbox(
+ android.PathForModuleGen(ctx, "aidl_library"),
+ android.PathForModuleGen(ctx, "aidl_library.sbox.textproto"),
+ ).SandboxInputs()
+ }
+ for _, aidlSrc := range aidlLibraryInfo.Srcs {
+ cppFile, aidlHeaders := genAidl(
+ ctx,
+ aidlLibraryRule,
+ "aidl_library",
+ aidlSrc,
+ aidlLibraryInfo.Hdrs.ToList(),
+ buildFlags.aidlFlags,
+ )
+
+ srcFiles = append(srcFiles, cppFile)
+ info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
+ // Use the generated headers as order only deps to ensure that they are up to date when
+ // needed.
+ // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
+ info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
+ }
+ }
+
if aidlRule != nil {
aidlRule.Build("aidl", "gen aidl")
}
+ if aidlLibraryRule != nil {
+ aidlLibraryRule.Build("aidl_library", "gen aidl_library")
+ }
+
if yaccRule_ != nil {
yaccRule_.Build("yacc", "gen yacc")
}
diff --git a/cc/library.go b/cc/library.go
index 7051f72..d5f5b40 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -271,7 +271,9 @@
Implementation_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
Tags bazel.StringListAttribute
+
sdkAttributes
+ includesAttributes
}
type stripAttributes struct {
@@ -330,6 +332,14 @@
Native_coverage: baseAttributes.Native_coverage,
}
+ includeAttrs := includesAttributes{
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
+ }
+
sharedCommonAttrs := staticOrSharedAttributes{
Srcs: *srcs.Clone().Append(sharedAttrs.Srcs),
Srcs_c: *compilerAttrs.cSrcs.Clone().Append(sharedAttrs.Srcs_c),
@@ -351,41 +361,34 @@
staticTargetAttrs := &bazelCcLibraryStaticAttributes{
staticOrSharedAttributes: staticCommonAttrs,
+ includesAttributes: includeAttrs,
Cppflags: compilerAttrs.cppFlags,
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
Features: baseAttributes.features,
}
sharedTargetAttrs := &bazelCcLibrarySharedAttributes{
staticOrSharedAttributes: sharedCommonAttrs,
- Cppflags: compilerAttrs.cppFlags,
- Conlyflags: compilerAttrs.conlyFlags,
- Asflags: asFlags,
+ includesAttributes: includeAttrs,
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- Linkopts: linkerAttrs.linkopts,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
- Use_version_lib: linkerAttrs.useVersionLib,
+ Cppflags: compilerAttrs.cppFlags,
+ Conlyflags: compilerAttrs.conlyFlags,
+ Asflags: asFlags,
+
+ Linkopts: linkerAttrs.linkopts,
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
+ Use_version_lib: linkerAttrs.useVersionLib,
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
@@ -428,11 +431,11 @@
var tagsForStaticVariant bazel.StringListAttribute
if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
- tagsForStaticVariant = android.ApexAvailableTags(m)
+ tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
}
tagsForStaticVariant.Append(bazel.StringListAttribute{Value: staticAttrs.Apex_available})
- tagsForSharedVariant := android.ApexAvailableTags(m)
+ tagsForSharedVariant := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
tagsForSharedVariant.Append(bazel.StringListAttribute{Value: sharedAttrs.Apex_available})
ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
@@ -2109,9 +2112,15 @@
// Optionally export aidl headers.
if Bool(library.Properties.Aidl.Export_aidl_headers) {
- if library.baseCompiler.hasSrcExt(".aidl") {
- dir := android.PathForModuleGen(ctx, "aidl")
- library.reexportDirs(dir)
+ if library.baseCompiler.hasAidl(deps) {
+ if library.baseCompiler.hasSrcExt(".aidl") {
+ dir := android.PathForModuleGen(ctx, "aidl")
+ library.reexportDirs(dir)
+ }
+ if len(deps.AidlLibraryInfos) > 0 {
+ dir := android.PathForModuleGen(ctx, "aidl_library")
+ library.reexportDirs(dir)
+ }
library.reexportDeps(library.baseCompiler.aidlOrderOnlyDeps...)
library.addExportedGeneratedHeaders(library.baseCompiler.aidlHeaders...)
@@ -2875,6 +2884,13 @@
linkerAttrs := baseAttributes.linkerAttributes
exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &compilerAttrs.includes)
+ includeAttrs := includesAttributes{
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
+ }
// Append shared/static{} stanza properties. These won't be specified on
// cc_library_* itself, but may be specified in cc_defaults that this module
@@ -2929,11 +2945,7 @@
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
+ includesAttributes: includeAttrs,
Cppflags: compilerAttrs.cppFlags,
Conlyflags: compilerAttrs.conlyFlags,
@@ -2959,11 +2971,8 @@
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
+ includesAttributes: includeAttrs,
+
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
@@ -2994,14 +3003,23 @@
Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name(), Tags: tags}, attrs)
}
+type includesAttributes struct {
+ Export_includes bazel.StringListAttribute
+ Export_absolute_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
+ Local_includes bazel.StringListAttribute
+ Absolute_includes bazel.StringListAttribute
+}
+
// TODO(b/199902614): Can this be factored to share with the other Attributes?
type bazelCcLibraryStaticAttributes struct {
staticOrSharedAttributes
+ includesAttributes
Use_version_lib bazel.BoolAttribute
Rtti bazel.BoolAttribute
@@ -3009,12 +3027,7 @@
Cpp_std *string
C_std *string
- Export_includes bazel.StringListAttribute
- Export_absolute_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
Cppflags bazel.StringListAttribute
Conlyflags bazel.StringListAttribute
@@ -3026,6 +3039,7 @@
// TODO(b/199902614): Can this be factored to share with the other Attributes?
type bazelCcLibrarySharedAttributes struct {
staticOrSharedAttributes
+ includesAttributes
Linkopts bazel.StringListAttribute
Use_version_lib bazel.BoolAttribute
@@ -3035,12 +3049,7 @@
Cpp_std *string
C_std *string
- Export_includes bazel.StringListAttribute
- Export_absolute_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
Strip stripAttributes
Additional_linker_inputs bazel.LabelListAttribute
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 1dee726..ce9c4aa 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -151,7 +151,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: module.Name(),
diff --git a/cc/object.go b/cc/object.go
index d65cdea..5d61872 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -226,7 +226,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_object.bzl",
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: m.Name(),
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 0b5841e..44cd0d7 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -389,7 +389,7 @@
name += "_bp2build_cc_library_static"
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
_true := true
@@ -420,7 +420,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
}
@@ -650,7 +650,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
@@ -813,7 +813,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
diff --git a/cc/proto.go b/cc/proto.go
index 97470e5..5d9aef6 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -207,7 +207,7 @@
protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version
name := m.Name() + suffix
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m)
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: rule_class,
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 7fddc1b..e28f537 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -99,6 +99,7 @@
Fuzzer
Memtag_heap
Memtag_stack
+ Memtag_globals
cfi // cfi is last to prevent it running before incompatible mutators
)
@@ -111,6 +112,7 @@
Fuzzer,
Memtag_heap,
Memtag_stack,
+ Memtag_globals,
cfi, // cfi is last to prevent it running before incompatible mutators
}
@@ -133,6 +135,8 @@
return "memtag_heap"
case Memtag_stack:
return "memtag_stack"
+ case Memtag_globals:
+ return "memtag_globals"
case Fuzzer:
return "fuzzer"
default:
@@ -151,6 +155,8 @@
return "memtag_heap"
case Memtag_stack:
return "memtag_stack"
+ case Memtag_globals:
+ return "memtag_globals"
case tsan:
return "thread"
case intOverflow:
@@ -172,7 +178,7 @@
sanitizer := &sanitizerSplitMutator{t}
ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
ctx.Transition(t.variationName(), sanitizer)
- case Memtag_heap, Memtag_stack, intOverflow:
+ case Memtag_heap, Memtag_stack, Memtag_globals, intOverflow:
// do nothing
default:
panic(fmt.Errorf("unknown SanitizerType %d", t))
@@ -213,6 +219,8 @@
return true
case Memtag_stack:
return true
+ case Memtag_globals:
+ return true
default:
return false
}
@@ -267,6 +275,9 @@
// Memory-tagging stack instrumentation, only available on arm64
// Adds instrumentation to detect stack buffer overflows and use-after-scope using MTE.
Memtag_stack *bool `android:"arch_variant"`
+ // Memory-tagging globals instrumentation, only available on arm64
+ // Adds instrumentation to detect global buffer overflows using MTE.
+ Memtag_globals *bool `android:"arch_variant"`
// A modifier for ASAN and HWASAN for write only instrumentation
Writeonly *bool `android:"arch_variant"`
@@ -342,6 +353,8 @@
Memtag_heap *bool `blueprint:"mutated"`
// Whether Memory-tagging stack instrumentation is enabled for this module
Memtag_stack *bool `blueprint:"mutated"`
+ // Whether Memory-tagging globals instrumentation is enabled for this module
+ Memtag_globals *bool `android:"arch_variant"`
// Whether a modifier for ASAN and HWASAN for write only instrumentation is enabled for this
// module
@@ -425,6 +438,7 @@
p.Integer_overflow = userProps.Integer_overflow
p.Memtag_heap = userProps.Memtag_heap
p.Memtag_stack = userProps.Memtag_stack
+ p.Memtag_globals = userProps.Memtag_globals
p.Safestack = userProps.Safestack
p.Scs = userProps.Scs
p.Scudo = userProps.Scudo
@@ -552,6 +566,10 @@
s.Memtag_stack = proptools.BoolPtr(true)
}
+ if found, globalSanitizers = removeFromList("memtag_globals", globalSanitizers); found && s.Memtag_globals == nil {
+ s.Memtag_globals = proptools.BoolPtr(true)
+ }
+
if len(globalSanitizers) > 0 {
ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
}
@@ -632,6 +650,7 @@
if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() || ctx.Host() {
s.Memtag_heap = nil
s.Memtag_stack = nil
+ s.Memtag_globals = nil
}
// Also disable CFI if ASAN is enabled.
@@ -641,6 +660,7 @@
// HWASAN and ASAN win against MTE.
s.Memtag_heap = nil
s.Memtag_stack = nil
+ s.Memtag_globals = nil
}
// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
@@ -696,7 +716,8 @@
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
- Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack)) {
+ Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack) ||
+ Bool(s.Memtag_globals)) {
sanitize.Properties.SanitizerEnabled = true
}
@@ -872,7 +893,7 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-fatal-warnings")
}
- if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack)) && ctx.binary() {
+ if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack) || Bool(sanProps.Memtag_globals)) && ctx.binary() {
if Bool(sanProps.Diag.Memtag_heap) {
flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=sync")
} else {
@@ -995,6 +1016,8 @@
return s.Properties.SanitizeMutated.Memtag_heap
case Memtag_stack:
return s.Properties.SanitizeMutated.Memtag_stack
+ case Memtag_globals:
+ return s.Properties.SanitizeMutated.Memtag_globals
case Fuzzer:
return s.Properties.SanitizeMutated.Fuzzer
default:
@@ -1011,6 +1034,7 @@
!sanitize.isSanitizerEnabled(scs) &&
!sanitize.isSanitizerEnabled(Memtag_heap) &&
!sanitize.isSanitizerEnabled(Memtag_stack) &&
+ !sanitize.isSanitizerEnabled(Memtag_globals) &&
!sanitize.isSanitizerEnabled(Fuzzer)
}
@@ -1032,10 +1056,12 @@
sanitize.Properties.SanitizeMutated.Address = bPtr
// For ASAN variant, we need to disable Memtag_stack
sanitize.Properties.SanitizeMutated.Memtag_stack = nil
+ sanitize.Properties.SanitizeMutated.Memtag_globals = nil
case Hwasan:
sanitize.Properties.SanitizeMutated.Hwaddress = bPtr
// For HWAsan variant, we need to disable Memtag_stack
sanitize.Properties.SanitizeMutated.Memtag_stack = nil
+ sanitize.Properties.SanitizeMutated.Memtag_globals = nil
case tsan:
sanitize.Properties.SanitizeMutated.Thread = bPtr
case intOverflow:
@@ -1049,6 +1075,8 @@
case Memtag_stack:
sanitize.Properties.SanitizeMutated.Memtag_stack = bPtr
// We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant.
+ case Memtag_globals:
+ sanitize.Properties.Sanitize.Memtag_globals = bPtr
case Fuzzer:
sanitize.Properties.SanitizeMutated.Fuzzer = bPtr
default:
@@ -1536,6 +1564,13 @@
sanitizers = append(sanitizers, "memtag-stack")
}
+ if Bool(sanProps.Memtag_globals) {
+ sanitizers = append(sanitizers, "memtag-globals")
+ // TODO(mitchp): For now, enable memtag-heap with memtag-globals because the linker
+ // isn't new enough (https://reviews.llvm.org/differential/changeset/?ref=4243566).
+ sanitizers = append(sanitizers, "memtag-heap")
+ }
+
if Bool(sanProps.Fuzzer) {
sanitizers = append(sanitizers, "fuzzer-no-link")
}
diff --git a/cc/sysprop.go b/cc/sysprop.go
index 0df290a..7ddd476 100644
--- a/cc/sysprop.go
+++ b/cc/sysprop.go
@@ -38,7 +38,7 @@
}
func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "sysprop_library",
diff --git a/cc/test.go b/cc/test.go
index 3f5f710..4b3db01 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -158,6 +158,7 @@
// binary.
func BenchmarkFactory() android.Module {
module := NewBenchmark(android.HostAndDeviceSupported)
+ module.testModule = true
return module.Init()
}
@@ -487,6 +488,7 @@
module, binary := newBinary(hod, bazelable)
module.bazelable = bazelable
module.multilib = android.MultilibBoth
+ module.testModule = true
binary.baseInstaller = NewTestInstaller()
test := &testBinary{
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f5da50e..f532297 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -419,6 +419,7 @@
addLocationLabel(in, inputLocation{paths})
}
}
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
var copyFrom android.Paths
var outputFiles android.WritablePaths
@@ -940,7 +941,7 @@
}
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
if ctx.ModuleType() == "gensrcs" {
// The Output_extension prop is not in an immediately accessible field
diff --git a/java/Android.bp b/java/Android.bp
index 4af2a14..4d1e34e 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -15,6 +15,7 @@
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-testing",
"soong-provenance",
"soong-python",
"soong-remoteexec",
@@ -83,6 +84,7 @@
"app_import_test.go",
"app_set_test.go",
"app_test.go",
+ "code_metadata_test.go",
"bootclasspath_fragment_test.go",
"device_host_converter_test.go",
"dex_test.go",
@@ -109,6 +111,7 @@
"sdk_library_test.go",
"system_modules_test.go",
"systemserver_classpath_fragment_test.go",
+ "test_spec_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/java/app.go b/java/app.go
index 706f99a..e026fea 100755
--- a/java/app.go
+++ b/java/app.go
@@ -21,6 +21,7 @@
"path/filepath"
"strings"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -33,8 +34,17 @@
func init() {
RegisterAppBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("ModifyAllowlistCmd", "modify_permissions_allowlist")
}
+var (
+ modifyAllowlist = pctx.AndroidStaticRule("modifyAllowlist",
+ blueprint.RuleParams{
+ Command: "${ModifyAllowlistCmd} $in $packageName $out",
+ CommandDeps: []string{"${ModifyAllowlistCmd}"},
+ }, "packageName")
+)
+
func RegisterAppBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_app", AndroidAppFactory)
ctx.RegisterModuleType("android_test", AndroidTestFactory)
@@ -115,6 +125,9 @@
// Prefer using other specific properties if build behaviour must be changed; avoid using this
// flag for anything but neverallow rules (unless the behaviour change is invisible to owners).
Updatable *bool
+
+ // Specifies the file that contains the allowlist for this app.
+ Privapp_allowlist *string `android:"path"`
}
// android_app properties that can be overridden by override_android_app
@@ -179,6 +192,8 @@
android.ApexBundleDepsInfo
javaApiUsedByOutputFile android.ModuleOutPath
+
+ privAppAllowlist android.OptionalPath
}
func (a *AndroidApp) IsInstallable() bool {
@@ -205,6 +220,10 @@
return a.jniCoverageOutputs
}
+func (a *AndroidApp) PrivAppAllowlist() android.OptionalPath {
+ return a.privAppAllowlist
+}
+
var _ AndroidLibraryDependency = (*AndroidApp)(nil)
type Certificate struct {
@@ -269,6 +288,16 @@
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+ if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) {
+ // There are a few uids that are explicitly considered privileged regardless of their
+ // app's location. Bluetooth is one such app. It should arguably be moved to priv-app,
+ // but for now, allow it not to be in priv-app.
+ privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth"
+ if !privilegedBecauseOfUid {
+ ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)")
+ }
+ }
+
for _, cert := range a.appProperties.Additional_certificates {
cert = android.SrcIsModule(cert)
if cert != "" {
@@ -290,6 +319,17 @@
a.generateJavaUsedByApex(ctx)
}
+func (a *AndroidApp) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ defaultMinSdkVersion := a.Module.MinSdkVersion(ctx)
+ if proptools.Bool(a.appProperties.Updatable) {
+ overrideApiLevel := android.MinSdkVersionFromValue(ctx, ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride())
+ if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(defaultMinSdkVersion) > 0 {
+ return overrideApiLevel
+ }
+ }
+ return defaultMinSdkVersion
+}
+
func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if a.Updatable() {
if !a.SdkVersion(ctx).Stable() {
@@ -591,7 +631,6 @@
}
}
-
return mainCertificate, certificates
}
@@ -599,6 +638,35 @@
return a.installApkName
}
+func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.Path {
+ if a.appProperties.Privapp_allowlist == nil {
+ return nil
+ }
+
+ isOverrideApp := a.GetOverriddenBy() != ""
+ if !isOverrideApp {
+ // if this is not an override, we don't need to rewrite the existing privapp allowlist
+ return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist)
+ }
+
+ if a.overridableAppProperties.Package_name == nil {
+ ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist")
+ }
+
+ packageName := *a.overridableAppProperties.Package_name
+ fileName := "privapp_allowlist_" + packageName + ".xml"
+ outPath := android.PathForModuleOut(ctx, fileName).OutputPath
+ ctx.Build(pctx, android.BuildParams{
+ Rule: modifyAllowlist,
+ Input: android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist),
+ Output: outPath,
+ Args: map[string]string{
+ "packageName": packageName,
+ },
+ })
+ return &outPath
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
@@ -734,11 +802,21 @@
BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
a.bundleFile = bundleFile
+ allowlist := a.createPrivappAllowlist(ctx)
+ if allowlist != nil {
+ a.privAppAllowlist = android.OptionalPathForPath(allowlist)
+ }
+
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
// Install the app package.
- if (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() &&
- !a.appProperties.PreventInstall {
+ shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
+ if shouldInstallAppPackage {
+ if a.privAppAllowlist.Valid() {
+ allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions")
+ allowlistInstallFilename := a.installApkName + ".xml"
+ ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path())
+ }
var extraInstalledPaths android.Paths
for _, extra := range a.extraOutputFiles {
@@ -925,6 +1003,10 @@
// For OutputFileProducer interface
func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
switch tag {
+ // In some instances, it can be useful to reference the aapt-generated flags from another
+ // target, e.g., system server implements services declared in the framework-res manifest.
+ case ".aapt.proguardOptionsFile":
+ return []android.Path{a.proguardOptionsFile}, nil
case ".aapt.srcjar":
return []android.Path{a.aaptSrcJar}, nil
case ".export-package.apk":
@@ -1043,6 +1125,7 @@
a.testConfig = a.FixTestConfig(ctx, testConfig)
a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
diff --git a/java/app_import.go b/java/app_import.go
index 85b35eb..3097d7f 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -376,6 +376,10 @@
return a.provenanceMetaDataFile
}
+func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath {
+ return android.OptionalPath{}
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
diff --git a/java/app_test.go b/java/app_test.go
index b154bc9..f078021 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3547,3 +3547,170 @@
android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
+
+func TestPrivappAllowlist(t *testing.T) {
+ testJavaError(t, "privileged must be set in order to use privapp_allowlist", `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "perms.xml",
+ }
+ `)
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ app := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("foo", "android_common_bar")
+
+ // verify that privapp allowlist is created for override apps
+ overrideApp.Output("out/soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml")
+ expectedAllowlistInput := "privapp_allowlist_com.android.foo.xml"
+ overrideActualAllowlistInput := overrideApp.Rule("modifyAllowlist").Input.String()
+ if expectedAllowlistInput != overrideActualAllowlistInput {
+ t.Errorf("expected override allowlist to be %q; got %q", expectedAllowlistInput, overrideActualAllowlistInput)
+ }
+
+ // verify that permissions are copied to device
+ app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml")
+ overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml")
+}
+
+func TestPrivappAllowlistAndroidMk(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ baseApp := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("foo", "android_common_bar")
+
+ baseAndroidApp := baseApp.Module().(*AndroidApp)
+ baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk:\\S+/target/product/test_device/system/priv-app/foo/foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml",
+ )
+
+ overrideAndroidApp := overrideApp.Module().(*AndroidApp)
+ overrideEntries := android.AndroidMkEntriesForTest(t, result.TestContext, overrideAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk:\\S+/target/product/test_device/system/priv-app/bar/bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
+ )
+}
+
+func TestApexGlobalMinSdkVersionOverride(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.ApexGlobalMinSdkVersionOverride = proptools.StringPtr("Tiramisu")
+ }),
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.bar",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "S",
+ updatable: true,
+ }
+ override_android_app {
+ name: "com.android.go.foo",
+ base: "com.android.foo",
+ }
+ `)
+ foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer")
+ bar := result.ModuleForTests("com.android.bar", "android_common").Rule("manifestFixer")
+
+ android.AssertStringDoesContain(t,
+ "expected manifest fixer to set com.android.bar minSdkVersion to S",
+ bar.BuildParams.Args["args"],
+ "--minSdkVersion S",
+ )
+ android.AssertStringDoesContain(t,
+ "com.android.foo: expected manifest fixer to set minSdkVersion to T",
+ foo.BuildParams.Args["args"],
+ "--minSdkVersion T",
+ )
+ android.AssertStringDoesContain(t,
+ "com.android.go.foo: expected manifest fixer to set minSdkVersion to T",
+ fooOverride.BuildParams.Args["args"],
+ "--minSdkVersion T",
+ )
+
+}
diff --git a/java/base.go b/java/base.go
index 9911323..025fc7e 100644
--- a/java/base.go
+++ b/java/base.go
@@ -22,6 +22,7 @@
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
+ "github.com/google/blueprint"
"android/soong/android"
"android/soong/dexpreopt"
@@ -1105,6 +1106,7 @@
uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
j.uniqueSrcFiles = uniqueSrcFiles
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()})
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 108fdd4..f815954 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -23,6 +23,7 @@
"android/soong/android"
"android/soong/dexpreopt"
+ "android/soong/testing"
"github.com/google/blueprint/proptools"
@@ -564,6 +565,7 @@
if ctx.Module() != ctx.FinalModule() {
b.HideFromMake()
}
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go
new file mode 100644
index 0000000..4b05d9e
--- /dev/null
+++ b/java/code_metadata_test.go
@@ -0,0 +1,125 @@
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ soongTesting "android/soong/testing"
+ "android/soong/testing/code_metadata_internal_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestCodeMetadata(t *testing.T) {
+ bp := `code_metadata {
+ name: "module-name",
+ teamId: "12345",
+ code: [
+ "foo",
+ ]
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }`
+ result := runCodeMetadataTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests(
+ "module-name", "",
+ ).Module().(*soongTesting.CodeMetadataModule)
+
+ // Check that the provider has the right contents
+ data := result.ModuleProvider(
+ module, soongTesting.CodeMetadataProviderKey,
+ ).(soongTesting.CodeMetadataProviderData)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateCodeMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ buildParamsSlice := module.BuildParamsForTests()
+ var metadata = ""
+ for _, params := range buildParamsSlice {
+ if params.Rule.String() == "android/soong/android.writeFile" {
+ metadata = params.Args["content"]
+ }
+ }
+
+ metadataList := make([]*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, 2)
+ teamId := "12345"
+ bpFilePath := "Android.bp"
+ targetName := "foo"
+ srcFile := []string{"a.java"}
+ expectedMetadataProto := code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TrendyTeamId: &teamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ SourceFiles: srcFile,
+ }
+ metadataList = append(metadataList, &expectedMetadataProto)
+
+ CodeMetadataMetadata := code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList}
+ protoData, _ := proto.Marshal(&CodeMetadataMetadata)
+ rawData := string(protoData)
+ formattedData := strings.ReplaceAll(rawData, "\n", "\\n")
+ expectedMetadata := "'" + formattedData + "\\n'"
+
+ if metadata != expectedMetadata {
+ t.Errorf(
+ "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata,
+ expectedMetadata,
+ )
+ }
+
+ // Tests for all_test_spec singleton.
+ singleton := result.SingletonForTests("all_code_metadata")
+ rule := singleton.Rule("all_code_metadata_rule")
+ prebuiltOs := result.Config.PrebuiltOS()
+ expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule code_metadata -inputFile out/soong/all_code_metadata_paths.rsp -outputFile out/soong/ownership/all_code_metadata.pb"
+ expectedOutputFile := "out/soong/ownership/all_code_metadata.pb"
+ expectedInputFile := "out/soong/.intermediates/module-name/intermediateCodeMetadata.pb"
+ if !strings.Contains(
+ strings.TrimSpace(rule.Output.String()),
+ expectedOutputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s",
+ rule.Output.String(), expectedOutputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.Inputs[0].String()),
+ expectedInputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s",
+ rule.Inputs[0].String(), expectedInputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.RuleParams.Command),
+ expectedCmd,
+ ) {
+ t.Errorf(
+ "Retrieved cmd: %s doesn't contain expectedCmd: %s",
+ rule.RuleParams.Command, expectedCmd,
+ )
+ }
+}
+func runCodeMetadataTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents, prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index dbe021d..1f9f773 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -694,7 +694,6 @@
cmd := rule.Command().
BuiltTool("soong_javac_wrapper").Tool(config.JavadocCmd(ctx)).
Flag(config.JavacVmFlags).
- FlagWithArg("-encoding ", "UTF-8").
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "javadoc.rsp"), srcs).
FlagWithInput("@", srcJarList)
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 8a521aa..ea9305f 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -152,6 +152,10 @@
// API surface of this module. If set, the module contributes to an API surface.
// For the full list of available API surfaces, refer to soong/android/sdk_version.go
Api_surface *string
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
}
// Used by xsd_config
@@ -512,17 +516,16 @@
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
- FlagWithArg("-source ", javaVersion.String()).
+ FlagWithArg("--java-source ", javaVersion.String()).
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
FlagWithInput("@", srcJarList)
- if len(bootclasspath) > 0 {
- cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
- }
-
- if len(classpath) > 0 {
- cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":")
+ // Metalava does not differentiate between bootclasspath and classpath and has not done so for
+ // years, so it is unlikely to change any time soon.
+ combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
+ combinedPaths = append(combinedPaths, classpath.Paths()...)
+ if len(combinedPaths) > 0 {
+ cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
cmd.Flag("--no-banner").
@@ -535,6 +538,16 @@
// b/223382732
FlagWithArg("--hide ", "ChangedDefault")
+ // Force metalava to ignore classes on the classpath when an API file contains missing classes.
+ // See b/285140653 for more information.
+ cmd.FlagWithArg("--api-class-resolution ", "api")
+
+ // Force metalava to sort overloaded methods by their order in the source code.
+ // See b/285312164 for more information.
+ // And add concrete overrides of abstract methods, see b/299366704 for more
+ // information.
+ cmd.FlagWithArg("--format-defaults ", "overloaded-method-order=source,add-additional-overrides=yes")
+
return cmd
}
@@ -688,6 +701,13 @@
cmd.FlagWithArg("--error-message:compatibility:released ", msg)
}
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
+ // Pass the current API file into metalava so it can use it as the basis for determining how to
+ // generate the output signature files (both api and removed).
+ currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
+ cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
+ }
+
if generateStubs {
rule.Command().
BuiltTool("soong_zip").
diff --git a/java/java.go b/java/java.go
index 0eb2518..e7def4b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -26,7 +26,7 @@
"android/soong/bazel"
"android/soong/bazel/cquery"
"android/soong/remoteexec"
-
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -1063,6 +1063,10 @@
return true
}
+func (j *TestHost) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+ return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
if len(j.testHostProperties.Data_device_bins_first) > 0 {
deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
@@ -1199,10 +1203,12 @@
}
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.generateAndroidBuildActionsWithConfig(ctx, nil)
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
@@ -1710,7 +1716,6 @@
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
FlagWithInputList("--source-files ", srcs, " ")
cmd.Flag("--no-banner").
@@ -1728,6 +1733,14 @@
FlagWithArg("--hide ", "InvalidNullabilityOverride").
FlagWithArg("--hide ", "ChangedDefault")
+ // Force metalava to ignore classes on the classpath when an API file contains missing classes.
+ // See b/285140653 for more information.
+ cmd.FlagWithArg("--api-class-resolution ", "api")
+
+ // Force metalava to sort overloaded methods by their order in the source code.
+ // See b/285312164 for more information.
+ cmd.FlagWithArg("--api-overloaded-method-order ", "source")
+
return cmd
}
@@ -2841,7 +2854,7 @@
return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
})
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
if !aidlSrcs.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 206d995..0740467 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -135,6 +135,19 @@
mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
}
+func createLatestApiModuleExtensionVersionFile(mctx android.LoadHookContext, name string, version string) {
+ genruleProps := struct {
+ Name *string
+ Srcs []string
+ Out []string
+ Cmd *string
+ }{}
+ genruleProps.Name = proptools.StringPtr(name)
+ genruleProps.Out = []string{name}
+ genruleProps.Cmd = proptools.StringPtr("echo " + version + " > $(out)")
+ mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
+}
+
func createEmptyFile(mctx android.LoadHookContext, name string) {
props := struct {
Name *string
@@ -233,9 +246,10 @@
type latestApiInfo struct {
module, scope, path string
version int
+ isExtensionApiFile bool
}
- getLatest := func(files []string) map[string]latestApiInfo {
+ getLatest := func(files []string, isExtensionApiFile bool) map[string]latestApiInfo {
m := make(map[string]latestApiInfo)
for _, f := range files {
module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
@@ -245,16 +259,16 @@
key := module + "." + scope
info, exists := m[key]
if !exists || version > info.version {
- m[key] = latestApiInfo{module, scope, f, version}
+ m[key] = latestApiInfo{module, scope, f, version, isExtensionApiFile}
}
}
return m
}
- latest := getLatest(apiLevelFiles)
+ latest := getLatest(apiLevelFiles, false)
if p.properties.Extensions_dir != nil {
extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
- for k, v := range getLatest(extensionApiFiles) {
+ for k, v := range getLatest(extensionApiFiles, true) {
if _, exists := latest[k]; !exists {
mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
}
@@ -267,6 +281,12 @@
for _, k := range android.SortedKeys(latest) {
info := latest[k]
name := PrebuiltApiModuleName(info.module, info.scope, "latest")
+ latestExtensionVersionModuleName := PrebuiltApiModuleName(info.module, info.scope, "latest.extension_version")
+ if info.isExtensionApiFile {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, strconv.Itoa(info.version))
+ } else {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, "-1")
+ }
createApiModule(mctx, name, info.path)
}
diff --git a/java/robolectric.go b/java/robolectric.go
index 008b8b1..f394006 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -22,6 +22,7 @@
"android/soong/android"
"android/soong/java/config"
+ "android/soong/testing"
"android/soong/tradefed"
"github.com/google/blueprint/proptools"
@@ -235,6 +236,7 @@
}
r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 103f1ac..d461882 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -571,6 +571,10 @@
Enabled *bool
}
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
+
// TODO: determines whether to create HTML doc or not
// Html_doc *bool
}
@@ -1678,11 +1682,28 @@
"MissingPermission",
"SdkConstant",
"Todo",
- "Typo",
"UnavailableSymbol",
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
+ droidstubsFiles := append([]string{}, module.sdkLibraryProperties.Droiddoc_option_files...)
+
+ // If requested hide the flagged APIs from the output of metalava. This
+ // should be implemented in the module SDK snapshot code by depending on
+ // special metalava rules that hide the flagged APIs but that will take
+ // lots of work. In the meantime, this is a temporary workaround that
+ // can and will only be used when building module SDK snapshots. This
+ // delegates the decision as to what options are passed to metalava to
+ // the "sdkext-released-flagged-apis" module by using metalava's support
+ // for expanding an argument of the form "@<file>" to the list of
+ // arguments found in <file>.
+ if mctx.Config().GetenvWithDefault("SOONG_SDK_SNAPSHOT_HIDE_FLAGGED_APIS", "false") == "true" {
+ metalavaHideFlaggedApisSource := ":sdkext-released-flagged-apis"
+ droidstubsArgs = append(droidstubsArgs,
+ fmt.Sprintf("@$(location %s)", metalavaHideFlaggedApisSource))
+ droidstubsFiles = append(droidstubsFiles, metalavaHideFlaggedApisSource)
+ }
+
// Output Javadoc comments for public scope.
if apiScope == apiScopePublic {
props.Output_javadoc_comments = proptools.BoolPtr(true)
@@ -1690,7 +1711,7 @@
// Add in scope specific arguments.
droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
- props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
+ props.Arg_files = droidstubsFiles
props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
// List of APIs identified from the provided source files are created. They are later
diff --git a/java/test_spec_test.go b/java/test_spec_test.go
new file mode 100644
index 0000000..7f06785
--- /dev/null
+++ b/java/test_spec_test.go
@@ -0,0 +1,133 @@
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ soongTesting "android/soong/testing"
+ "android/soong/testing/test_spec_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestTestSpec(t *testing.T) {
+ bp := `test_spec {
+ name: "module-name",
+ teamId: "12345",
+ tests: [
+ "java-test-module-name-one",
+ "java-test-module-name-two"
+ ]
+ }
+
+ java_test {
+ name: "java-test-module-name-one",
+ }
+
+ java_test {
+ name: "java-test-module-name-two",
+ }`
+ result := runTestSpecTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests(
+ "module-name", "",
+ ).Module().(*soongTesting.TestSpecModule)
+
+ // Check that the provider has the right contents
+ data := result.ModuleProvider(
+ module, soongTesting.TestSpecProviderKey,
+ ).(soongTesting.TestSpecProviderData)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ buildParamsSlice := module.BuildParamsForTests()
+ var metadata = ""
+ for _, params := range buildParamsSlice {
+ if params.Rule.String() == "android/soong/android.writeFile" {
+ metadata = params.Args["content"]
+ }
+ }
+
+ metadataList := make([]*test_spec_proto.TestSpec_OwnershipMetadata, 0, 2)
+ teamId := "12345"
+ bpFilePath := "Android.bp"
+ targetNames := []string{
+ "java-test-module-name-one", "java-test-module-name-two",
+ }
+
+ for _, test := range targetNames {
+ targetName := test
+ metadata := test_spec_proto.TestSpec_OwnershipMetadata{
+ TrendyTeamId: &teamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ }
+ metadataList = append(metadataList, &metadata)
+ }
+ testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList}
+ protoData, _ := proto.Marshal(&testSpecMetadata)
+ rawData := string(protoData)
+ formattedData := strings.ReplaceAll(rawData, "\n", "\\n")
+ expectedMetadata := "'" + formattedData + "\\n'"
+
+ if metadata != expectedMetadata {
+ t.Errorf(
+ "Retrieved metadata: %s doesn't contain expectedMetadata: %s", metadata,
+ expectedMetadata,
+ )
+ }
+
+ // Tests for all_test_spec singleton.
+ singleton := result.SingletonForTests("all_test_specs")
+ rule := singleton.Rule("all_test_specs_rule")
+ prebuiltOs := result.Config.PrebuiltOS()
+ expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb"
+ expectedOutputFile := "out/soong/ownership/all_test_specs.pb"
+ expectedInputFile := "out/soong/.intermediates/module-name/intermediateTestSpecMetadata.pb"
+ if !strings.Contains(
+ strings.TrimSpace(rule.Output.String()),
+ expectedOutputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s",
+ rule.Output.String(), expectedOutputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.Inputs[0].String()),
+ expectedInputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s",
+ rule.Inputs[0].String(), expectedInputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.RuleParams.Command),
+ expectedCmd,
+ ) {
+ t.Errorf(
+ "Retrieved cmd: %s is not equal to expectedCmd: %s",
+ rule.RuleParams.Command, expectedCmd,
+ )
+ }
+}
+
+func runTestSpecTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents,
+ PrepareForIntegrationTestWithJava,
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/python/Android.bp b/python/Android.bp
index 7578673..87810c9 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -10,6 +10,7 @@
"soong-android",
"soong-tradefed",
"soong-cc",
+ "soong-testing",
],
srcs: [
"binary.go",
diff --git a/python/python.go b/python/python.go
index 1a12973..353cc65 100644
--- a/python/python.go
+++ b/python/python.go
@@ -404,6 +404,7 @@
// GenerateAndroidBuildActions performs build actions common to all Python modules
func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: expandedSrcs.Strings()})
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
diff --git a/python/test.go b/python/test.go
index 31da17e..18da72a 100644
--- a/python/test.go
+++ b/python/test.go
@@ -17,6 +17,7 @@
import (
"fmt"
+ "android/soong/testing"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -159,6 +160,7 @@
p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath})
}
}
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/rust/Android.bp b/rust/Android.bp
index b01a94a..c5b2000 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -12,6 +12,7 @@
"soong-cc",
"soong-rust-config",
"soong-snapshot",
+ "soong-testing",
],
srcs: [
"afdo.go",
diff --git a/rust/rust.go b/rust/rust.go
index 7b520cd..fdc7849 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -19,6 +19,7 @@
"fmt"
"strings"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -139,8 +140,9 @@
Properties BaseProperties
- hod android.HostOrDeviceSupported
- multilib android.Multilib
+ hod android.HostOrDeviceSupported
+ multilib android.Multilib
+ testModule bool
makeLinkType string
@@ -956,6 +958,7 @@
sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
}
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()})
}
if mod.compiler != nil && !mod.compiler.Disabled() {
@@ -1007,6 +1010,9 @@
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
}
+ if mod.testModule {
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ }
}
func (mod *Module) deps(ctx DepsContext) Deps {
diff --git a/rust/test.go b/rust/test.go
index 4b5296e..7ffc367 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -222,11 +222,13 @@
// rustTestHostMultilib load hook to set MultilibFirst for the
// host target.
android.AddLoadHook(module, rustTestHostMultilib)
+ module.testModule = true
return module.Init()
}
func RustTestHostFactory() android.Module {
module, _ := NewRustTest(android.HostSupported)
+ module.testModule = true
return module.Init()
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 9367ff0..97f6ab4 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -237,3 +237,20 @@
name: "jars-to-module-info-java",
src: "jars-to-module-info-java.sh",
}
+
+python_binary_host {
+ name: "modify_permissions_allowlist",
+ main: "modify_permissions_allowlist.py",
+ srcs: [
+ "modify_permissions_allowlist.py",
+ ],
+}
+
+python_test_host {
+ name: "modify_permissions_allowlist_test",
+ main: "modify_permissions_allowlist_test.py",
+ srcs: [
+ "modify_permissions_allowlist_test.py",
+ "modify_permissions_allowlist.py",
+ ],
+}
diff --git a/scripts/modify_permissions_allowlist.py b/scripts/modify_permissions_allowlist.py
new file mode 100755
index 0000000..38ec7ec
--- /dev/null
+++ b/scripts/modify_permissions_allowlist.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""A tool for modifying privileged permission allowlists."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+from xml.dom import minidom
+
+
+class InvalidRootNodeException(Exception):
+ pass
+
+
+class InvalidNumberOfPrivappPermissionChildren(Exception):
+ pass
+
+
+def modify_allowlist(allowlist_dom, package_name):
+ if allowlist_dom.documentElement.tagName != 'permissions':
+ raise InvalidRootNodeException
+ nodes = allowlist_dom.getElementsByTagName('privapp-permissions')
+ if nodes.length != 1:
+ raise InvalidNumberOfPrivappPermissionChildren
+ privapp_permissions = nodes[0]
+ privapp_permissions.setAttribute('package', package_name)
+
+
+def parse_args():
+ """Parse commandline arguments."""
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input', help='input allowlist template file')
+ parser.add_argument(
+ 'package_name', help='package name to use in the allowlist'
+ )
+ parser.add_argument('output', help='output allowlist file')
+
+ return parser.parse_args()
+
+
+def main():
+ try:
+ args = parse_args()
+ doc = minidom.parse(args.input)
+ modify_allowlist(doc, args.package_name)
+ with open(args.output, 'w') as output_file:
+ doc.writexml(output_file, encoding='utf-8')
+ except Exception as err:
+ print('error: ' + str(err), file=sys.stderr)
+ sys.exit(-1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/modify_permissions_allowlist_test.py b/scripts/modify_permissions_allowlist_test.py
new file mode 100755
index 0000000..ee8b12c
--- /dev/null
+++ b/scripts/modify_permissions_allowlist_test.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for modify_permissions_allowlist.py."""
+
+from __future__ import print_function
+
+import unittest
+
+from xml.dom import minidom
+
+from modify_permissions_allowlist import InvalidRootNodeException, InvalidNumberOfPrivappPermissionChildren, modify_allowlist
+
+
+class ModifyPermissionsAllowlistTest(unittest.TestCase):
+
+ def test_invalid_root(self):
+ xml_data = '<foo></foo>'
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(InvalidRootNodeException, modify_allowlist, xml_dom, 'x')
+
+ def test_no_packages(self):
+ xml_data = '<permissions></permissions>'
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(
+ InvalidNumberOfPrivappPermissionChildren, modify_allowlist, xml_dom, 'x'
+ )
+
+ def test_multiple_packages(self):
+ xml_data = (
+ '<permissions>'
+ ' <privapp-permissions package="foo.bar"></privapp-permissions>'
+ ' <privapp-permissions package="bar.baz"></privapp-permissions>'
+ '</permissions>'
+ )
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(
+ InvalidNumberOfPrivappPermissionChildren, modify_allowlist, xml_dom, 'x'
+ )
+
+ def test_modify_package_name(self):
+ xml_data = (
+ '<permissions>'
+ ' <privapp-permissions package="foo.bar">'
+ ' <permission name="myperm1"/>'
+ ' </privapp-permissions>'
+ '</permissions>'
+ )
+ xml_dom = minidom.parseString(xml_data)
+ modify_allowlist(xml_dom, 'bar.baz')
+ expected_data = (
+ '<?xml version="1.0" ?>'
+ '<permissions>'
+ ' <privapp-permissions package="bar.baz">'
+ ' <permission name="myperm1"/>'
+ ' </privapp-permissions>'
+ '</permissions>'
+ )
+ self.assertEqual(expected_data, xml_dom.toxml())
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/sdk/Android.bp b/sdk/Android.bp
index f42b478..f436320 100644
--- a/sdk/Android.bp
+++ b/sdk/Android.bp
@@ -18,6 +18,7 @@
"bp.go",
"build_release.go",
"exports.go",
+ "genrule.go",
"member_trait.go",
"member_type.go",
"sdk.go",
@@ -30,6 +31,7 @@
"cc_sdk_test.go",
"compat_config_sdk_test.go",
"exports_test.go",
+ "genrule_test.go",
"java_sdk_test.go",
"license_sdk_test.go",
"member_trait_test.go",
diff --git a/sdk/genrule.go b/sdk/genrule.go
new file mode 100644
index 0000000..347ab05
--- /dev/null
+++ b/sdk/genrule.go
@@ -0,0 +1,44 @@
+// Copyright 2023 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 sdk
+
+import (
+ "android/soong/android"
+ "android/soong/genrule"
+)
+
+func init() {
+ registerGenRuleBuildComponents(android.InitRegistrationContext)
+}
+
+func registerGenRuleBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sdk_genrule", SdkGenruleFactory)
+}
+
+// sdk_genrule_host is a genrule that can depend on sdk and sdk_snapshot module types
+//
+// What this means is that it's a genrule with only the "common_os" variant.
+// sdk modules have 3 variants: host, android, and common_os. The common_os one depends
+// on the host/device ones and packages their result into a final snapshot zip.
+// Genrules probably want access to this snapshot zip when they depend on an sdk module,
+// which means they want to depend on the common_os variant and not the host/android
+// variants.
+func SdkGenruleFactory() android.Module {
+ module := genrule.NewGenRule()
+
+ android.InitCommonOSAndroidMultiTargetsArchModule(module, android.NeitherHostNorDeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
+ return module
+}
diff --git a/sdk/genrule_test.go b/sdk/genrule_test.go
new file mode 100644
index 0000000..6e52a3d
--- /dev/null
+++ b/sdk/genrule_test.go
@@ -0,0 +1,52 @@
+// Copyright 2018 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 sdk
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/genrule"
+ "android/soong/java"
+)
+
+func TestSdkGenrule(t *testing.T) {
+ // Test that an sdk_genrule can depend on an sdk, and that a genrule can depend on an sdk_genrule
+ bp := `
+ sdk {
+ name: "my_sdk",
+ }
+ sdk_genrule {
+ name: "my_sdk_genrule",
+ tool_files: ["tool"],
+ cmd: "$(location tool) $(in) $(out)",
+ srcs: [":my_sdk"],
+ out: ["out"],
+ }
+ genrule {
+ name: "my_regular_genrule",
+ srcs: [":my_sdk_genrule"],
+ out: ["out"],
+ cmd: "cp $(in) $(out)",
+ }
+ `
+ android.GroupFixturePreparers(
+ // if java components aren't registered, the sdk module doesn't create a snapshot for some reason.
+ java.PrepareForTestWithJavaBuildComponents,
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+ PrepareForTestWithSdkBuildComponents,
+ android.FixtureRegisterWithContext(registerGenRuleBuildComponents),
+ ).RunTestWithBp(t, bp)
+}
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 4d4a2a2..fd16ab6 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -222,6 +222,18 @@
}}
}
+func (s *sdk) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ if s.snapshotFile.Valid() {
+ return []android.Path{s.snapshotFile.Path()}, nil
+ }
+ return nil, fmt.Errorf("snapshot file not defined. This is most likely because this isn't the common_os variant of this module")
+ default:
+ return nil, fmt.Errorf("unknown tag %q", tag)
+ }
+}
+
// gatherTraits gathers the traits from the dynamically generated trait specific properties.
//
// Returns a map from member name to the set of required traits.
diff --git a/sh/Android.bp b/sh/Android.bp
index f9198dc..2341a12 100644
--- a/sh/Android.bp
+++ b/sh/Android.bp
@@ -10,6 +10,7 @@
"soong",
"soong-android",
"soong-cc",
+ "soong-testing",
"soong-tradefed",
],
srcs: [
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index c921ca6..d5e9d42 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -20,6 +20,7 @@
"sort"
"strings"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -260,6 +261,7 @@
Output: s.outputFilePath,
Input: s.sourceFilePath,
})
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: []string{s.sourceFilePath.String()}})
}
func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -426,6 +428,7 @@
ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
}
})
+ ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (s *ShTest) InstallInData() bool {
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0edbb7c..61fabae 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -241,12 +241,13 @@
// generated java_library will depend on these API files.
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
baseModuleName := m.BaseModuleName()
-
- for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) {
+ srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
+ for _, syspropFile := range srcs {
if syspropFile.Ext() != ".sysprop" {
ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
}
}
+ ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
if ctx.Failed() {
return
@@ -264,7 +265,7 @@
rule.Command().
BuiltTool("sysprop_api_dump").
Output(m.dumpedApiFile).
- Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
+ Inputs(srcs)
rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump")
// check API rule
diff --git a/testing/Android.bp b/testing/Android.bp
new file mode 100644
index 0000000..43040b0
--- /dev/null
+++ b/testing/Android.bp
@@ -0,0 +1,24 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing",
+ pkgPath: "android/soong/testing",
+ deps: [
+ "blueprint",
+ "soong-android",
+ "soong-testing-code_metadata_internal_proto",
+ "soong-testing-test_spec_proto",
+
+ ],
+ srcs: [
+ "all_code_metadata.go",
+ "all_test_specs.go",
+ "code_metadata.go",
+ "test_spec.go",
+ "init.go",
+ "test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/testing/OWNERS b/testing/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/all_code_metadata.go b/testing/all_code_metadata.go
new file mode 100644
index 0000000..16d7aae
--- /dev/null
+++ b/testing/all_code_metadata.go
@@ -0,0 +1,51 @@
+package testing
+
+import (
+ "android/soong/android"
+)
+
+const fileContainingCodeMetadataFilePaths = "all_code_metadata_paths.rsp"
+const allCodeMetadataFile = "all_code_metadata.pb"
+
+func AllCodeMetadataFactory() android.Singleton {
+ return &allCodeMetadataSingleton{}
+}
+
+type allCodeMetadataSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath android.OutputPath
+}
+
+func (this *allCodeMetadataSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var intermediateMetadataPaths android.Paths
+
+ ctx.VisitAllModules(
+ func(module android.Module) {
+ if !ctx.ModuleHasProvider(module, CodeMetadataProviderKey) {
+ return
+ }
+ intermediateMetadataPaths = append(
+ intermediateMetadataPaths, ctx.ModuleProvider(
+ module, CodeMetadataProviderKey,
+ ).(CodeMetadataProviderData).IntermediatePath,
+ )
+ },
+ )
+
+ rspFile := android.PathForOutput(ctx, fileContainingCodeMetadataFilePaths)
+ this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allCodeMetadataFile)
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command().
+ BuiltTool("metadata").
+ FlagWithArg("-rule ", "code_metadata").
+ FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths)
+ cmd.FlagWithOutput("-outputFile ", this.outputPath)
+ rule.Build("all_code_metadata_rule", "Generate all code metadata")
+
+ ctx.Phony("all_code_metadata", this.outputPath)
+}
+
+func (this *allCodeMetadataSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("code_metadata", this.outputPath)
+}
diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go
new file mode 100644
index 0000000..9d4645b
--- /dev/null
+++ b/testing/all_test_specs.go
@@ -0,0 +1,45 @@
+package testing
+
+import (
+ "android/soong/android"
+)
+
+const ownershipDirectory = "ownership"
+const fileContainingFilePaths = "all_test_spec_paths.rsp"
+const allTestSpecsFile = "all_test_specs.pb"
+
+func AllTestSpecsFactory() android.Singleton {
+ return &allTestSpecsSingleton{}
+}
+
+type allTestSpecsSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath android.OutputPath
+}
+
+func (this *allTestSpecsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var intermediateMetadataPaths android.Paths
+
+ ctx.VisitAllModules(func(module android.Module) {
+ if !ctx.ModuleHasProvider(module, TestSpecProviderKey) {
+ return
+ }
+ intermediateMetadataPaths = append(intermediateMetadataPaths, ctx.ModuleProvider(module, TestSpecProviderKey).(TestSpecProviderData).IntermediatePath)
+ })
+
+ rspFile := android.PathForOutput(ctx, fileContainingFilePaths)
+ this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allTestSpecsFile)
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command().
+ BuiltTool("metadata").
+ FlagWithArg("-rule ", "test_spec").
+ FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths)
+ cmd.FlagWithOutput("-outputFile ", this.outputPath)
+ rule.Build("all_test_specs_rule", "Generate all test specifications")
+ ctx.Phony("all_test_specs", this.outputPath)
+}
+
+func (this *allTestSpecsSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("test_specs", this.outputPath)
+}
diff --git a/testing/code_metadata.go b/testing/code_metadata.go
new file mode 100644
index 0000000..4550283
--- /dev/null
+++ b/testing/code_metadata.go
@@ -0,0 +1,139 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package testing
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+ "android/soong/testing/code_metadata_internal_proto"
+ "github.com/google/blueprint"
+ "google.golang.org/protobuf/proto"
+)
+
+func CodeMetadataFactory() android.Module {
+ module := &CodeMetadataModule{}
+
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+type CodeMetadataModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.BazelModuleBase
+
+ // Properties for "code_metadata"
+ properties struct {
+ // Specifies the name of the code_config.
+ Name string
+ // Specifies the team ID.
+ TeamId string
+ // Specifies the list of modules that this code_metadata covers.
+ Code []string
+ // An optional field to specify if multiple ownerships for source files is allowed.
+ MultiOwnership bool
+ }
+}
+
+type codeDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var codeDepTag = codeDepTagType{}
+
+func (module *CodeMetadataModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Validate Properties
+ if len(module.properties.TeamId) == 0 {
+ ctx.PropertyErrorf(
+ "TeamId",
+ "Team Id not found in the code_metadata module. Hint: Maybe the teamId property hasn't been properly specified.",
+ )
+ }
+ if !isInt(module.properties.TeamId) {
+ ctx.PropertyErrorf(
+ "TeamId", "Invalid value for Team ID. The Team ID must be an integer.",
+ )
+ }
+ if len(module.properties.Code) == 0 {
+ ctx.PropertyErrorf(
+ "Code",
+ "Targets to be attributed cannot be empty. Hint: Maybe the code property hasn't been properly specified.",
+ )
+ }
+ ctx.AddDependency(ctx.Module(), codeDepTag, module.properties.Code...)
+}
+
+// Provider published by CodeMetadata
+type CodeMetadataProviderData struct {
+ IntermediatePath android.WritablePath
+}
+
+var CodeMetadataProviderKey = blueprint.NewProvider(CodeMetadataProviderData{})
+
+func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ metadataList := make(
+ []*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0,
+ len(module.properties.Code),
+ )
+ bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile())
+
+ for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) {
+ targetName := m.Name()
+ var moduleSrcs []string
+ if ctx.OtherModuleHasProvider(m, blueprint.SrcsFileProviderKey) {
+ moduleSrcs = ctx.OtherModuleProvider(
+ m, blueprint.SrcsFileProviderKey,
+ ).(blueprint.SrcsFileProviderData).SrcPaths
+ }
+ if module.properties.MultiOwnership {
+ metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TargetName: &targetName,
+ TrendyTeamId: &module.properties.TeamId,
+ Path: &bpFilePath,
+ MultiOwnership: &module.properties.MultiOwnership,
+ SourceFiles: moduleSrcs,
+ }
+ metadataList = append(metadataList, metadata)
+ } else {
+ metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TargetName: &targetName,
+ TrendyTeamId: &module.properties.TeamId,
+ Path: &bpFilePath,
+ SourceFiles: moduleSrcs,
+ }
+ metadataList = append(metadataList, metadata)
+ }
+
+ }
+ codeMetadata := &code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList}
+ protoData, err := proto.Marshal(codeMetadata)
+ if err != nil {
+ ctx.ModuleErrorf("Error marshaling code metadata: %s", err.Error())
+ return
+ }
+ intermediatePath := android.PathForModuleOut(
+ ctx, "intermediateCodeMetadata.pb",
+ )
+ android.WriteFileRule(ctx, intermediatePath, string(protoData))
+
+ ctx.SetProvider(
+ CodeMetadataProviderKey,
+ CodeMetadataProviderData{IntermediatePath: intermediatePath},
+ )
+}
diff --git a/testing/code_metadata_internal_proto/Android.bp b/testing/code_metadata_internal_proto/Android.bp
new file mode 100644
index 0000000..a534cc2
--- /dev/null
+++ b/testing/code_metadata_internal_proto/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-code_metadata_internal_proto",
+ pkgPath: "android/soong/testing/code_metadata_internal_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "code_metadata_internal.pb.go",
+ ],
+}
diff --git a/testing/code_metadata_internal_proto/OWNERS b/testing/code_metadata_internal_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/code_metadata_internal_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.pb.go b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go
new file mode 100644
index 0000000..ecb8b86
--- /dev/null
+++ b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go
@@ -0,0 +1,277 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: code_metadata_internal.proto
+
+package code_metadata_internal_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CodeMetadataInternal struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all code targets and their metadata.
+ TargetOwnershipList []*CodeMetadataInternal_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"`
+}
+
+func (x *CodeMetadataInternal) Reset() {
+ *x = CodeMetadataInternal{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_internal_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadataInternal) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadataInternal) ProtoMessage() {}
+
+func (x *CodeMetadataInternal) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_internal_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadataInternal.ProtoReflect.Descriptor instead.
+func (*CodeMetadataInternal) Descriptor() ([]byte, []int) {
+ return file_code_metadata_internal_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CodeMetadataInternal) GetTargetOwnershipList() []*CodeMetadataInternal_TargetOwnership {
+ if x != nil {
+ return x.TargetOwnershipList
+ }
+ return nil
+}
+
+type CodeMetadataInternal_TargetOwnership struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"`
+ // OPTIONAL: Specify if multiple ownerships of the source files are allowed.
+ MultiOwnership *bool `protobuf:"varint,5,opt,name=multi_ownership,json=multiOwnership" json:"multi_ownership,omitempty"`
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) Reset() {
+ *x = CodeMetadataInternal_TargetOwnership{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_internal_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadataInternal_TargetOwnership) ProtoMessage() {}
+
+func (x *CodeMetadataInternal_TargetOwnership) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_internal_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadataInternal_TargetOwnership.ProtoReflect.Descriptor instead.
+func (*CodeMetadataInternal_TargetOwnership) Descriptor() ([]byte, []int) {
+ return file_code_metadata_internal_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetSourceFiles() []string {
+ if x != nil {
+ return x.SourceFiles
+ }
+ return nil
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetMultiOwnership() bool {
+ if x != nil && x.MultiOwnership != nil {
+ return *x.MultiOwnership
+ }
+ return false
+}
+
+var File_code_metadata_internal_proto protoreflect.FileDescriptor
+
+var file_code_metadata_internal_proto_rawDesc = []byte{
+ 0x0a, 0x1c, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c,
+ 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x02, 0x0a,
+ 0x14, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x76, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
+ 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
+ 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0xb8, 0x01,
+ 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79,
+ 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+ 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
+ 0x27, 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68,
+ 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x42, 0x34, 0x5a, 0x32, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_code_metadata_internal_proto_rawDescOnce sync.Once
+ file_code_metadata_internal_proto_rawDescData = file_code_metadata_internal_proto_rawDesc
+)
+
+func file_code_metadata_internal_proto_rawDescGZIP() []byte {
+ file_code_metadata_internal_proto_rawDescOnce.Do(func() {
+ file_code_metadata_internal_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_internal_proto_rawDescData)
+ })
+ return file_code_metadata_internal_proto_rawDescData
+}
+
+var file_code_metadata_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_code_metadata_internal_proto_goTypes = []interface{}{
+ (*CodeMetadataInternal)(nil), // 0: code_metadata_internal_proto.CodeMetadataInternal
+ (*CodeMetadataInternal_TargetOwnership)(nil), // 1: code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership
+}
+var file_code_metadata_internal_proto_depIdxs = []int32{
+ 1, // 0: code_metadata_internal_proto.CodeMetadataInternal.target_ownership_list:type_name -> code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_code_metadata_internal_proto_init() }
+func file_code_metadata_internal_proto_init() {
+ if File_code_metadata_internal_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_code_metadata_internal_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadataInternal); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_code_metadata_internal_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadataInternal_TargetOwnership); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_code_metadata_internal_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_code_metadata_internal_proto_goTypes,
+ DependencyIndexes: file_code_metadata_internal_proto_depIdxs,
+ MessageInfos: file_code_metadata_internal_proto_msgTypes,
+ }.Build()
+ File_code_metadata_internal_proto = out.File
+ file_code_metadata_internal_proto_rawDesc = nil
+ file_code_metadata_internal_proto_goTypes = nil
+ file_code_metadata_internal_proto_depIdxs = nil
+}
diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.proto b/testing/code_metadata_internal_proto/code_metadata_internal.proto
new file mode 100644
index 0000000..14edc0f
--- /dev/null
+++ b/testing/code_metadata_internal_proto/code_metadata_internal.proto
@@ -0,0 +1,40 @@
+// 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.
+
+syntax = "proto2";
+package code_metadata_internal_proto;
+option go_package = "android/soong/testing/code_metadata_internal_proto";
+
+message CodeMetadataInternal {
+
+ message TargetOwnership {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ repeated string source_files = 4;
+
+ // OPTIONAL: Specify if multiple ownerships of the source files are allowed.
+ optional bool multi_ownership = 5;
+ }
+
+ // List of all code targets and their metadata.
+ repeated TargetOwnership target_ownership_list = 1;
+}
diff --git a/testing/code_metadata_internal_proto/regen.sh b/testing/code_metadata_internal_proto/regen.sh
new file mode 100644
index 0000000..f101a02
--- /dev/null
+++ b/testing/code_metadata_internal_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. code_metadata_internal.proto
diff --git a/testing/code_metadata_proto/Android.bp b/testing/code_metadata_proto/Android.bp
new file mode 100644
index 0000000..8fcca19
--- /dev/null
+++ b/testing/code_metadata_proto/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-code_metadata_proto",
+ pkgPath: "android/soong/testing/code_metadata_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "code_metadata.pb.go",
+ ],
+}
diff --git a/testing/code_metadata_proto/OWNERS b/testing/code_metadata_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/code_metadata_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/code_metadata_proto/code_metadata.pb.go b/testing/code_metadata_proto/code_metadata.pb.go
new file mode 100644
index 0000000..711bf7a
--- /dev/null
+++ b/testing/code_metadata_proto/code_metadata.pb.go
@@ -0,0 +1,263 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: code_metadata.proto
+
+package code_metadata_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CodeMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all code targets and their metadata.
+ TargetOwnershipList []*CodeMetadata_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"`
+}
+
+func (x *CodeMetadata) Reset() {
+ *x = CodeMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadata) ProtoMessage() {}
+
+func (x *CodeMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadata.ProtoReflect.Descriptor instead.
+func (*CodeMetadata) Descriptor() ([]byte, []int) {
+ return file_code_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CodeMetadata) GetTargetOwnershipList() []*CodeMetadata_TargetOwnership {
+ if x != nil {
+ return x.TargetOwnershipList
+ }
+ return nil
+}
+
+type CodeMetadata_TargetOwnership struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"`
+}
+
+func (x *CodeMetadata_TargetOwnership) Reset() {
+ *x = CodeMetadata_TargetOwnership{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadata_TargetOwnership) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadata_TargetOwnership) ProtoMessage() {}
+
+func (x *CodeMetadata_TargetOwnership) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadata_TargetOwnership.ProtoReflect.Descriptor instead.
+func (*CodeMetadata_TargetOwnership) Descriptor() ([]byte, []int) {
+ return file_code_metadata_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *CodeMetadata_TargetOwnership) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetSourceFiles() []string {
+ if x != nil {
+ return x.SourceFiles
+ }
+ return nil
+}
+
+var File_code_metadata_proto protoreflect.FileDescriptor
+
+var file_code_metadata_proto_rawDesc = []byte{
+ 0x0a, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x02, 0x0a, 0x0c, 0x43,
+ 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, 0x15, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f,
+ 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x64,
+ 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61,
+ 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69,
+ 0x73, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e,
+ 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74,
+ 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49,
+ 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+ 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46,
+ 0x69, 0x6c, 0x65, 0x73, 0x42, 0x2b, 0x5a, 0x29, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f,
+ 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f,
+}
+
+var (
+ file_code_metadata_proto_rawDescOnce sync.Once
+ file_code_metadata_proto_rawDescData = file_code_metadata_proto_rawDesc
+)
+
+func file_code_metadata_proto_rawDescGZIP() []byte {
+ file_code_metadata_proto_rawDescOnce.Do(func() {
+ file_code_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_proto_rawDescData)
+ })
+ return file_code_metadata_proto_rawDescData
+}
+
+var file_code_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_code_metadata_proto_goTypes = []interface{}{
+ (*CodeMetadata)(nil), // 0: code_metadata_proto.CodeMetadata
+ (*CodeMetadata_TargetOwnership)(nil), // 1: code_metadata_proto.CodeMetadata.TargetOwnership
+}
+var file_code_metadata_proto_depIdxs = []int32{
+ 1, // 0: code_metadata_proto.CodeMetadata.target_ownership_list:type_name -> code_metadata_proto.CodeMetadata.TargetOwnership
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_code_metadata_proto_init() }
+func file_code_metadata_proto_init() {
+ if File_code_metadata_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_code_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_code_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadata_TargetOwnership); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_code_metadata_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_code_metadata_proto_goTypes,
+ DependencyIndexes: file_code_metadata_proto_depIdxs,
+ MessageInfos: file_code_metadata_proto_msgTypes,
+ }.Build()
+ File_code_metadata_proto = out.File
+ file_code_metadata_proto_rawDesc = nil
+ file_code_metadata_proto_goTypes = nil
+ file_code_metadata_proto_depIdxs = nil
+}
diff --git a/testing/code_metadata_proto/code_metadata.proto b/testing/code_metadata_proto/code_metadata.proto
new file mode 100644
index 0000000..2548363
--- /dev/null
+++ b/testing/code_metadata_proto/code_metadata.proto
@@ -0,0 +1,37 @@
+// 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.
+
+syntax = "proto2";
+package code_metadata_proto;
+option go_package = "android/soong/testing/code_metadata_proto";
+
+message CodeMetadata {
+
+ message TargetOwnership {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ repeated string source_files = 4;
+ }
+
+ // List of all code targets and their metadata.
+ repeated TargetOwnership target_ownership_list = 1;
+}
diff --git a/testing/code_metadata_proto/regen.sh b/testing/code_metadata_proto/regen.sh
new file mode 100644
index 0000000..ffe06f7
--- /dev/null
+++ b/testing/code_metadata_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. code_metadata.proto
diff --git a/testing/init.go b/testing/init.go
new file mode 100644
index 0000000..290efc6
--- /dev/null
+++ b/testing/init.go
@@ -0,0 +1,35 @@
+// 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 testing
+
+import (
+ "android/soong/android"
+)
+
+var (
+ pctx = android.NewPackageContext("android/soong/testing")
+)
+
+func init() {
+ RegisterBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("metadata", "metadata")
+}
+
+func RegisterBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("code_metadata", CodeMetadataFactory)
+ ctx.RegisterModuleType("test_spec", TestSpecFactory)
+ ctx.RegisterSingletonType("all_test_specs", AllTestSpecsFactory)
+ ctx.RegisterSingletonType("all_code_metadata", AllCodeMetadataFactory)
+}
diff --git a/testing/test.go b/testing/test.go
new file mode 100644
index 0000000..cd97a8f
--- /dev/null
+++ b/testing/test.go
@@ -0,0 +1,21 @@
+// Copyright 2023 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 testing
+
+import (
+ "android/soong/android"
+)
+
+var PrepareForTestWithTestingBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
diff --git a/testing/test_spec.go b/testing/test_spec.go
new file mode 100644
index 0000000..c370f71
--- /dev/null
+++ b/testing/test_spec.go
@@ -0,0 +1,127 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package testing
+
+import (
+ "path/filepath"
+ "strconv"
+
+ "android/soong/android"
+ "android/soong/testing/test_spec_proto"
+ "github.com/google/blueprint"
+ "google.golang.org/protobuf/proto"
+)
+
+// ErrTestModuleDataNotFound is the error message for missing test module provider data.
+const ErrTestModuleDataNotFound = "The module '%s' does not provide test specification data. Hint: This issue could arise if either the module is not a valid testing module or if it lacks the required 'TestModuleProviderKey' provider.\n"
+
+func TestSpecFactory() android.Module {
+ module := &TestSpecModule{}
+
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+type TestSpecModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.BazelModuleBase
+
+ // Properties for "test_spec"
+ properties struct {
+ // Specifies the name of the test config.
+ Name string
+ // Specifies the team ID.
+ TeamId string
+ // Specifies the list of tests covered under this module.
+ Tests []string
+ }
+}
+
+type testsDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var testsDepTag = testsDepTagType{}
+
+func (module *TestSpecModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Validate Properties
+ if len(module.properties.TeamId) == 0 {
+ ctx.PropertyErrorf("TeamId", "Team Id not found in the test_spec module. Hint: Maybe the TeamId property hasn't been properly specified.")
+ }
+ if !isInt(module.properties.TeamId) {
+ ctx.PropertyErrorf("TeamId", "Invalid value for Team ID. The Team ID must be an integer.")
+ }
+ if len(module.properties.Tests) == 0 {
+ ctx.PropertyErrorf("Tests", "Expected to attribute some test but none found. Hint: Maybe the test property hasn't been properly specified.")
+ }
+ ctx.AddDependency(ctx.Module(), testsDepTag, module.properties.Tests...)
+}
+func isInt(s string) bool {
+ _, err := strconv.Atoi(s)
+ return err == nil
+}
+
+// Provider published by TestSpec
+type TestSpecProviderData struct {
+ IntermediatePath android.WritablePath
+}
+
+var TestSpecProviderKey = blueprint.NewProvider(TestSpecProviderData{})
+
+type TestModuleProviderData struct {
+}
+
+var TestModuleProviderKey = blueprint.NewProvider(TestModuleProviderData{})
+
+func (module *TestSpecModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ for _, m := range ctx.GetDirectDepsWithTag(testsDepTag) {
+ if !ctx.OtherModuleHasProvider(m, TestModuleProviderKey) {
+ ctx.ModuleErrorf(ErrTestModuleDataNotFound, m.Name())
+ }
+ }
+ bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile())
+ metadataList := make(
+ []*test_spec_proto.TestSpec_OwnershipMetadata, 0,
+ len(module.properties.Tests),
+ )
+ for _, test := range module.properties.Tests {
+ targetName := test
+ metadata := test_spec_proto.TestSpec_OwnershipMetadata{
+ TrendyTeamId: &module.properties.TeamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ }
+ metadataList = append(metadataList, &metadata)
+ }
+ intermediatePath := android.PathForModuleOut(
+ ctx, "intermediateTestSpecMetadata.pb",
+ )
+ testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList}
+ protoData, err := proto.Marshal(&testSpecMetadata)
+ if err != nil {
+ ctx.ModuleErrorf("Error: %s", err.Error())
+ }
+ android.WriteFileRule(ctx, intermediatePath, string(protoData))
+
+ ctx.SetProvider(
+ TestSpecProviderKey, TestSpecProviderData{
+ IntermediatePath: intermediatePath,
+ },
+ )
+}
diff --git a/testing/test_spec_proto/Android.bp b/testing/test_spec_proto/Android.bp
new file mode 100644
index 0000000..1cac492
--- /dev/null
+++ b/testing/test_spec_proto/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-test_spec_proto",
+ pkgPath: "android/soong/testing/test_spec_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "test_spec.pb.go",
+ ],
+}
diff --git a/testing/test_spec_proto/OWNERS b/testing/test_spec_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/test_spec_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/test_spec_proto/regen.sh b/testing/test_spec_proto/regen.sh
new file mode 100644
index 0000000..2cf8203
--- /dev/null
+++ b/testing/test_spec_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. test_spec.proto
diff --git a/testing/test_spec_proto/test_spec.pb.go b/testing/test_spec_proto/test_spec.pb.go
new file mode 100644
index 0000000..5cce600
--- /dev/null
+++ b/testing/test_spec_proto/test_spec.pb.go
@@ -0,0 +1,244 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: test_spec.proto
+
+package test_spec_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type TestSpec struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all test targets and their metadata.
+ OwnershipMetadataList []*TestSpec_OwnershipMetadata `protobuf:"bytes,1,rep,name=ownership_metadata_list,json=ownershipMetadataList" json:"ownership_metadata_list,omitempty"`
+}
+
+func (x *TestSpec) Reset() {
+ *x = TestSpec{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_spec_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TestSpec) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestSpec) ProtoMessage() {}
+
+func (x *TestSpec) ProtoReflect() protoreflect.Message {
+ mi := &file_test_spec_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestSpec.ProtoReflect.Descriptor instead.
+func (*TestSpec) Descriptor() ([]byte, []int) {
+ return file_test_spec_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *TestSpec) GetOwnershipMetadataList() []*TestSpec_OwnershipMetadata {
+ if x != nil {
+ return x.OwnershipMetadataList
+ }
+ return nil
+}
+
+type TestSpec_OwnershipMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+}
+
+func (x *TestSpec_OwnershipMetadata) Reset() {
+ *x = TestSpec_OwnershipMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_spec_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TestSpec_OwnershipMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestSpec_OwnershipMetadata) ProtoMessage() {}
+
+func (x *TestSpec_OwnershipMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_test_spec_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestSpec_OwnershipMetadata.ProtoReflect.Descriptor instead.
+func (*TestSpec_OwnershipMetadata) Descriptor() ([]byte, []int) {
+ return file_test_spec_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *TestSpec_OwnershipMetadata) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *TestSpec_OwnershipMetadata) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *TestSpec_OwnershipMetadata) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+var File_test_spec_proto protoreflect.FileDescriptor
+
+var file_test_spec_proto_rawDesc = []byte{
+ 0x0a, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x22, 0xdf, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12,
+ 0x63, 0x0a, 0x17, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4f, 0x77, 0x6e, 0x65,
+ 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x15, 0x6f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x6e, 0x0a, 0x11, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+ 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61,
+ 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24,
+ 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65,
+ 0x61, 0x6d, 0x49, 0x64, 0x42, 0x27, 0x5a, 0x25, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x74, 0x65,
+ 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_test_spec_proto_rawDescOnce sync.Once
+ file_test_spec_proto_rawDescData = file_test_spec_proto_rawDesc
+)
+
+func file_test_spec_proto_rawDescGZIP() []byte {
+ file_test_spec_proto_rawDescOnce.Do(func() {
+ file_test_spec_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_spec_proto_rawDescData)
+ })
+ return file_test_spec_proto_rawDescData
+}
+
+var file_test_spec_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_test_spec_proto_goTypes = []interface{}{
+ (*TestSpec)(nil), // 0: test_spec_proto.TestSpec
+ (*TestSpec_OwnershipMetadata)(nil), // 1: test_spec_proto.TestSpec.OwnershipMetadata
+}
+var file_test_spec_proto_depIdxs = []int32{
+ 1, // 0: test_spec_proto.TestSpec.ownership_metadata_list:type_name -> test_spec_proto.TestSpec.OwnershipMetadata
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_test_spec_proto_init() }
+func file_test_spec_proto_init() {
+ if File_test_spec_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_test_spec_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TestSpec); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_test_spec_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TestSpec_OwnershipMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_test_spec_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_test_spec_proto_goTypes,
+ DependencyIndexes: file_test_spec_proto_depIdxs,
+ MessageInfos: file_test_spec_proto_msgTypes,
+ }.Build()
+ File_test_spec_proto = out.File
+ file_test_spec_proto_rawDesc = nil
+ file_test_spec_proto_goTypes = nil
+ file_test_spec_proto_depIdxs = nil
+}
diff --git a/testing/test_spec_proto/test_spec.proto b/testing/test_spec_proto/test_spec.proto
new file mode 100644
index 0000000..86bc789
--- /dev/null
+++ b/testing/test_spec_proto/test_spec.proto
@@ -0,0 +1,33 @@
+// 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.
+
+syntax = "proto2";
+package test_spec_proto;
+option go_package = "android/soong/testing/test_spec_proto";
+
+message TestSpec {
+
+ message OwnershipMetadata {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+ }
+
+ // List of all test targets and their metadata.
+ repeated OwnershipMetadata ownership_metadata_list = 1;
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index bf4aec9..31031eb 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1370,6 +1370,19 @@
return v
}
}
+ return c.rbeTmpDir()
+}
+
+func (c *configImpl) rbeDownloadTmpDir() string {
+ for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return c.rbeTmpDir()
+}
+
+func (c *configImpl) rbeTmpDir() string {
buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
return filepath.Join(buildTmpDir, "rbe")
}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 6479925..58c6930 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -55,13 +55,14 @@
func getRBEVars(ctx Context, config Config) map[string]string {
vars := map[string]string{
- "RBE_log_dir": config.rbeProxyLogsDir(),
- "RBE_re_proxy": config.rbeReproxy(),
- "RBE_exec_root": config.rbeExecRoot(),
- "RBE_output_dir": config.rbeProxyLogsDir(),
- "RBE_proxy_log_dir": config.rbeProxyLogsDir(),
- "RBE_cache_dir": config.rbeCacheDir(),
- "RBE_platform": "container-image=" + remoteexec.DefaultImage,
+ "RBE_log_dir": config.rbeProxyLogsDir(),
+ "RBE_re_proxy": config.rbeReproxy(),
+ "RBE_exec_root": config.rbeExecRoot(),
+ "RBE_output_dir": config.rbeProxyLogsDir(),
+ "RBE_proxy_log_dir": config.rbeProxyLogsDir(),
+ "RBE_cache_dir": config.rbeCacheDir(),
+ "RBE_download_tmp_dir": config.rbeDownloadTmpDir(),
+ "RBE_platform": "container-image=" + remoteexec.DefaultImage,
}
if config.StartRBE() {
name, err := config.rbeSockAddr(absPath(ctx, config.TempDir()))