Make overrides work in Soong

This change adds `overrides` property to all module types. It is used
to prevent another module (or modules) from being installed or packaged.

Bug: 330141242
Test: go test ./...

Change-Id: I4f05c603f0c5dbb699d00327882c7498472b59de
diff --git a/android/module.go b/android/module.go
index 5d68a87..c033973 100644
--- a/android/module.go
+++ b/android/module.go
@@ -499,6 +499,10 @@
 
 	// vintf_fragment Modules required from this module.
 	Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
+
+	// List of module names that are prevented from being installed when this module gets
+	// installed.
+	Overrides []string
 }
 
 type distProperties struct {
diff --git a/android/module_context.go b/android/module_context.go
index 5322240..b69aa29 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -522,6 +522,7 @@
 
 func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
 	licenseFiles := m.Module().EffectiveLicenseFiles()
+	overrides := CopyOf(m.Module().base().commonProperties.Overrides)
 	spec := PackagingSpec{
 		relPathInPackage:      Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
 		srcPath:               srcPath,
@@ -532,6 +533,8 @@
 		skipInstall:           m.skipInstall(),
 		aconfigPaths:          m.getAconfigPaths(),
 		archType:              m.target.Arch.ArchType,
+		overrides:             &overrides,
+		owner:                 m.ModuleName(),
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
@@ -649,6 +652,7 @@
 		m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 	}
 
+	overrides := CopyOf(m.Module().base().commonProperties.Overrides)
 	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
 		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
 		srcPath:          nil,
@@ -658,6 +662,8 @@
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
 		archType:         m.target.Arch.ArchType,
+		overrides:        &overrides,
+		owner:            m.ModuleName(),
 	})
 
 	return fullInstallPath
@@ -693,6 +699,7 @@
 		m.installFiles = append(m.installFiles, fullInstallPath)
 	}
 
+	overrides := CopyOf(m.Module().base().commonProperties.Overrides)
 	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
 		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
 		srcPath:          nil,
@@ -702,6 +709,8 @@
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
 		archType:         m.target.Arch.ArchType,
+		overrides:        &overrides,
+		owner:            m.ModuleName(),
 	})
 
 	return fullInstallPath
diff --git a/android/neverallow.go b/android/neverallow.go
index a68f5ea..233ca61 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -182,6 +182,7 @@
 		"packages/modules/SdkExtensions/derive_sdk",
 		// These are for apps and shouldn't be used by non-SDK variant modules.
 		"prebuilts/ndk",
+		"frameworks/native/libs/binder/ndk",
 		"tools/test/graphicsbenchmark/apps/sample_app",
 		"tools/test/graphicsbenchmark/functional_tests/java",
 		"vendor/xts/gts-tests/hostsidetests/gamedevicecert/apps/javatests",
diff --git a/android/packaging.go b/android/packaging.go
index 42009d5..61dfa7e 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -56,6 +56,12 @@
 
 	// ArchType of the module which produced this packaging spec
 	archType ArchType
+
+	// List of module names that this packaging spec overrides
+	overrides *[]string
+
+	// Name of the module where this packaging spec is output of
+	owner string
 }
 
 func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -325,7 +331,10 @@
 }
 
 func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
-	m := make(map[string]PackagingSpec)
+	// all packaging specs gathered from the dep.
+	var all []PackagingSpec
+	// list of module names overridden
+	var overridden []string
 
 	var arches []ArchType
 	for _, target := range getSupportedTargets(ctx) {
@@ -357,17 +366,33 @@
 					continue
 				}
 			}
-			dstPath := ps.relPathInPackage
-			if existingPs, ok := m[dstPath]; ok {
-				if !existingPs.Equals(&ps) {
-					ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
-				}
-				continue
+			all = append(all, ps)
+			if ps.overrides != nil {
+				overridden = append(overridden, *ps.overrides...)
 			}
-
-			m[dstPath] = ps
 		}
 	})
+
+	// all minus packaging specs that are overridden
+	var filtered []PackagingSpec
+	for _, ps := range all {
+		if ps.owner != "" && InList(ps.owner, overridden) {
+			continue
+		}
+		filtered = append(filtered, ps)
+	}
+
+	m := make(map[string]PackagingSpec)
+	for _, ps := range filtered {
+		dstPath := ps.relPathInPackage
+		if existingPs, ok := m[dstPath]; ok {
+			if !existingPs.Equals(&ps) {
+				ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
+			}
+			continue
+		}
+		m[dstPath] = ps
+	}
 	return m
 }
 
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 19b46fe..0f7bb39 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -28,6 +28,7 @@
 	props struct {
 		Deps         []string
 		Skip_install *bool
+		Overrides    []string
 	}
 }
 
@@ -650,3 +651,64 @@
 		runPackagingTest(t, config, bp, tc.expected)
 	}
 }
+
+func TestOverrides(t *testing.T) {
+	bpTemplate := `
+		component {
+			name: "foo",
+			deps: ["bar"],
+		}
+
+		component {
+			name: "bar",
+		}
+
+		component {
+			name: "bar_override",
+			overrides: ["bar"],
+		}
+
+		component {
+			name: "baz",
+			deps: ["bar_override"],
+		}
+
+		package_module {
+			name: "package",
+			deps: %DEPS%,
+		}
+	`
+	testcases := []struct {
+		deps     []string
+		expected []string
+	}{
+		{
+			deps:     []string{"foo"},
+			expected: []string{"lib64/foo", "lib64/bar"},
+		},
+		{
+			deps:     []string{"foo", "bar_override"},
+			expected: []string{"lib64/foo", "lib64/bar_override"},
+		},
+		{
+			deps:     []string{"foo", "bar", "bar_override"},
+			expected: []string{"lib64/foo", "lib64/bar_override"},
+		},
+		{
+			deps:     []string{"bar", "bar_override"},
+			expected: []string{"lib64/bar_override"},
+		},
+		{
+			deps:     []string{"foo", "baz"},
+			expected: []string{"lib64/foo", "lib64/baz", "lib64/bar_override"},
+		},
+	}
+	for _, tc := range testcases {
+		config := testConfig{
+			multiTarget:                true,
+			depsCollectFirstTargetOnly: false,
+		}
+		bp := strings.Replace(bpTemplate, "%DEPS%", `["`+strings.Join(tc.deps, `", "`)+`"]`, -1)
+		runPackagingTest(t, config, bp, tc.expected)
+	}
+}