Merge "Add -fdebug-info-for-profiling flag to emit more debug info for sampling pgo"
diff --git a/android/config.go b/android/config.go
index 3dae6e2..da4f8e2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1029,7 +1029,7 @@
 }
 
 func (c *deviceConfig) NativeCoverageEnabled() bool {
-	return Bool(c.config.productVariables.NativeCoverage)
+	return Bool(c.config.productVariables.Native_coverage)
 }
 
 func (c *deviceConfig) ClangCoverageEnabled() bool {
diff --git a/android/sdk.go b/android/sdk.go
index 9e6ad16..006b3a0 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -182,6 +182,8 @@
 	AddPrebuiltModule(member SdkMember, moduleType string) BpModule
 }
 
+type BpPropertyTag interface{}
+
 // A set of properties for use in a .bp file.
 type BpPropertySet interface {
 	// Add a property, the value can be one of the following types:
@@ -190,9 +192,12 @@
 	// * bool
 	// * BpPropertySet
 	//
-	// It is an error is multiples properties with the same name are added.
+	// It is an error if multiple properties with the same name are added.
 	AddProperty(name string, value interface{})
 
+	// Add a property with an associated tag
+	AddPropertyWithTag(name string, value interface{}, tag BpPropertyTag)
+
 	// Add a property set with the specified name and return so that additional
 	// properties can be added.
 	AddPropertySet(name string) BpPropertySet
diff --git a/android/variable.go b/android/variable.go
index 51306ad..c277acc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -125,6 +125,11 @@
 		Experimental_mte struct {
 			Cflags []string `android:"arch_variant"`
 		} `android:"arch_variant"`
+
+		Native_coverage struct {
+			Srcs         []string `android:"arch_variant"`
+			Exclude_srcs []string `android:"arch_variant"`
+		} `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
 
@@ -247,7 +252,7 @@
 	ClangTidy  *bool   `json:",omitempty"`
 	TidyChecks *string `json:",omitempty"`
 
-	NativeCoverage       *bool    `json:",omitempty"`
+	Native_coverage      *bool    `json:",omitempty"`
 	ClangCoverage        *bool    `json:",omitempty"`
 	CoveragePaths        []string `json:",omitempty"`
 	CoverageExcludePaths []string `json:",omitempty"`
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 391072e..dd08f03 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -82,7 +82,7 @@
 				notice: "custom_notice",
 			}
 		`, func(fs map[string][]byte, config android.Config) {
-			config.TestProductVariables.NativeCoverage = proptools.BoolPtr(true)
+			config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
 		})
 
 		files := getFiles(t, ctx, "myapex", "android_common_image")
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ad84cde..3243e43 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -293,7 +293,7 @@
 	outputPath := hiddenAPISingletonPaths(ctx).metadata
 
 	rule.Command().
-		Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/merge_csv.py")).
+		BuiltTool(ctx, "merge_csv").
 		Inputs(metadataCSV).
 		Text(">").
 		Output(outputPath)
diff --git a/sdk/bp.go b/sdk/bp.go
index ae06a09..6936daf 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -22,6 +22,7 @@
 
 type bpPropertySet struct {
 	properties map[string]interface{}
+	tags       map[string]android.BpPropertyTag
 	order      []string
 }
 
@@ -29,6 +30,7 @@
 
 func (s *bpPropertySet) init() {
 	s.properties = make(map[string]interface{})
+	s.tags = make(map[string]android.BpPropertyTag)
 }
 
 func (s *bpPropertySet) AddProperty(name string, value interface{}) {
@@ -40,6 +42,11 @@
 	s.order = append(s.order, name)
 }
 
+func (s *bpPropertySet) AddPropertyWithTag(name string, value interface{}, tag android.BpPropertyTag) {
+	s.AddProperty(name, value)
+	s.tags[name] = tag
+}
+
 func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet {
 	set := &bpPropertySet{}
 	set.init()
@@ -51,26 +58,34 @@
 	return s.properties[name]
 }
 
