1*333d2b36SAndroid Build Coastguard Workerpackage android 2*333d2b36SAndroid Build Coastguard Worker 3*333d2b36SAndroid Build Coastguard Workerimport ( 4*333d2b36SAndroid Build Coastguard Worker "path" 5*333d2b36SAndroid Build Coastguard Worker "path/filepath" 6*333d2b36SAndroid Build Coastguard Worker 7*333d2b36SAndroid Build Coastguard Worker "android/soong/android/team_proto" 8*333d2b36SAndroid Build Coastguard Worker 9*333d2b36SAndroid Build Coastguard Worker "google.golang.org/protobuf/proto" 10*333d2b36SAndroid Build Coastguard Worker) 11*333d2b36SAndroid Build Coastguard Worker 12*333d2b36SAndroid Build Coastguard Workerconst ownershipDirectory = "ownership" 13*333d2b36SAndroid Build Coastguard Workerconst allTeamsFile = "all_teams.pb" 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerfunc AllTeamsFactory() Singleton { 16*333d2b36SAndroid Build Coastguard Worker return &allTeamsSingleton{} 17*333d2b36SAndroid Build Coastguard Worker} 18*333d2b36SAndroid Build Coastguard Worker 19*333d2b36SAndroid Build Coastguard Workerfunc init() { 20*333d2b36SAndroid Build Coastguard Worker registerAllTeamBuildComponents(InitRegistrationContext) 21*333d2b36SAndroid Build Coastguard Worker} 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Workerfunc registerAllTeamBuildComponents(ctx RegistrationContext) { 24*333d2b36SAndroid Build Coastguard Worker ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) 25*333d2b36SAndroid Build Coastguard Worker} 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Worker// For each module, list the team or the bpFile the module is defined in. 28*333d2b36SAndroid Build Coastguard Workertype moduleTeamAndTestInfo struct { 29*333d2b36SAndroid Build Coastguard Worker // Name field from bp file for the team 30*333d2b36SAndroid Build Coastguard Worker teamName string 31*333d2b36SAndroid Build Coastguard Worker // Blueprint file the module is located in. 32*333d2b36SAndroid Build Coastguard Worker bpFile string 33*333d2b36SAndroid Build Coastguard Worker // Is this module only used by tests. 34*333d2b36SAndroid Build Coastguard Worker testOnly bool 35*333d2b36SAndroid Build Coastguard Worker // Is this a directly testable target by running the module directly 36*333d2b36SAndroid Build Coastguard Worker // or via tradefed. 37*333d2b36SAndroid Build Coastguard Worker topLevelTestTarget bool 38*333d2b36SAndroid Build Coastguard Worker // String name indicating the module, like `java_library` for reporting. 39*333d2b36SAndroid Build Coastguard Worker kind string 40*333d2b36SAndroid Build Coastguard Worker} 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Workertype allTeamsSingleton struct { 43*333d2b36SAndroid Build Coastguard Worker // Path where the collected metadata is stored after successful validation. 44*333d2b36SAndroid Build Coastguard Worker outputPath OutputPath 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Worker // Map of all package modules we visit during GenerateBuildActions 47*333d2b36SAndroid Build Coastguard Worker packages map[string]packageProperties 48*333d2b36SAndroid Build Coastguard Worker // Map of all team modules we visit during GenerateBuildActions 49*333d2b36SAndroid Build Coastguard Worker teams map[string]teamProperties 50*333d2b36SAndroid Build Coastguard Worker // Keeps track of team information or bp file for each module we visit. 51*333d2b36SAndroid Build Coastguard Worker teams_for_mods map[string]moduleTeamAndTestInfo 52*333d2b36SAndroid Build Coastguard Worker} 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Worker// See if there is a package module for the given bpFilePath with a team defined, if so return the team. 55*333d2b36SAndroid Build Coastguard Worker// If not ascend up to the parent directory and do the same. 56*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) { 57*333d2b36SAndroid Build Coastguard Worker // return the Default_team listed in the package if is there. 58*333d2b36SAndroid Build Coastguard Worker if p, ok := t.packages[bpFilePath]; ok { 59*333d2b36SAndroid Build Coastguard Worker if defaultTeam := p.Default_team; defaultTeam != nil { 60*333d2b36SAndroid Build Coastguard Worker return t.teams[*defaultTeam], true 61*333d2b36SAndroid Build Coastguard Worker } 62*333d2b36SAndroid Build Coastguard Worker } 63*333d2b36SAndroid Build Coastguard Worker // Strip a directory and go up. 64*333d2b36SAndroid Build Coastguard Worker // Does android/paths.go basePath,SourcePath help? 65*333d2b36SAndroid Build Coastguard Worker current, base := filepath.Split(bpFilePath) 66*333d2b36SAndroid Build Coastguard Worker current = filepath.Clean(current) // removes trailing slash, convert "" -> "." 67*333d2b36SAndroid Build Coastguard Worker parent, _ := filepath.Split(current) 68*333d2b36SAndroid Build Coastguard Worker if current == "." { 69*333d2b36SAndroid Build Coastguard Worker return teamProperties{}, false 70*333d2b36SAndroid Build Coastguard Worker } 71*333d2b36SAndroid Build Coastguard Worker return t.lookupDefaultTeam(filepath.Join(parent, base)) 72*333d2b36SAndroid Build Coastguard Worker} 73*333d2b36SAndroid Build Coastguard Worker 74*333d2b36SAndroid Build Coastguard Worker// Visit all modules and collect all teams and use WriteFileRuleVerbatim 75*333d2b36SAndroid Build Coastguard Worker// to write it out. 76*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { 77*333d2b36SAndroid Build Coastguard Worker t.packages = make(map[string]packageProperties) 78*333d2b36SAndroid Build Coastguard Worker t.teams = make(map[string]teamProperties) 79*333d2b36SAndroid Build Coastguard Worker t.teams_for_mods = make(map[string]moduleTeamAndTestInfo) 80*333d2b36SAndroid Build Coastguard Worker 81*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(module Module) { 82*333d2b36SAndroid Build Coastguard Worker bpFile := ctx.BlueprintFile(module) 83*333d2b36SAndroid Build Coastguard Worker 84*333d2b36SAndroid Build Coastguard Worker // Package Modules and Team Modules are stored in a map so we can look them up by name for 85*333d2b36SAndroid Build Coastguard Worker // modules without a team. 86*333d2b36SAndroid Build Coastguard Worker if pack, ok := module.(*packageModule); ok { 87*333d2b36SAndroid Build Coastguard Worker // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context. 88*333d2b36SAndroid Build Coastguard Worker pkgKey := bpFile 89*333d2b36SAndroid Build Coastguard Worker t.packages[pkgKey] = pack.properties 90*333d2b36SAndroid Build Coastguard Worker return 91*333d2b36SAndroid Build Coastguard Worker } 92*333d2b36SAndroid Build Coastguard Worker if team, ok := module.(*teamModule); ok { 93*333d2b36SAndroid Build Coastguard Worker t.teams[team.Name()] = team.properties 94*333d2b36SAndroid Build Coastguard Worker return 95*333d2b36SAndroid Build Coastguard Worker } 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Worker testModInfo := TestModuleInformation{} 98*333d2b36SAndroid Build Coastguard Worker if tmi, ok := OtherModuleProvider(ctx, module, TestOnlyProviderKey); ok { 99*333d2b36SAndroid Build Coastguard Worker testModInfo = tmi 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Worker // Some modules, like java_test_host don't set the provider when the module isn't enabled: 103*333d2b36SAndroid Build Coastguard Worker // test_only, top_level 104*333d2b36SAndroid Build Coastguard Worker // AVFHostTestCases{os:linux_glibc,arch:common} {true true} 105*333d2b36SAndroid Build Coastguard Worker // AVFHostTestCases{os:windows,arch:common} {false false} 106*333d2b36SAndroid Build Coastguard Worker // Generally variant information of true override false or unset. 107*333d2b36SAndroid Build Coastguard Worker if testModInfo.TestOnly == false { 108*333d2b36SAndroid Build Coastguard Worker if prevValue, exists := t.teams_for_mods[module.Name()]; exists { 109*333d2b36SAndroid Build Coastguard Worker if prevValue.testOnly == true { 110*333d2b36SAndroid Build Coastguard Worker return 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker } 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker entry := moduleTeamAndTestInfo{ 115*333d2b36SAndroid Build Coastguard Worker bpFile: bpFile, 116*333d2b36SAndroid Build Coastguard Worker testOnly: testModInfo.TestOnly, 117*333d2b36SAndroid Build Coastguard Worker topLevelTestTarget: testModInfo.TopLevelTarget, 118*333d2b36SAndroid Build Coastguard Worker kind: ctx.ModuleType(module), 119*333d2b36SAndroid Build Coastguard Worker teamName: module.base().Team(), 120*333d2b36SAndroid Build Coastguard Worker } 121*333d2b36SAndroid Build Coastguard Worker t.teams_for_mods[module.Name()] = entry 122*333d2b36SAndroid Build Coastguard Worker 123*333d2b36SAndroid Build Coastguard Worker }) 124*333d2b36SAndroid Build Coastguard Worker 125*333d2b36SAndroid Build Coastguard Worker // Visit all modules again and lookup the team name in the package or parent package if the team 126*333d2b36SAndroid Build Coastguard Worker // isn't assignged at the module level. 127*333d2b36SAndroid Build Coastguard Worker allTeams := t.lookupTeamForAllModules() 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Worker t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile) 130*333d2b36SAndroid Build Coastguard Worker data, err := proto.Marshal(allTeams) 131*333d2b36SAndroid Build Coastguard Worker if err != nil { 132*333d2b36SAndroid Build Coastguard Worker ctx.Errorf("Unable to marshal team data. %s", err) 133*333d2b36SAndroid Build Coastguard Worker } 134*333d2b36SAndroid Build Coastguard Worker 135*333d2b36SAndroid Build Coastguard Worker WriteFileRuleVerbatim(ctx, t.outputPath, string(data)) 136*333d2b36SAndroid Build Coastguard Worker ctx.Phony("all_teams", t.outputPath) 137*333d2b36SAndroid Build Coastguard Worker} 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) { 140*333d2b36SAndroid Build Coastguard Worker ctx.DistForGoal("all_teams", t.outputPath) 141*333d2b36SAndroid Build Coastguard Worker} 142*333d2b36SAndroid Build Coastguard Worker 143*333d2b36SAndroid Build Coastguard Worker// Visit every (non-package, non-team) module and write out a proto containing 144*333d2b36SAndroid Build Coastguard Worker// either the declared team data for that module or the package default team data for that module. 145*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams { 146*333d2b36SAndroid Build Coastguard Worker teamsProto := make([]*team_proto.Team, len(t.teams_for_mods)) 147*333d2b36SAndroid Build Coastguard Worker for i, moduleName := range SortedKeys(t.teams_for_mods) { 148*333d2b36SAndroid Build Coastguard Worker m, _ := t.teams_for_mods[moduleName] 149*333d2b36SAndroid Build Coastguard Worker teamName := m.teamName 150*333d2b36SAndroid Build Coastguard Worker var teamProperties teamProperties 151*333d2b36SAndroid Build Coastguard Worker found := false 152*333d2b36SAndroid Build Coastguard Worker if teamName != "" { 153*333d2b36SAndroid Build Coastguard Worker teamProperties, found = t.teams[teamName] 154*333d2b36SAndroid Build Coastguard Worker } else { 155*333d2b36SAndroid Build Coastguard Worker teamProperties, found = t.lookupDefaultTeam(m.bpFile) 156*333d2b36SAndroid Build Coastguard Worker } 157*333d2b36SAndroid Build Coastguard Worker // Deal with one blueprint file including another by looking up the default 158*333d2b36SAndroid Build Coastguard Worker // in the main Android.bp rather than one listed with "build = [My.bp]" 159*333d2b36SAndroid Build Coastguard Worker if !found { 160*333d2b36SAndroid Build Coastguard Worker teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp")) 161*333d2b36SAndroid Build Coastguard Worker } 162*333d2b36SAndroid Build Coastguard Worker 163*333d2b36SAndroid Build Coastguard Worker trendy_team_id := "" 164*333d2b36SAndroid Build Coastguard Worker if found { 165*333d2b36SAndroid Build Coastguard Worker trendy_team_id = *teamProperties.Trendy_team_id 166*333d2b36SAndroid Build Coastguard Worker } 167*333d2b36SAndroid Build Coastguard Worker 168*333d2b36SAndroid Build Coastguard Worker teamData := new(team_proto.Team) 169*333d2b36SAndroid Build Coastguard Worker *teamData = team_proto.Team{ 170*333d2b36SAndroid Build Coastguard Worker TargetName: proto.String(moduleName), 171*333d2b36SAndroid Build Coastguard Worker Path: proto.String(m.bpFile), 172*333d2b36SAndroid Build Coastguard Worker TestOnly: proto.Bool(m.testOnly), 173*333d2b36SAndroid Build Coastguard Worker TopLevelTarget: proto.Bool(m.topLevelTestTarget), 174*333d2b36SAndroid Build Coastguard Worker Kind: proto.String(m.kind), 175*333d2b36SAndroid Build Coastguard Worker } 176*333d2b36SAndroid Build Coastguard Worker if trendy_team_id != "" { 177*333d2b36SAndroid Build Coastguard Worker teamData.TrendyTeamId = proto.String(trendy_team_id) 178*333d2b36SAndroid Build Coastguard Worker } else { 179*333d2b36SAndroid Build Coastguard Worker // Clients rely on the TrendyTeamId optional field not being set. 180*333d2b36SAndroid Build Coastguard Worker } 181*333d2b36SAndroid Build Coastguard Worker teamsProto[i] = teamData 182*333d2b36SAndroid Build Coastguard Worker } 183*333d2b36SAndroid Build Coastguard Worker return &team_proto.AllTeams{Teams: teamsProto} 184*333d2b36SAndroid Build Coastguard Worker} 185