blob: 18a050f5d2b5215beddc103f7820a8cc37cca1e3 [file] [log] [blame]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08001package android
2
3import (
Ronald Braunstein4a2f3682024-08-15 13:34:46 -07004 "path"
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08005 "path/filepath"
6
Yu Liu663e4502024-08-12 18:23:59 +00007 "android/soong/android/team_proto"
8
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08009 "google.golang.org/protobuf/proto"
10)
11
12const ownershipDirectory = "ownership"
13const allTeamsFile = "all_teams.pb"
14
15func AllTeamsFactory() Singleton {
16 return &allTeamsSingleton{}
17}
18
19func init() {
20 registerAllTeamBuildComponents(InitRegistrationContext)
21}
22
23func registerAllTeamBuildComponents(ctx RegistrationContext) {
24 ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
25}
26
27// For each module, list the team or the bpFile the module is defined in.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070028type moduleTeamAndTestInfo struct {
29 // Name field from bp file for the team
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080030 teamName string
Ronald Braunsteinc5603092024-03-27 06:46:47 -070031 // Blueprint file the module is located in.
32 bpFile string
33 // Is this module only used by tests.
34 testOnly bool
35 // Is this a directly testable target by running the module directly
36 // or via tradefed.
37 topLevelTestTarget bool
38 // String name indicating the module, like `java_library` for reporting.
39 kind string
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080040}
41
42type allTeamsSingleton struct {
43 // Path where the collected metadata is stored after successful validation.
44 outputPath OutputPath
45
46 // Map of all package modules we visit during GenerateBuildActions
47 packages map[string]packageProperties
48 // Map of all team modules we visit during GenerateBuildActions
49 teams map[string]teamProperties
50 // Keeps track of team information or bp file for each module we visit.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070051 teams_for_mods map[string]moduleTeamAndTestInfo
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080052}
53
54// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
55// If not ascend up to the parent directory and do the same.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070056func (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080057 // return the Default_team listed in the package if is there.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070058 if p, ok := t.packages[bpFilePath]; ok {
59 if defaultTeam := p.Default_team; defaultTeam != nil {
60 return t.teams[*defaultTeam], true
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080061 }
62 }
63 // Strip a directory and go up.
64 // Does android/paths.go basePath,SourcePath help?
65 current, base := filepath.Split(bpFilePath)
66 current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
67 parent, _ := filepath.Split(current)
68 if current == "." {
69 return teamProperties{}, false
70 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -070071 return t.lookupDefaultTeam(filepath.Join(parent, base))
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080072}
73
Ronald Braunsteinc5603092024-03-27 06:46:47 -070074// Visit all modules and collect all teams and use WriteFileRuleVerbatim
75// to write it out.
76func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
77 t.packages = make(map[string]packageProperties)
78 t.teams = make(map[string]teamProperties)
79 t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080080
Yu Liu95cef3a2025-02-25 00:54:20 +000081 ctx.VisitAllModuleProxies(func(module ModuleProxy) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080082 bpFile := ctx.BlueprintFile(module)
83
84 // Package Modules and Team Modules are stored in a map so we can look them up by name for
85 // modules without a team.
Yu Liu95cef3a2025-02-25 00:54:20 +000086 if pack, ok := OtherModuleProvider(ctx, module, PackageInfoProvider); ok {
Ronald Braunsteinc5603092024-03-27 06:46:47 -070087 // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context.
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080088 pkgKey := bpFile
Yu Liu95cef3a2025-02-25 00:54:20 +000089 t.packages[pkgKey] = pack.Properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080090 return
91 }
Yu Liu95cef3a2025-02-25 00:54:20 +000092 if team, ok := OtherModuleProvider(ctx, module, TeamInfoProvider); ok {
93 t.teams[module.Name()] = team.Properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080094 return
95 }
96
Ronald Braunsteinc864b242024-04-16 07:33:52 -070097 testModInfo := TestModuleInformation{}
Yu Liu663e4502024-08-12 18:23:59 +000098 if tmi, ok := OtherModuleProvider(ctx, module, TestOnlyProviderKey); ok {
Ronald Braunsteinc864b242024-04-16 07:33:52 -070099 testModInfo = tmi
100 }
101
102 // Some modules, like java_test_host don't set the provider when the module isn't enabled:
103 // test_only, top_level
104 // AVFHostTestCases{os:linux_glibc,arch:common} {true true}
105 // AVFHostTestCases{os:windows,arch:common} {false false}
106 // Generally variant information of true override false or unset.
107 if testModInfo.TestOnly == false {
108 if prevValue, exists := t.teams_for_mods[module.Name()]; exists {
109 if prevValue.testOnly == true {
110 return
111 }
112 }
113 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700114 entry := moduleTeamAndTestInfo{
115 bpFile: bpFile,
116 testOnly: testModInfo.TestOnly,
117 topLevelTestTarget: testModInfo.TopLevelTarget,
118 kind: ctx.ModuleType(module),
Yu Liuf22120f2025-03-13 18:36:35 +0000119 teamName: OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Team,
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800120 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700121 t.teams_for_mods[module.Name()] = entry
122
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800123 })
124
125 // Visit all modules again and lookup the team name in the package or parent package if the team
126 // isn't assignged at the module level.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700127 allTeams := t.lookupTeamForAllModules()
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800128
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700129 t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800130 data, err := proto.Marshal(allTeams)
131 if err != nil {
132 ctx.Errorf("Unable to marshal team data. %s", err)
133 }
134
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700135 WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
136 ctx.Phony("all_teams", t.outputPath)
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700137 ctx.DistForGoal("all_teams", t.outputPath)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800138}
139
140// Visit every (non-package, non-team) module and write out a proto containing
141// either the declared team data for that module or the package default team data for that module.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700142func (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
143 teamsProto := make([]*team_proto.Team, len(t.teams_for_mods))
144 for i, moduleName := range SortedKeys(t.teams_for_mods) {
145 m, _ := t.teams_for_mods[moduleName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800146 teamName := m.teamName
147 var teamProperties teamProperties
148 found := false
149 if teamName != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700150 teamProperties, found = t.teams[teamName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800151 } else {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700152 teamProperties, found = t.lookupDefaultTeam(m.bpFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800153 }
Ronald Braunstein4a2f3682024-08-15 13:34:46 -0700154 // Deal with one blueprint file including another by looking up the default
155 // in the main Android.bp rather than one listed with "build = [My.bp]"
156 if !found {
157 teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp"))
158 }
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800159
160 trendy_team_id := ""
161 if found {
162 trendy_team_id = *teamProperties.Trendy_team_id
163 }
164
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800165 teamData := new(team_proto.Team)
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700166 *teamData = team_proto.Team{
167 TargetName: proto.String(moduleName),
168 Path: proto.String(m.bpFile),
169 TestOnly: proto.Bool(m.testOnly),
170 TopLevelTarget: proto.Bool(m.topLevelTestTarget),
171 Kind: proto.String(m.kind),
172 }
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800173 if trendy_team_id != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700174 teamData.TrendyTeamId = proto.String(trendy_team_id)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800175 } else {
176 // Clients rely on the TrendyTeamId optional field not being set.
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800177 }
178 teamsProto[i] = teamData
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800179 }
180 return &team_proto.AllTeams{Teams: teamsProto}
181}