Merge changes Ibb6c4aed,I54af1654

* changes:
  AndroidProducts.mk file reader
  Soong variables reader
diff --git a/android/module.go b/android/module.go
index 07d82f1..196b095 100644
--- a/android/module.go
+++ b/android/module.go
@@ -344,8 +344,18 @@
 	// Deprecated: use ModuleContext.Build instead.
 	ModuleBuild(pctx PackageContext, params ModuleBuildParams)
 
+	// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
+	// be tagged with `android:"path" to support automatic source module dependency resolution.
+	//
+	// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
 	ExpandSources(srcFiles, excludes []string) Paths
+
+	// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
+	// be tagged with `android:"path" to support automatic source module dependency resolution.
+	//
+	// Deprecated: use PathForModuleSrc instead.
 	ExpandSource(srcFile, prop string) Path
+
 	ExpandOptionalSource(srcFile *string, prop string) OptionalPath
 
 	// InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
@@ -473,6 +483,7 @@
 	InitRc() Paths
 	VintfFragments() Paths
 	NoticeFiles() Paths
+	EffectiveLicenseFiles() Paths
 
 	AddProperties(props ...interface{})
 	GetProperties() []interface{}
@@ -1505,6 +1516,10 @@
 	return m.commonProperties.NamespaceExportedToMake
 }
 
+func (m *ModuleBase) EffectiveLicenseFiles() Paths {
+	return m.commonProperties.Effective_license_text
+}
+
 // computeInstallDeps finds the installed paths of all dependencies that have a dependency
 // tag that is annotated as needing installation via the IsInstallDepNeeded method.
 func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]*installPathsDepSet, []*packagingSpecsDepSet) {
@@ -2832,8 +2847,26 @@
 	return sourceOrOutputDependencyTag{tag: tag}
 }
 
+// Deprecated, use IsSourceDepTagWithOutputTag(tag, "") instead.
 var SourceDepTag = sourceOrOutputDepTag("")
 
+// IsSourceDepTag returns true if the supplied blueprint.DependencyTag is one that was used to add
+// dependencies by either ExtractSourceDeps, ExtractSourcesDeps or automatically for properties
+// tagged with `android:"path"`.
+func IsSourceDepTag(depTag blueprint.DependencyTag) bool {
+	_, ok := depTag.(sourceOrOutputDependencyTag)
+	return ok
+}
+
+// IsSourceDepTagWithOutputTag returns true if the supplied blueprint.DependencyTag is one that was
+// used to add dependencies by either ExtractSourceDeps, ExtractSourcesDeps or automatically for
+// properties tagged with `android:"path"` AND it was added using a module reference of
+// :moduleName{outputTag}.
+func IsSourceDepTagWithOutputTag(depTag blueprint.DependencyTag, outputTag string) bool {
+	t, ok := depTag.(sourceOrOutputDependencyTag)
+	return ok && t.tag == outputTag
+}
+
 // Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
 // using ":module" syntax, if any.
 //
diff --git a/android/namespace.go b/android/namespace.go
index d137636..4f727e1 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -27,7 +27,11 @@
 )
 
 func init() {
-	RegisterModuleType("soong_namespace", NamespaceFactory)
+	registerNamespaceBuildComponents(InitRegistrationContext)
+}
+
+func registerNamespaceBuildComponents(ctx RegistrationContext) {
+	ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
 }
 
 // threadsafe sorted list
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 08e221a..ea399da 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -636,13 +636,12 @@
 	result := GroupFixturePreparers(
 		FixtureModifyContext(func(ctx *TestContext) {
 			ctx.RegisterModuleType("test_module", newTestModule)
-			ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
 			ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
-			ctx.PreArchMutators(RegisterNamespaceMutator)
 			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
 				ctx.BottomUp("rename", renameMutator)
 			})
 		}),
+		PrepareForTestWithNamespace,
 		bps.AddToFixture(),
 	).
 		// Ignore errors for now so tests can check them later.
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 568f868..07b4869 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -63,7 +63,8 @@
 
 	if p.props.Foo != "" {
 		// Make sure there is only one dependency on a module listed in a property present in multiple property structs
-		if ctx.GetDirectDepWithTag(SrcIsModule(p.props.Foo), sourceOrOutputDepTag("")) == nil {
+		m := SrcIsModule(p.props.Foo)
+		if GetModuleFromPathDep(ctx, m, "") == nil {
 			ctx.ModuleErrorf("GetDirectDepWithTag failed")
 		}
 	}
diff --git a/android/paths.go b/android/paths.go
index 128ec12..c5e4806 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -446,7 +446,7 @@
 // If the dependency is not found, a missingErrorDependency is returned.
 // If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
 func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag string) (Paths, error) {
-	module := ctx.GetDirectDepWithTag(moduleName, sourceOrOutputDepTag(tag))
+	module := GetModuleFromPathDep(ctx, moduleName, tag)
 	if module == nil {
 		return nil, missingDependencyError{[]string{moduleName}}
 	}
@@ -474,6 +474,22 @@
 	}
 }
 
