Merge "Restrict visibility of EXTRA_INSTALL_ZIPS" into main
diff --git a/android/module_context.go b/android/module_context.go
index 3c1e30a..18adb30 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -497,6 +497,7 @@
 		partition:             fullInstallPath.partition,
 		skipInstall:           m.skipInstall(),
 		aconfigPaths:          m.getAconfigPaths(),
+		archType:              m.target.Arch.ArchType,
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
@@ -622,6 +623,7 @@
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
+		archType:         m.target.Arch.ArchType,
 	})
 
 	return fullInstallPath
@@ -665,6 +667,7 @@
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
+		archType:         m.target.Arch.ArchType,
 	})
 
 	return fullInstallPath
diff --git a/android/packaging.go b/android/packaging.go
index a7260a6..383f828 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -51,6 +51,9 @@
 
 	// Paths of aconfig files for the built artifact
 	aconfigPaths *Paths
+
+	// ArchType of the module which produced this packaging spec
+	archType ArchType
 }
 
 func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -260,11 +263,31 @@
 
 func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
 	m := make(map[string]PackagingSpec)
+
+	var arches []ArchType
+	for _, target := range p.getSupportedTargets(ctx) {
+		arches = append(arches, target.Arch.ArchType)
+	}
+
+	// filter out packaging specs for unsupported architecture
+	filterArch := func(ps PackagingSpec) bool {
+		for _, arch := range arches {
+			if arch == ps.archType {
+				return true
+			}
+		}
+		return false
+	}
+
 	ctx.VisitDirectDeps(func(child Module) {
 		if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
 			return
 		}
 		for _, ps := range child.TransitivePackagingSpecs() {
+			if !filterArch(ps) {
+				continue
+			}
+
 			if filter != nil {
 				if !filter(ps) {
 					continue
diff --git a/apex/apex.go b/apex/apex.go
index 9a80ec6..8029910 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1636,7 +1636,8 @@
 
 func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
 	dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
-	return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
+	makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
+	return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt)
 }
 
 func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9a5c2b4..74b2eec 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11531,3 +11531,42 @@
 		"depend on java_aconfig_library not passed as an input",
 		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "quux"))
 }
+
+func TestMultiplePrebuiltsWithSameBase(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			prebuilts: ["myetc", "myetc2"],
+			min_sdk_version: "29",
+		}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		prebuilt_etc {
+			name: "myetc",
+			src: "myprebuilt",
+			filename: "myfilename",
+		}
+		prebuilt_etc {
+			name: "myetc2",
+			sub_dir: "mysubdir",
+			src: "myprebuilt",
+			filename: "myfilename",
+		}
+	`, withFiles(android.MockFS{
+		"packages/modules/common/build/allowed_deps.txt": nil,
+	}))
+
+	ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, ab)
+	var builder strings.Builder
+	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+	androidMk := builder.String()
+
+	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_myfilename.myapex")
+	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_mysubdir_myfilename.myapex")
+}
diff --git a/bin/aninja b/bin/aninja
new file mode 100755
index 0000000..cceb794
--- /dev/null
+++ b/bin/aninja
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+# Copyright (C) 2022 The Android Open Source Project
+#
+# 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.
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+require_lunch
+
+cd $(gettop)
+prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja "$@"
+
diff --git a/bin/overrideflags b/bin/overrideflags
new file mode 100755
index 0000000..e16537b
--- /dev/null
+++ b/bin/overrideflags
@@ -0,0 +1,100 @@
+#!/bin/bash -e
+# Copyright (C) 2023 The Android Open Source Project
+#
+# 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.
+
+
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+function print_help() {
+    echo -e "overrideflags is used to set default value for local build."
+    echo -e "\nOptions:"
+    echo -e "\t--release-config  \tPath to release configuration directory. Required"
+    echo -e "\t--no-edit         \tIf present, skip editing flag value file."
+    echo -e "\t-h/--help         \tShow this help."
+}
+
+function main() {
+    while (($# > 0)); do
+        case $1 in
+        --release-config)
+            if [[ $# -le 1 ]]; then
+                echo "--release-config requires a path"
+                return 1
+            fi
+            local release_config_dir="$2"
+            shift 2
+            ;;
+        --no-edit)
+            local no_edit="true"
+            shift 1
+            ;;
+        -h|--help)
+            print_help
+            return
+            ;;
+        *)
+            echo "$1 is unrecognized"
+            print_help
+            return 1
+            ;;
+        esac
+    done
+
+
+
+    case $(uname -s) in
+        Darwin)
+            local host_arch=darwin-x86
+            ;;
+        Linux)
+            local host_arch=linux-x86
+            ;;
+        *)
+            >&2 echo Unknown host $(uname -s)
+            return
+            ;;
+    esac
+
+    if [[ -z "${release_config_dir}" ]]; then
+        echo "Please provide release configuration path by --release-config"
+        exit 1
+    elif [ ! -d "${release_config_dir}" ]; then
+        echo "${release_config_dir} is an invalid directory"
+        exit 1
+    fi
+    local T="$(gettop)"
+    local aconfig_dir="${T}"/build/make/tools/aconfig/
+    local overrideflag_py="${aconfig_dir}"/overrideflags/overrideflags.py
+    local overridefile="${release_config_dir}/aconfig/override_values.textproto"
+
+    # Edit override file
+    if [[ -z "${no_edit}" ]]; then
+        editor="${EDITOR:-$(which vim)}"
+
+        eval "${editor} ${overridefile}"
+        if [ $? -ne 0 ]; then
+            echo "Fail to set override values"
+            return 1
+        fi
+    fi
+
+    ${T}/prebuilts/build-tools/${host_arch}/bin/py3-cmd -u "${overrideflag_py}" \
+        --overrides "${overridefile}" \
+        --out "${release_config_dir}/aconfig"
+}
+
+
+main "$@"
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 861918f..015d39a 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -497,3 +497,70 @@
 		android.AssertStringListContains(t, "missing entry", fs.entries, e)
 	}
 }
+
+func TestFilterOutUnsupportedArches(t *testing.T) {
+	result := fixture.RunTestWithBp(t, `
+		android_filesystem {
+			name: "fs_64_only",
+			deps: ["foo"],
+		}
+
+		android_filesystem {
+			name: "fs_64_32",
+			compile_multilib: "both",
+			multilib: {
+				first: {
+					deps: ["foo"],
+				},
+			},
+		}
+
+		cc_binary {
+			name: "foo",
+			required: ["phony"],
+		}
+
+		phony {
+			name: "phony",
+			required: [
+				"libbar",
+				"app",
+			],
+		}
+
+		cc_library {
+			name: "libbar",
+		}
+
+		android_app {
+			name: "app",
+			srcs: ["a.java"],
+			platform_apis: true,
+		}
+	`)
+	testcases := []struct {
+		fsName     string
+		expected   []string
+		unexpected []string
+	}{
+		{
+			fsName:     "fs_64_only",
+			expected:   []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so"},
+			unexpected: []string{"lib/libbar.so"},
+		},
+		{
+			fsName:     "fs_64_32",
+			expected:   []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so", "lib/libbar.so"},
+			unexpected: []string{},
+		},
+	}
+	for _, c := range testcases {
+		fs := result.ModuleForTests(c.fsName, "android_common").Module().(*filesystem)
+		for _, e := range c.expected {
+			android.AssertStringListContains(t, "missing entry", fs.entries, e)
+		}
+		for _, e := range c.unexpected {
+			android.AssertStringListDoesNotContain(t, "unexpected entry", fs.entries, e)
+		}
+	}
+}