-func (s *bpPropertySet) deepCopy() *bpPropertySet {
-	propertiesCopy := make(map[string]interface{})
-	for p, v := range s.properties {
-		var valueCopy interface{}
-		if ps, ok := v.(*bpPropertySet); ok {
-			valueCopy = ps.deepCopy()
-		} else if values, ok := v.([]string); ok {
-			valuesCopy := make([]string, len(values))
-			copy(valuesCopy, values)
-			valueCopy = valuesCopy
-		} else {
-			valueCopy = v
-		}
-		propertiesCopy[p] = valueCopy
-	}
+func (s *bpPropertySet) getTag(name string) interface{} {
+	return s.tags[name]
+}
 
-	return &bpPropertySet{
-		properties: propertiesCopy,
-		order:      append([]string(nil), s.order...),
+func (s *bpPropertySet) transform(transformer bpPropertyTransformer) {
+	var newOrder []string
+	for _, name := range s.order {
+		value := s.properties[name]
+		tag := s.tags[name]
+		var newValue interface{}
+		var newTag android.BpPropertyTag
+		if propertySet, ok := value.(*bpPropertySet); ok {
+			newValue, newTag = transformer.transformPropertySet(name, propertySet, tag)
+		} else {
+			newValue, newTag = transformer.transformProperty(name, value, tag)
+		}
+
+		if newValue == nil {
+			// Delete the property from the map and exclude it from the new order.
+			delete(s.properties, name)
+		} else {
+			// Update the property in the map and add the name to the new order list.
+			s.properties[name] = newValue
+			s.tags[name] = newTag
+			newOrder = append(newOrder, name)
+		}
 	}
+	s.order = newOrder
 }
 
 func (s *bpPropertySet) setProperty(name string, value interface{}) {
@@ -78,6 +93,7 @@
 		s.AddProperty(name, value)
 	} else {
 		s.properties[name] = value
+		s.tags[name] = nil
 	}
 }
 
@@ -111,13 +127,107 @@
 
 var _ android.BpModule = (*bpModule)(nil)
 
-func (m *bpModule) deepCopy() *bpModule {
-	return &bpModule{
-		bpPropertySet: m.bpPropertySet.deepCopy(),
-		moduleType:    m.moduleType,
-	}
+type bpPropertyTransformer interface {
+	// Transform the property set, returning the new property set/tag to insert back into the
+	// parent property set (or module if this is the top level property set).
+	//
+	// This will be called before transforming the properties in the supplied set.
+	//
+	// The name will be "" for the top level property set.
+	//
+	// Returning (nil, ...) will cause the property set to be removed.
+	transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
+
+	// Transform a property, return the new value/tag to insert back into the property set.
+	//
+	// Returning (nil, ...) will cause the property to be removed.
+	transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag)
 }
 
+// Interface for transforming bpModule objects.
+type bpTransformer interface {
+	// Transform the module, returning the result.
+	//
+	// The method can either create a new module and return that, or modify the supplied module
+	// in place and return that.
+	//
+	// After this returns the transformer is applied to the contents of the returned module.
+	transformModule(module *bpModule) *bpModule
+
+	bpPropertyTransformer
+}
+
+type identityTransformation struct{}
+
+var _ bpTransformer = (*identityTransformation)(nil)
+
+func (t identityTransformation) transformModule(module *bpModule) *bpModule {
+	return module
+}
+
+func (t identityTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+	return propertySet, tag
+}
+
+func (t identityTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+	return value, tag
+}
+
+func (m *bpModule) deepCopy() *bpModule {
+	return m.transform(deepCopyTransformer)
+}
+
+func (m *bpModule) transform(transformer bpTransformer) *bpModule {
+	transformedModule := transformer.transformModule(m)
+	// Copy the contents of the returned property set into the module and then transform that.
+	transformedModule.bpPropertySet, _ = transformer.transformPropertySet("", transformedModule.bpPropertySet, nil)
+	transformedModule.bpPropertySet.transform(transformer)
+	return transformedModule
+}
+
+type deepCopyTransformation struct{}
+
+func (t deepCopyTransformation) transformModule(module *bpModule) *bpModule {
+	// Take a shallow copy of the module. Any mutable property values will be copied by the
+	// transformer.
+	moduleCopy := *module
+	return &moduleCopy
+}
+
+func (t deepCopyTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+	// Create a shallow copy of the properties map. Any mutable property values will be copied by the
+	// transformer.
+	propertiesCopy := make(map[string]interface{})
+	for propertyName, value := range propertySet.properties {
+		propertiesCopy[propertyName] = value
+	}
+
+	// Ditto for tags map.
+	tagsCopy := make(map[string]android.BpPropertyTag)
+	for propertyName, propertyTag := range propertySet.tags {
+		tagsCopy[propertyName] = propertyTag
+	}
+
+	// Create a new property set.
+	return &bpPropertySet{
+		properties: propertiesCopy,
+		tags:       tagsCopy,
+		order:      append([]string(nil), propertySet.order...),
+	}, tag
+}
+
+func (t deepCopyTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+	// Copy string slice, otherwise return value.
+	if values, ok := value.([]string); ok {
+		valuesCopy := make([]string, len(values))
+		copy(valuesCopy, values)
+		return valuesCopy, tag
+	}
+	return value, tag
+}
+
+var deepCopyTransformer bpTransformer = deepCopyTransformation{}
+
 // A .bp file
 type bpFile struct {
 	modules map[string]*bpModule
diff --git a/sdk/update.go b/sdk/update.go
index 2731d50..0d2e4e4 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -194,12 +194,16 @@
 		member.memberType.BuildSnapshot(ctx, builder, member)
 	}
 
+	// Create a transformer that will transform an unversioned module into a versioned module.
+	unversionedToVersionedTransformer := unversionedToVersionedTransformation{builder: builder}
+
 	for _, unversioned := range builder.prebuiltOrder {
 		// Copy the unversioned module so it can be modified to make it versioned.
 		versioned := unversioned.deepCopy()
-		name := versioned.properties["name"].(string)
-		versioned.setProperty("name", builder.versionedSdkMemberName(name))
-		versioned.insertAfter("name", "sdk_member_name", name)
+
+		// Transform the unversioned module into a versioned one.
+		versioned.transform(unversionedToVersionedTransformer)
+
 		bpFile.AddModule(versioned)
 
 		// Set prefer: false - this is not strictly required as that is the default.
@@ -281,6 +285,22 @@
 	return outputZipFile
 }
 
+type unversionedToVersionedTransformation struct {
+	identityTransformation
+	builder *snapshotBuilder
+}
+
+var _ bpTransformer = (*unversionedToVersionedTransformation)(nil)
+
+func (t unversionedToVersionedTransformation) transformModule(module *bpModule) *bpModule {
+	// Use a versioned name for the module but remember the original name for the
+	// snapshot.
+	name := module.getValue("name").(string)
+	module.setProperty("name", t.builder.versionedSdkMemberName(name))
+	module.insertAfter("name", "sdk_member_name", name)
+	return module
+}
+
 func generateBpContents(contents *generatedContents, bpFile *bpFile) {
 	contents.Printfln("// This is auto-generated. DO NOT EDIT.")
 	for _, bpModule := range bpFile.order {
@@ -294,7 +314,7 @@
 func outputPropertySet(contents *generatedContents, set *bpPropertySet) {
 	contents.Indent()
 	for _, name := range set.order {
-		value := set.properties[name]
+		value := set.getValue(name)
 
 		reflectedValue := reflect.ValueOf(value)
 		t := reflectedValue.Type()