+// GetModuleFromPathDep will return the module that was added as a dependency automatically for
+// properties tagged with `android:"path"` or manually using ExtractSourceDeps or
+// ExtractSourcesDeps.
+//
+// The moduleName and tag supplied to this should be the values returned from SrcIsModuleWithTag.
+// Or, if no tag is expected then the moduleName should be the value returned by  SrcIsModule and
+// the tag must be "".
+//
+// If tag is "" then the returned module will be the dependency that was added for ":moduleName".
+// Otherwise, it is the dependency that was added for ":moduleName{tag}".
+//
+// TODO(b/193228441) Make this handle fully qualified names, e.g. //namespace:moduleName.
+func GetModuleFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string) blueprint.Module {
+	return ctx.GetDirectDepWithTag(moduleName, sourceOrOutputDepTag(tag))
+}
+
 // PathsAndMissingDepsForModuleSrcExcludes returns a Paths{} containing the resolved references in
 // paths, minus those listed in excludes. Elements of paths and excludes are resolved as:
 // * filepath, relative to local module directory, resolves as a filepath relative to the local
diff --git a/android/testing.go b/android/testing.go
index b36f62c..17a812e 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -110,6 +110,11 @@
 	FixtureAddFile("build/soong/licenses/LICENSE", nil),
 )
 
+var PrepareForTestWithNamespace = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+	registerNamespaceBuildComponents(ctx)
+	ctx.PreArchMutators(RegisterNamespaceMutator)
+})
+
 // Test fixture preparer that will register most java build components.
 //
 // Singletons and mutators should only be added here if they are needed for a majority of java
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index d4384b2..adb0a7b 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -130,7 +130,11 @@
 	},
 	{
 		Name: "removePdkProperty",
-		Fix:  runPatchListMod(removePdkProperty),
+		Fix:  runPatchListMod(removeObsoleteProperty("product_variables.pdk")),
+	},
+	{
+		Name: "removeScudoProperty",
+		Fix:  runPatchListMod(removeObsoleteProperty("sanitize.scudo")),
 	},
 }
 
@@ -863,7 +867,9 @@
 	}
 }
 
