Add Code Metadata rule to soong/testing.
This Cl adds a new rule to Soong to generate code ownership metadata. Also, this CL adds a provider in the Java SDK library to provide generated source files to the Code_metadata rule. Will add providers to other libraries in the future changes.
Bug: 296873595
Change-Id: Ic2e43aa9b161231fea4416d1f0d36b778361d7c5
diff --git a/testing/code_metadata.go b/testing/code_metadata.go
new file mode 100644
index 0000000..926324d
--- /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 android.Paths
+ if ctx.OtherModuleHasProvider(m, android.SrcsFileProviderKey) {
+ moduleSrcs = ctx.OtherModuleProvider(
+ m, android.SrcsFileProviderKey,
+ ).(android.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.Strings(),
+ }
+ metadataList = append(metadataList, metadata)
+ } else {
+ metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TargetName: &targetName,
+ TrendyTeamId: &module.properties.TeamId,
+ Path: &bpFilePath,
+ SourceFiles: moduleSrcs.Strings(),
+ }
+ 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},
+ )
+}