deps in the packaging modules supports select

deps: ["foo"] + select(product_variable("debuggable") {
    true: ["bar"],
    default: [],
}),

returns ["foo", "bar"] on debuggable builds, and ["foo"] on user builds.

Bug: N/A
Test: go test ./...
Change-Id: I31ca22e69e3316e4007a36ae13c04c7e5c445907
diff --git a/android/packaging.go b/android/packaging.go
index 080dcfe..a2b8755 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -20,6 +20,7 @@
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 // PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
@@ -150,7 +151,7 @@
 
 type depsProperty struct {
 	// Modules to include in this package
-	Deps []string `android:"arch_variant"`
+	Deps proptools.Configurable[[]string] `android:"arch_variant"`
 }
 
 type packagingMultilibProperties struct {
@@ -169,8 +170,8 @@
 }
 
 type PackagingProperties struct {
-	Deps     []string                    `android:"arch_variant"`
-	Multilib packagingMultilibProperties `android:"arch_variant"`
+	Deps     proptools.Configurable[[]string] `android:"arch_variant"`
+	Multilib packagingMultilibProperties      `android:"arch_variant"`
 	Arch     packagingArchProperties
 }
 
@@ -188,38 +189,42 @@
 // multi target, deps is selected for each of the targets and is NOT selected for the current
 // architecture which would be Common.
 func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
+	get := func(prop proptools.Configurable[[]string]) []string {
+		return prop.GetOrDefault(ctx, nil)
+	}
+
 	var ret []string
 	if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
-		ret = append(ret, p.properties.Deps...)
+		ret = append(ret, get(p.properties.Deps)...)
 	} else if arch.Multilib == "lib32" {
-		ret = append(ret, p.properties.Multilib.Lib32.Deps...)
+		ret = append(ret, get(p.properties.Multilib.Lib32.Deps)...)
 	} else if arch.Multilib == "lib64" {
-		ret = append(ret, p.properties.Multilib.Lib64.Deps...)
+		ret = append(ret, get(p.properties.Multilib.Lib64.Deps)...)
 	} else if arch == Common {
-		ret = append(ret, p.properties.Multilib.Common.Deps...)
+		ret = append(ret, get(p.properties.Multilib.Common.Deps)...)
 	}
 
 	if p.DepsCollectFirstTargetOnly {
-		if len(p.properties.Multilib.First.Deps) > 0 {
+		if len(get(p.properties.Multilib.First.Deps)) > 0 {
 			ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
 		}
 		for i, t := range ctx.MultiTargets() {
 			if t.Arch.ArchType == arch {
-				ret = append(ret, p.properties.Multilib.Both.Deps...)
+				ret = append(ret, get(p.properties.Multilib.Both.Deps)...)
 				if i == 0 {
-					ret = append(ret, p.properties.Deps...)
+					ret = append(ret, get(p.properties.Deps)...)
 				}
 			}
 		}
 	} else {
-		if len(p.properties.Multilib.Both.Deps) > 0 {
+		if len(get(p.properties.Multilib.Both.Deps)) > 0 {
 			ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
 		}
 		for i, t := range ctx.MultiTargets() {
 			if t.Arch.ArchType == arch {
-				ret = append(ret, p.properties.Deps...)
+				ret = append(ret, get(p.properties.Deps)...)
 				if i == 0 {
-					ret = append(ret, p.properties.Multilib.First.Deps...)
+					ret = append(ret, get(p.properties.Multilib.First.Deps)...)
 				}
 			}
 		}
@@ -228,13 +233,13 @@
 	if ctx.Arch().ArchType == Common {
 		switch arch {
 		case Arm64:
-			ret = append(ret, p.properties.Arch.Arm64.Deps...)
+			ret = append(ret, get(p.properties.Arch.Arm64.Deps)...)
 		case Arm:
-			ret = append(ret, p.properties.Arch.Arm.Deps...)
+			ret = append(ret, get(p.properties.Arch.Arm.Deps)...)
 		case X86_64:
-			ret = append(ret, p.properties.Arch.X86_64.Deps...)
+			ret = append(ret, get(p.properties.Arch.X86_64.Deps)...)
 		case X86:
-			ret = append(ret, p.properties.Arch.X86.Deps...)
+			ret = append(ret, get(p.properties.Arch.X86.Deps)...)
 		}
 	}
 
diff --git a/android/packaging_test.go b/android/packaging_test.go
index f99bb91..0570ec5 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -95,12 +95,13 @@
 	m.entries = m.CopyDepsToZip(ctx, m.GatherPackagingSpecs(ctx), zipFile)
 }
 
-type packageTestModuleConfig struct {
+type testConfig struct {
 	multiTarget                bool
 	depsCollectFirstTargetOnly bool
+	debuggable                 bool
 }
 
-func runPackagingTest(t *testing.T, config packageTestModuleConfig, bp string, expected []string) {
+func runPackagingTest(t *testing.T, config testConfig, bp string, expected []string) {
 	t.Helper()
 
 	var archVariant string
@@ -120,6 +121,9 @@
 			ctx.RegisterModuleType("component", componentTestModuleFactory)
 			ctx.RegisterModuleType("package_module", moduleFactory)
 		}),
+		FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+			variables.Debuggable = proptools.BoolPtr(config.debuggable)
+		}),
 		FixtureWithRootAndroidBp(bp),
 	).RunTest(t)
 
@@ -131,7 +135,7 @@
 }
 
 func TestPackagingBaseMultiTarget(t *testing.T) {
-	config := packageTestModuleConfig{
+	config := testConfig{
 		multiTarget:                true,
 		depsCollectFirstTargetOnly: false,
 	}
@@ -258,7 +262,7 @@
 }
 
 func TestPackagingBaseSingleTarget(t *testing.T) {
-	config := packageTestModuleConfig{
+	config := testConfig{
 		multiTarget:                false,
 		depsCollectFirstTargetOnly: false,
 	}
@@ -383,7 +387,7 @@
 func TestPackagingWithSkipInstallDeps(t *testing.T) {
 	// package -[dep]-> foo -[dep]-> bar      -[dep]-> baz
 	// Packaging should continue transitively through modules that are not installed.
-	config := packageTestModuleConfig{
+	config := testConfig{
 		multiTarget:                false,
 		depsCollectFirstTargetOnly: false,
 	}
@@ -412,7 +416,7 @@
 }
 
 func TestPackagingWithDepsCollectFirstTargetOnly(t *testing.T) {
-	config := packageTestModuleConfig{
+	config := testConfig{
 		multiTarget:                true,
 		depsCollectFirstTargetOnly: true,
 	}
@@ -537,3 +541,46 @@
 		}
 		`, []string{"lib64/foo", "lib64/bar"})
 }
+
+func TestDebuggableDeps(t *testing.T) {
+	bp := `
+		component {
+			name: "foo",
+		}
+
+		component {
+			name: "bar",
+			deps: ["baz"],
+		}
+
+		component {
+			name: "baz",
+		}
+
+		package_module {
+			name: "package",
+			deps: ["foo"] + select(product_variable("debuggable"), {
+				true: ["bar"],
+				default: [],
+			}),
+		}`
+	testcases := []struct {
+		debuggable bool
+		expected   []string
+	}{
+		{
+			debuggable: true,
+			expected:   []string{"lib64/foo", "lib64/bar", "lib64/baz"},
+		},
+		{
+			debuggable: false,
+			expected:   []string{"lib64/foo"},
+		},
+	}
+	for _, tc := range testcases {
+		config := testConfig{
+			debuggable: tc.debuggable,
+		}
+		runPackagingTest(t, config, bp, tc.expected)
+	}
+}