-func runPatchListMod(modFunc func(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error) func(*Fixer) error {
+type patchListModFunction func(*parser.Module, []byte, *parser.PatchList) error
+
+func runPatchListMod(modFunc patchListModFunction) func(*Fixer) error {
 	return func(f *Fixer) error {
 		// Make sure all the offsets are accurate
 		buf, err := f.reparse()
@@ -1033,23 +1039,63 @@
 	return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr)
 }
 
-func removePdkProperty(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
-	prop, ok := mod.GetProperty("product_variables")
-	if !ok {
-		return nil
+type propertyProvider interface {
+	GetProperty(string) (*parser.Property, bool)
+	RemoveProperty(string) bool
+}
+
+func removeNestedProperty(mod *parser.Module, patchList *parser.PatchList, propName string) error {
+	propNames := strings.Split(propName, ".")
+
+	var propProvider, toRemoveFrom propertyProvider
+	propProvider = mod
+
+	var propToRemove *parser.Property
+	for i, name := range propNames {
+		p, ok := propProvider.GetProperty(name)
+		if !ok {
+			return nil
+		}
+		// if this is the inner most element, it's time to delete
+		if i == len(propNames)-1 {
+			if propToRemove == nil {
+				// if we cannot remove the properties that the current property is nested in,
+				// remove only the current property
+				propToRemove = p
+				toRemoveFrom = propProvider
+			}
+
+			// remove the property from the list, in case we remove other properties in this list
+			toRemoveFrom.RemoveProperty(propToRemove.Name)
+			// only removing the property would leave blank line(s), remove with a patch
+			if err := patchList.Add(propToRemove.Pos().Offset, propToRemove.End().Offset+2, ""); err != nil {
+				return err
+			}
+		} else {
+			propMap, ok := p.Value.(*parser.Map)
+			if !ok {
+				return nil
+			}
+			if len(propMap.Properties) > 1 {
+				// if there are other properties in this struct, we need to keep this struct
+				toRemoveFrom = nil
+				propToRemove = nil
+			} else if propToRemove == nil {
+				// otherwise, we can remove the empty struct entirely
+				toRemoveFrom = propProvider
+				propToRemove = p
+			}
+			propProvider = propMap
+		}
 	}
-	propMap, ok := prop.Value.(*parser.Map)
-	if !ok {
-		return nil
+
+	return nil
+}
+
+func removeObsoleteProperty(propName string) patchListModFunction {
+	return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
+		return removeNestedProperty(mod, patchList, propName)
 	}
-	pdkProp, ok := propMap.GetProperty("pdk")
-	if !ok {
-		return nil
-	}
-	if len(propMap.Properties) > 1 {
-		return patchlist.Add(pdkProp.Pos().Offset, pdkProp.End().Offset+2, "")
-	}
-	return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "")
 }
 
 func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index f502229..b994e25 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -999,7 +999,171 @@
 	}
 }
 
-func TestRemovePdkProperty(t *testing.T) {
+func TestRemoveNestedProperty(t *testing.T) {
+	tests := []struct {
+		name         string
+		in           string
+		out          string
+		propertyName string
+	}{
+		{
+			name: "remove no nesting",
+			in: `
+cc_library {
+	name: "foo",
+	foo: true,
+}`,
+			out: `
+cc_library {
+	name: "foo",
+}
+`,
+			propertyName: "foo",
+		},
+		{
+			name: "remove one nest",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: true,
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+}
+`,
+			propertyName: "foo.bar",
+		},
+		{
+			name: "remove one nest, multiple props",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: true,
+		baz: false,
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+	foo: {
+		baz: false,
+	},
+}
+`,
+			propertyName: "foo.bar",
+		},
+		{
+			name: "remove multiple nest",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			baz: {
+				a: true,
+			}
+		},
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+}
+`,
+			propertyName: "foo.bar.baz.a",
+		},
+		{
+			name: "remove multiple nest, outer non-empty",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			baz: {
+				a: true,
+			}
+		},
+		other: true,
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+	foo: {
+		other: true,
+	},
+}
+`,
+			propertyName: "foo.bar.baz.a",
+		},
+		{
+			name: "remove multiple nest, inner non-empty",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			baz: {
+				a: true,
+			},
+			other: true,
+		},
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			other: true,
+		},
+	},
+}
+`,
+			propertyName: "foo.bar.baz.a",
+		},
+		{
+			name: "remove multiple nest, inner-most non-empty",
+			in: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			baz: {
+				a: true,
+				other: true,
+			},
+		},
+	},
+}`,
+			out: `
+cc_library {
+	name: "foo",
+	foo: {
+		bar: {
+			baz: {
+				other: true,
+			},
+		},
+	},
+}
+`,
+			propertyName: "foo.bar.baz.a",
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty(test.propertyName)))
+		})
+	}
+}
+
+func TestRemoveObsoleteProperties(t *testing.T) {
 	tests := []struct {
 		name string
 		in   string
@@ -1052,7 +1216,7 @@
 	}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			runPass(t, test.in, test.out, runPatchListMod(removePdkProperty))
+			runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty("product_variables.pdk")))
 		})
 	}
 }
diff --git a/cc/linkable.go b/cc/linkable.go
index c42c875..84141e2 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -83,6 +83,9 @@
 	// SnapshotLibrary returns true if this module is a snapshot library.
 	IsSnapshotLibrary() bool
 
+	// EffectiveLicenseFiles returns the list of License files for this module.
+	EffectiveLicenseFiles() android.Paths
+
 	// SnapshotRuntimeLibs returns a list of libraries needed by this module at runtime but which aren't build dependencies.
 	SnapshotRuntimeLibs() []string
 
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 7ba2363..003b7c9 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -501,13 +501,13 @@
 			headers = append(headers, m.SnapshotHeaders()...)
 		}
 
-		if len(m.NoticeFiles()) > 0 {
+		if len(m.EffectiveLicenseFiles()) > 0 {
 			noticeName := ctx.ModuleName(m) + ".txt"
 			noticeOut := filepath.Join(noticeDir, noticeName)
 			// skip already copied notice file
 			if !installedNotices[noticeOut] {
 				installedNotices[noticeOut] = true
-				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.NoticeFiles(), noticeOut))
+				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.EffectiveLicenseFiles(), noticeOut))
 			}
 		}
 	})
diff --git a/rust/rust.go b/rust/rust.go
index 0a9869f..38f1742 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -990,7 +990,9 @@
 			case procMacroDepTag:
 				directProcMacroDeps = append(directProcMacroDeps, rustDep)
 				mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
-			case android.SourceDepTag:
+			}
+
+			if android.IsSourceDepTagWithOutputTag(depTag, "") {
 				// Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
 				// OS/Arch variant is used.
 				var helper string
@@ -1120,8 +1122,7 @@
 		}
 
 		if srcDep, ok := dep.(android.SourceFileProducer); ok {
-			switch depTag {
-			case android.SourceDepTag:
+			if android.IsSourceDepTagWithOutputTag(depTag, "") {
 				// These are usually genrules which don't have per-target variants.
 				directSrcDeps = append(directSrcDeps, srcDep)
 			}