Merge "Required deps don't track native bridge architectures" into main
diff --git a/aconfig/build_flags/Android.bp b/aconfig/build_flags/Android.bp
index 69e4316..b3c7339 100644
--- a/aconfig/build_flags/Android.bp
+++ b/aconfig/build_flags/Android.bp
@@ -14,6 +14,7 @@
     ],
     srcs: [
         "all_build_flag_declarations.go",
+        "build_flags.go",
         "declarations.go",
         "init.go",
     ],
diff --git a/aconfig/build_flags/build_flags.go b/aconfig/build_flags/build_flags.go
new file mode 100644
index 0000000..e878b5a
--- /dev/null
+++ b/aconfig/build_flags/build_flags.go
@@ -0,0 +1,71 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// 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.
+
+package build_flags
+
+import (
+	"fmt"
+
+	"android/soong/android"
+)
+
+const (
+	outJsonFileName = "build_flags.json"
+)
+
+func init() {
+	registerBuildFlagsModuleType(android.InitRegistrationContext)
+}
+
+func registerBuildFlagsModuleType(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("build_flags_json", buildFlagsFactory)
+}
+
+type buildFlags struct {
+	android.ModuleBase
+
+	outputPath android.OutputPath
+}
+
+func buildFlagsFactory() android.Module {
+	module := &buildFlags{}
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	return module
+}
+
+func (m *buildFlags) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Read the build_flags_<partition>.json file generated by soong
+	// 'release-config' command.
+	srcPath := android.PathForOutput(ctx, "release-config", fmt.Sprintf("build_flags_%s.json", m.PartitionTag(ctx.DeviceConfig())))
+	m.outputPath = android.PathForModuleOut(ctx, outJsonFileName).OutputPath
+
+	// The 'release-config' command is called for every build, and generates the
+	// build_flags_<partition>.json file.
+	// Update the output file only if the source file is changed.
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.CpIfChanged,
+		Input:  srcPath,
+		Output: m.outputPath,
+	})
+
+	installPath := android.PathForModuleInstall(ctx, "etc")
+	ctx.InstallFile(installPath, outJsonFileName, m.outputPath)
+}
+
+func (m *buildFlags) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(m.outputPath),
+	}}
+}
diff --git a/aconfig/build_flags/init.go b/aconfig/build_flags/init.go
index 5907f4e..dc1369c 100644
--- a/aconfig/build_flags/init.go
+++ b/aconfig/build_flags/init.go
@@ -69,6 +69,7 @@
 
 func init() {
 	RegisterBuildComponents(android.InitRegistrationContext)
+	pctx.Import("android/soong/android")
 	pctx.HostBinToolVariable("buildFlagDeclarations", "build-flag-declarations")
 }
 
diff --git a/android/config.go b/android/config.go
index 6007451..2d32f1c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1466,10 +1466,6 @@
 	return c.config.productVariables.ExtraVndkVersions
 }
 
-func (c *deviceConfig) VndkUseCoreVariant() bool {
-	return Bool(c.config.productVariables.VndkUseCoreVariant) && Bool(c.config.productVariables.KeepVndk)
-}
-
 func (c *deviceConfig) SystemSdkVersions() []string {
 	return c.config.productVariables.DeviceSystemSdkVersions
 }
diff --git a/android/filegroup.go b/android/filegroup.go
index a8326d4..ff0f74e 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -19,6 +19,7 @@
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -36,9 +37,9 @@
 
 type fileGroupProperties struct {
 	// srcs lists files that will be included in this filegroup
-	Srcs []string `android:"path"`
+	Srcs proptools.Configurable[[]string] `android:"path"`
 
-	Exclude_srcs []string `android:"path"`
+	Exclude_srcs proptools.Configurable[[]string] `android:"path"`
 
 	// The base path to the files.  May be used by other modules to determine which portion
 	// of the path to use.  For example, when a filegroup is used as data in a cc_test rule,
@@ -89,7 +90,7 @@
 }
 
 func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
-	fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)
+	fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs.GetOrDefault(ctx, nil), fg.properties.Exclude_srcs.GetOrDefault(ctx, nil))
 	if fg.properties.Path != nil {
 		fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
 	}
diff --git a/android/variable.go b/android/variable.go
index a3fdafb..9a95563 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -181,8 +181,10 @@
 		// release_aidl_use_unfrozen is "true" when a device can
 		// use the unfrozen versions of AIDL interfaces.
 		Release_aidl_use_unfrozen struct {
-			Cflags []string
-			Cmd    *string
+			Cflags          []string
+			Cmd             *string
+			Required        []string
+			Vintf_fragments []string
 		}
 	} `android:"arch_variant"`
 }
@@ -362,7 +364,6 @@
 
 	PgoAdditionalProfileDirs []string `json:",omitempty"`
 
-	VndkUseCoreVariant         *bool `json:",omitempty"`
 	VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
 
 	DirectedVendorSnapshot bool            `json:",omitempty"`
diff --git a/bin/allmod b/bin/allmod
new file mode 100755
index 0000000..f7d25e5
--- /dev/null
+++ b/bin/allmod
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# List all modules for the current device, as cached in all_modules.txt. If any build change is
+# made and it should be reflected in the output, you should run 'refreshmod' first.
+
+cat $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null
+
diff --git a/bin/core b/bin/core
new file mode 100755
index 0000000..01dbd13
--- /dev/null
+++ b/bin/core
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# core - send SIGV and pull the core for process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must be called once per boot for core dumps to be
+#       enabled globally.
+
+set -e
+
+PID=$1;
+
+if [ -z "$PID" ]; then
+    printf "Expecting a PID!\n";
+    exit 1
+fi;
+
+CORENAME=core.$PID;
+COREPATH=/cores/$CORENAME;
+SIG=SEGV;
+
+coredump_enable $1;
+
+done=0;
+while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
+    printf "\tSending SIG%s to %d...\n" $SIG $PID;
+    adb shell kill -$SIG $PID;
+    sleep 1;
+done;
+
+adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
+echo "Done: core is under $COREPATH on device.";
+
+
diff --git a/bin/coredump_enable b/bin/coredump_enable
new file mode 100755
index 0000000..da63a0c
--- /dev/null
+++ b/bin/coredump_enable
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+PID=$1;
+if [ -z "$PID" ]; then
+    printf "Expecting a PID!\n";
+    exit 1
+fi;
+echo "Setting core limit for $PID to infinite...";
+adb shell /system/bin/ulimit -P $PID -c unlimited
+
diff --git a/bin/coredump_setup b/bin/coredump_setup
new file mode 100755
index 0000000..7647659
--- /dev/null
+++ b/bin/coredump_setup
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_setup - enable core dumps globally for any process
+#                  that has the core-file-size limit set correctly
+#
+# NOTE: You must call also coredump_enable for a specific process
+#       if its core-file-size limit is not set already.
+# NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
+
+set -e
+
+echo "Getting root...";
+adb root;
+adb wait-for-device;
+
+echo "Remounting root partition read-write...";
+adb shell mount -w -o remount -t rootfs rootfs;
+sleep 1;
+adb wait-for-device;
+adb shell mkdir -p /cores;
+adb shell mount -t tmpfs tmpfs /cores;
+adb shell chmod 0777 /cores;
+
+echo "Granting SELinux permission to dump in /cores...";
+adb shell restorecon -R /cores;
+
+echo "Set core pattern.";
+adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
+
+echo "Done."
+
diff --git a/bin/dirmods b/bin/dirmods
new file mode 100755
index 0000000..d43506a
--- /dev/null
+++ b/bin/dirmods
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of pathmod.
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: usage: dirmods <path>\n")
+        sys.exit(1)
+
+    d = argv[1]
+    while d.endswith('/'):
+        d = d[:-1]
+    prefix = d + '/'
+
+    module_info = modinfo.ReadModuleInfo()
+
+    results = set()
+    for m in module_info.values():
+        for path in m.get(u'path', []):
+            if path == d or path.startswith(prefix):
+                name = m.get(u'module_name')
+                if name:
+                    results.add(name)
+
+    for name in sorted(results):
+        print(name)
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/bin/get_abs_build_var b/bin/get_abs_build_var
new file mode 100755
index 0000000..8072cf1
--- /dev/null
+++ b/bin/get_abs_build_var
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# Get the value of a build variable as an absolute path.
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+$TOP/build/soong/soong_ui.bash --dumpvar-mode --abs $1
+
+exit $?
diff --git a/bin/get_build_var b/bin/get_build_var
new file mode 100755
index 0000000..9fdf55f
--- /dev/null
+++ b/bin/get_build_var
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# Get the exact value of a build variable.
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+$TOP/build/soong/soong_ui.bash --dumpvar-mode $1
+
+exit $?
diff --git a/bin/getlastscreenshot b/bin/getlastscreenshot
new file mode 100755
index 0000000..dfe9a6b
--- /dev/null
+++ b/bin/getlastscreenshot
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+screenshot_path=$(getscreenshotpath)
+screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
+if [ "$screenshot" = "" ]; then
+    echo "No screenshots found."
+    exit 1
+fi
+echo "${screenshot}"
+adb ${adbOptions} pull ${screenshot_path}/${screenshot}
+
diff --git a/bin/getprebuilt b/bin/getprebuilt
new file mode 100755
index 0000000..68e65b4
--- /dev/null
+++ b/bin/getprebuilt
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+get_abs_build_var ANDROID_PREBUILTS
+
diff --git a/bin/getscreenshotpath b/bin/getscreenshotpath
new file mode 100755
index 0000000..ff8e327
--- /dev/null
+++ b/bin/getscreenshotpath
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+echo "$(getsdcardpath)/Pictures/Screenshots"
+
diff --git a/bin/getsdcardpath b/bin/getsdcardpath
new file mode 100755
index 0000000..655659a
--- /dev/null
+++ b/bin/getsdcardpath
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
+
diff --git a/bin/gettargetarch b/bin/gettargetarch
new file mode 100755
index 0000000..e53ce3f
--- /dev/null
+++ b/bin/gettargetarch
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+get_build_var TARGET_ARCH
+
diff --git a/bin/hmm b/bin/hmm
index c3d60fa..161bad6 100755
--- a/bin/hmm
+++ b/bin/hmm
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2022 The Android Open Source Project
+# Copyright (C) 2024 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.
@@ -14,6 +14,9 @@
 # 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
+
 cat <<EOF
 
 Run "m help" for help with the build system itself.
@@ -56,7 +59,6 @@
 - godir:      Go to the directory containing a file.
 - allmod:     List all modules.
 - gomod:      Go to the directory containing a module.
-- bmod:       Get the Bazel label of a Soong module if it is converted with bp2build.
 - pathmod:    Get the directory containing a module.
 - outmod:     Gets the location of a module's installed outputs with a certain extension.
 - dirmods:    Gets the modules defined in a given directory.
@@ -68,12 +70,12 @@
 - SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
 - ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
 
-Look at build/make/envsetup for more functions:
+Look at the source to view more functions. The complete list is:
 EOF
-    local T=$(gettop)
-    local A=""
-    local i
-    for i in `(cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z]*\).*/\1/p" | sort | uniq`; do
+    T=$(gettop)
+    A=""
+    for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
       A="$A $i"
     done
     echo $A
+
diff --git a/bin/installmod b/bin/installmod
new file mode 100755
index 0000000..1d0d836
--- /dev/null
+++ b/bin/installmod
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# adb install a module's apk, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Usage: installmod [adb install arguments] <module>
+# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
+
+if [[ $# -eq 0 ]]; then
+    echo "usage: installmod [adb install arguments] <module>" >&2
+    echo "" >&2
+    echo "Only flags to be passed after the \"install\" in adb install are supported," >&2
+    echo "with the exception of -s. If -s is passed it will be placed before the \"install\"." >&2
+    echo "-s must be the first flag passed if it exists." >&2
+    return 1
+fi
+
+local _path
+_path=$(outmod ${@:$#:1})
+if [ $? -ne 0 ]; then
+    return 1
+fi
+
+_path=$(echo "$_path" | grep -E \\.apk$ | head -n 1)
+if [ -z "$_path" ]; then
+    echo "Module '$1' does not produce a file ending with .apk (try 'refreshmod' if there have been build changes?)" >&2
+    return 1
+fi
+local serial_device=""
+if [[ "$1" == "-s" ]]; then
+    if [[ $# -le 2 ]]; then
+        echo "-s requires an argument" >&2
+        return 1
+    fi
+    serial_device="-s $2"
+    shift 2
+fi
+local length=$(( $# - 1 ))
+echo adb $serial_device install ${@:1:$length} $_path
+adb $serial_device install ${@:1:$length} $_path
+
diff --git a/bin/is64bit b/bin/is64bit
new file mode 100755
index 0000000..35bbcc3
--- /dev/null
+++ b/bin/is64bit
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# Read the ELF header from /proc/$PID/exe to determine if the process is
+# 64-bit.
+
+set -e
+
+local PID="$1"
+if [ "$PID" ] ; then
+    if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]] ; then
+        echo "64"
+    else
+        echo ""
+    fi
+else
+    echo ""
+fi
+
diff --git a/bin/isviewserverstarted b/bin/isviewserverstarted
new file mode 100755
index 0000000..c7c82af
--- /dev/null
+++ b/bin/isviewserverstarted
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb shell service call window 3
+
diff --git a/bin/key_back b/bin/key_back
new file mode 100755
index 0000000..2de8d07
--- /dev/null
+++ b/bin/key_back
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb shell input keyevent 4
+
diff --git a/bin/key_home b/bin/key_home
new file mode 100755
index 0000000..653a5f9
--- /dev/null
+++ b/bin/key_home
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb shell input keyevent 3
+
diff --git a/bin/key_menu b/bin/key_menu
new file mode 100755
index 0000000..29b2bc6
--- /dev/null
+++ b/bin/key_menu
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb shell input keyevent 82
+
diff --git a/bin/modinfo.py b/bin/modinfo.py
new file mode 100644
index 0000000..015129f
--- /dev/null
+++ b/bin/modinfo.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2024 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.
+
+import json
+import os
+import pathlib
+import sys
+
+
+def OpenModuleInfoFile():
+    product_out = os.getenv("ANDROID_PRODUCT_OUT")
+    if not product_out:
+        if os.getenv("QUIET_VERIFYMODINFO") != "true":
+            sys.stderr.write("No ANDROID_PRODUCT_OUT. Try running 'lunch' first.\n")
+        sys.exit(1)
+    try:
+        return open(pathlib.Path(product_out) / "module-info.json")
+    except (FileNotFoundError, PermissionError):
+        if os.getenv("QUIET_VERIFYMODINFO") != "true":
+            sys.stderr.write("Could not find module-info.json. Please run 'refreshmod' first.\n")
+        sys.exit(1)
+
+
+def ReadModuleInfo():
+    with OpenModuleInfoFile() as f:
+        return json.load(f)
+
+def GetModule(modules, module_name):
+    if module_name not in modules:
+        sys.stderr.write(f"Could not find module '{module_name}' (try 'refreshmod' if there have been build changes?)\n")
+        sys.exit(1)
+    return modules[module_name]
+
diff --git a/bin/outmod b/bin/outmod
new file mode 100755
index 0000000..681b405
--- /dev/null
+++ b/bin/outmod
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of dirmods.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: outmod <module>\n")
+        sys.exit(1)
+
+    for output in modinfo.GetModule(modinfo.ReadModuleInfo(), argv[1])['installed']:
+        print(os.path.join(os.getenv("ANDROID_BUILD_TOP"), output))
+
+if __name__ == "__main__":
+    main(sys.argv)
+
diff --git a/bin/pathmod b/bin/pathmod
new file mode 100755
index 0000000..90d84b5
--- /dev/null
+++ b/bin/pathmod
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of dirmods.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: pathmod <module>\n")
+        sys.exit(1)
+
+    print(modinfo.GetModule(modinfo.ReadModuleInfo(), argv[1])['path'][0])
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/bin/qpid b/bin/qpid
new file mode 100755
index 0000000..b47cb6b
--- /dev/null
+++ b/bin/qpid
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# adb install a module's apk, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Usage: installmod [adb install arguments] <module>
+# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
+
+function _impl() {
+    local prepend=''
+    local append=''
+    if [ "$1" = "--exact" ]; then
+        prepend=' '
+        append='$'
+        shift
+    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
+        echo "usage: qpid [[--exact] <process name|pid>"
+        return 255
+    fi
+
+    local EXE="$1"
+    if [ "$EXE" ] ; then
+        _impl | \grep "$prepend$EXE$append"
+    else
+        adb shell ps \
+            | tr -d '\r' \
+            | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
+    fi
+}
+
+_impl "$@"
diff --git a/bin/startviewserver b/bin/startviewserver
new file mode 100755
index 0000000..4d612b8
--- /dev/null
+++ b/bin/startviewserver
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+port=4939
+if [ $# -gt 0 ]; then
+    port=$1
+fi
+adb shell service call window 1 i32 $port
+
diff --git a/bin/stopviewserver b/bin/stopviewserver
new file mode 100755
index 0000000..a734e4b
--- /dev/null
+++ b/bin/stopviewserver
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# coredump_enable - enable core dumps for the specified process
+# $1 = PID of process (e.g., $(pid mediaserver))
+#
+# NOTE: coredump_setup must have been called as well for a core
+#       dump to actually be generated.
+
+set -e
+
+adb shell service call window 2
+
diff --git a/bin/systemstack b/bin/systemstack
new file mode 100755
index 0000000..b259133
--- /dev/null
+++ b/bin/systemstack
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# systemstack - dump the current stack trace of all threads in the system process
+# to the usual ANR traces file
+
+stacks system_server
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 0c6f97c..e1bc336 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -261,15 +261,6 @@
 		if library.coverageOutputFile.Valid() {
 			entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputFile.String())
 		}
-
-		if library.useCoreVariant {
-			entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
-			entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
-			entries.SetBool("LOCAL_VNDK_DEPEND_ON_CORE_VARIANT", true)
-		}
-		if library.checkSameCoreVariant {
-			entries.SetBool("LOCAL_CHECK_SAME_VNDK_VARIANTS", true)
-		}
 	})
 
 	if library.shared() && !library.buildStubs() {
diff --git a/cc/cc.go b/cc/cc.go
index a64775d..cb82f86 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -374,10 +374,6 @@
 	// build system and source tree.
 	Cmake_snapshot_supported *bool
 
-	// Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
-	// see soong/cc/config/vndk.go
-	MustUseVendorVariant bool `blueprint:"mutated"`
-
 	Installable *bool `android:"arch_variant"`
 
 	// Set by factories of module types that can only be referenced from variants compiled against
@@ -479,10 +475,6 @@
 	// IsLLNDK is set to true for the vendor variant of a cc_library module that has LLNDK stubs.
 	IsLLNDK bool `blueprint:"mutated"`
 
-	// IsVNDKUsingCoreVariant is true for VNDK modules if the global VndkUseCoreVariant option is
-	// set and the module is not listed in VndkMustUseVendorVariantList.
-	IsVNDKUsingCoreVariant bool `blueprint:"mutated"`
-
 	// IsVNDKCore is set if a VNDK module does not set the vndk.support_system_process property.
 	IsVNDKCore bool `blueprint:"mutated"`
 
@@ -548,7 +540,6 @@
 	apexVariationName() string
 	apexSdkVersion() android.ApiLevel
 	bootstrap() bool
-	mustUseVendorVariant() bool
 	nativeCoverage() bool
 	directlyInAnyApex() bool
 	isPreventInstall() bool
@@ -1472,10 +1463,6 @@
 	return c.Properties.SubName
 }
 
-func (c *Module) MustUseVendorVariant() bool {
-	return c.IsVndkSp() || c.Properties.MustUseVendorVariant
-}
-
 func (c *Module) getVndkExtendsModuleName() string {
 	if vndkdep := c.vndkdep; vndkdep != nil {
 		return vndkdep.getVndkExtendsModuleName()
@@ -1768,10 +1755,6 @@
 	return ctx.mod.IsVendorPublicLibrary()
 }
 
-func (ctx *moduleContextImpl) mustUseVendorVariant() bool {
-	return ctx.mod.MustUseVendorVariant()
-}
-
 func (ctx *moduleContextImpl) selectedStl() string {
 	if stl := ctx.mod.stl; stl != nil {
 		return stl.Properties.SelectedStl
@@ -3648,12 +3631,7 @@
 		}
 	}
 
-	if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() &&
-		!c.InRamdisk() && !c.InVendorRamdisk() && !c.InRecovery() {
-		// The vendor module is a no-vendor-variant VNDK library.  Depend on the
-		// core module instead.
-		return libName
-	} else if ccDep.InVendorOrProduct() && nonSystemVariantsExist {
+	if ccDep.InVendorOrProduct() && nonSystemVariantsExist {
 		// The vendor and product modules in Make will have been renamed to not conflict with the
 		// core module, so update the dependency name here accordingly.
 		return libName + ccDep.SubName()
@@ -3866,8 +3844,6 @@
 		// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
 		//family, link := getNdkStlFamilyAndLinkType(c)
 		//return fmt.Sprintf("native:ndk:%s:%s", family, link)
-	} else if actx.DeviceConfig().VndkUseCoreVariant() && !c.MustUseVendorVariant() {
-		return "native:platform_vndk"
 	} else {
 		return "native:platform"
 	}
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index fdc94ad..289409f 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -15,7 +15,6 @@
         "global.go",
         "tidy.go",
         "toolchain.go",
-        "vndk.go",
 
         "bionic.go",
 
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
deleted file mode 100644
index dd612ce..0000000
--- a/cc/config/vndk.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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.
-
-package config
-
-// List of VNDK libraries that have different core variant and vendor variant.
-// For these libraries, the vendor variants must be installed even if the device
-// has VndkUseCoreVariant set.
-// Note that AIDL-generated modules must use vendor variants by default.
-var VndkMustUseVendorVariantList = []string{
-	"android.hardware.nfc@1.2",
-	"libbinder",
-	"libcrypto",
-	"libexpat",
-	"libgatekeeper",
-	"libgui",
-	"libhidlcache",
-	"libkeymaster_messages",
-	"libkeymaster_portable",
-	"libmedia_omx",
-	"libpuresoftkeymasterdevice",
-	"libselinux",
-	"libsoftkeymasterdevice",
-	"libsqlite",
-	"libssl",
-	"libstagefright_bufferpool@2.0",
-	"libstagefright_bufferqueue_helper",
-	"libstagefright_foundation",
-	"libstagefright_omx",
-	"libstagefright_omx_utils",
-	"libstagefright_xmlparser",
-	"libui",
-	"libxml2",
-}
diff --git a/cc/library.go b/cc/library.go
index b9018a7..b9c1466 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -419,11 +419,6 @@
 
 	postInstallCmds []string
 
-	// If useCoreVariant is true, the vendor variant of a VNDK library is
-	// not installed.
-	useCoreVariant       bool
-	checkSameCoreVariant bool
-
 	skipAPIDefine bool
 
 	// Decorated interfaces
@@ -1767,27 +1762,6 @@
 				}
 			}
 
-			// In some cases we want to use core variant for VNDK-Core libs.
-			// Skip product variant since VNDKs use only the vendor variant.
-			if ctx.isVndk() && !ctx.isVndkSp() && !ctx.IsVndkExt() && !ctx.inProduct() {
-				mayUseCoreVariant := true
-
-				if ctx.mustUseVendorVariant() {
-					mayUseCoreVariant = false
-				}
-
-				if ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) {
-					mayUseCoreVariant = false
-				}
-
-				if mayUseCoreVariant {
-					library.checkSameCoreVariant = true
-					if ctx.DeviceConfig().VndkUseCoreVariant() {
-						library.useCoreVariant = true
-					}
-				}
-			}
-
 			// do not install vndk libs
 			// vndk libs are packaged into VNDK APEX
 			if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() && !ctx.inProduct() {
diff --git a/cc/linkable.go b/cc/linkable.go
index 5579aae..fecc6a2 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -165,7 +165,6 @@
 	// IsVndkSp returns true if this is a VNDK-SP module.
 	IsVndkSp() bool
 
-	MustUseVendorVariant() bool
 	IsVndk() bool
 	IsVndkExt() bool
 	IsVndkPrivate() bool
diff --git a/cc/vndk.go b/cc/vndk.go
index 548992d..ea55835 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -20,7 +20,6 @@
 	"strings"
 
 	"android/soong/android"
-	"android/soong/cc/config"
 	"android/soong/etc"
 
 	"github.com/google/blueprint"
@@ -219,11 +218,10 @@
 type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string)
 
 var (
-	vndkSPLibraries               = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP })
-	vndkCoreLibraries             = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore })
-	vndkPrivateLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate })
-	vndkProductLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKProduct })
-	vndkUsingCoreVariantLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKUsingCoreVariant })
+	vndkSPLibraries      = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP })
+	vndkCoreLibraries    = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore })
+	vndkPrivateLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate })
+	vndkProductLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKProduct })
 )
 
 // vndkModuleLister takes a predicate that operates on a Module and returns a moduleListerFunc
@@ -266,22 +264,6 @@
 	}
 }
 
-var vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
-
-func vndkMustUseVendorVariantList(cfg android.Config) []string {
-	return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} {
-		return config.VndkMustUseVendorVariantList
-	}).([]string)
-}
-
-// test may call this to override global configuration(config.VndkMustUseVendorVariantList)
-// when it is called, it must be before the first call to vndkMustUseVendorVariantList()
-func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) {
-	config.Once(vndkMustUseVendorVariantListKey, func() interface{} {
-		return mustUseVendorVariantList
-	})
-}
-
 func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
 	if m.InProduct() {
 		// We may skip the steps for the product variants because they
@@ -301,13 +283,6 @@
 		mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK")
 	}
 
-	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
-		m.Properties.MustUseVendorVariant = true
-	}
-	if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant {
-		m.VendorProperties.IsVNDKUsingCoreVariant = true
-	}
-
 	if m.vndkdep.isVndkSp() {
 		m.VendorProperties.IsVNDKSP = true
 	} else {
@@ -356,8 +331,7 @@
 		if lib.buildStubs() {
 			return false
 		}
-		useCoreVariant := mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
-		return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
+		return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt()
 	}
 	return false
 }
@@ -400,7 +374,6 @@
 	ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory)
 	ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory)
 	ctx.RegisterParallelSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory)
-	ctx.RegisterParallelSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory)
 }
 
 type vndkLibrariesTxt struct {
@@ -453,13 +426,6 @@
 	return newVndkLibrariesTxt(vndkProductLibraries, "VNDK_PRODUCT_LIBRARIES")
 }
 
-// vndkcorevariant_libraries_txt is a singleton module whose content is a list of VNDK libraries
-// that are using the core variant, generated by Soong but can be referenced by other modules.
-// For example, apex_vndk can depend on these files as prebuilt.
-func vndkUsingCoreVariantLibrariesTxtFactory() android.SingletonModule {
-	return newVndkLibrariesTxt(vndkUsingCoreVariantLibraries, "VNDK_USING_CORE_VARIANT_LIBRARIES")
-}
-
 func newVndkLibrariesWithMakeVarFilter(lister moduleListerFunc, makeVarName string, filter string) android.SingletonModule {
 	m := &vndkLibrariesTxt{
 		lister:               lister,
diff --git a/cmd/release_config/build_flag_declarations/main.go b/cmd/release_config/build_flag_declarations/main.go
index 7fdd084..cc286b6 100644
--- a/cmd/release_config/build_flag_declarations/main.go
+++ b/cmd/release_config/build_flag_declarations/main.go
@@ -6,6 +6,7 @@
 	"os"
 
 	rc_lib "android/soong/cmd/release_config/release_config_lib"
+	rc_proto "android/soong/cmd/release_config/release_config_proto"
 )
 
 type Flags struct {
@@ -62,18 +63,17 @@
 	}
 
 	flagArtifacts := rc_lib.FlagArtifactsFactory("")
+	intermediates := []*rc_proto.FlagDeclarationArtifacts{}
 	for _, intermediate := range flags.intermediates {
-		fas := rc_lib.FlagArtifactsFactory(intermediate)
-		for _, fa := range *fas {
-			(*flagArtifacts)[*fa.FlagDeclaration.Name] = fa
-		}
+		fda := rc_lib.FlagDeclarationArtifactsFactory(intermediate)
+		intermediates = append(intermediates, fda)
 	}
 	for _, decl := range flags.decls {
 		fa := rc_lib.FlagArtifactFactory(decl)
 		(*flagArtifacts)[*fa.FlagDeclaration.Name] = fa
 	}
 
-	message := flagArtifacts.GenerateFlagDeclarationArtifacts()
+	message := flagArtifacts.GenerateFlagDeclarationArtifacts(intermediates)
 	err = rc_lib.WriteFormattedMessage(flags.output, flags.format, message)
 	if err != nil {
 		errorExit(err)
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index 0617838..762f561 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -120,7 +120,7 @@
 			panic(err)
 		}
 	}
-	if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil {
+	if err = config.WritePartitionBuildFlags(outputDir); err != nil {
 		panic(err)
 	}
 
diff --git a/cmd/release_config/release_config_lib/flag_artifact.go b/cmd/release_config/release_config_lib/flag_artifact.go
index 6919ff5..6d36595 100644
--- a/cmd/release_config/release_config_lib/flag_artifact.go
+++ b/cmd/release_config/release_config_lib/flag_artifact.go
@@ -102,11 +102,24 @@
 	return ret
 }
 
-func (fas *FlagArtifacts) GenerateFlagDeclarationArtifacts() *rc_proto.FlagDeclarationArtifacts {
+func FlagDeclarationArtifactsFactory(path string) *rc_proto.FlagDeclarationArtifacts {
+	ret := &rc_proto.FlagDeclarationArtifacts{}
+	if path != "" {
+		LoadMessage(path, ret)
+	} else {
+		ret.FlagDeclarationArtifacts = []*rc_proto.FlagDeclarationArtifact{}
+	}
+	return ret
+}
+
+func (fas *FlagArtifacts) GenerateFlagDeclarationArtifacts(intermediates []*rc_proto.FlagDeclarationArtifacts) *rc_proto.FlagDeclarationArtifacts {
 	ret := &rc_proto.FlagDeclarationArtifacts{FlagDeclarationArtifacts: []*rc_proto.FlagDeclarationArtifact{}}
 	for _, fa := range *fas {
 		ret.FlagDeclarationArtifacts = append(ret.FlagDeclarationArtifacts, fa.GenerateFlagDeclarationArtifact())
 	}
+	for _, fda := range intermediates {
+		ret.FlagDeclarationArtifacts = append(ret.FlagDeclarationArtifacts, fda.FlagDeclarationArtifacts...)
+	}
 	slices.SortFunc(ret.FlagDeclarationArtifacts, func(a, b *rc_proto.FlagDeclarationArtifact) int {
 		return cmp.Compare(*a.Name, *b.Name)
 	})
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index 547f0dc..3e2348f 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -284,13 +284,15 @@
 	return nil
 }
 
-func (config *ReleaseConfig) WritePartitionBuildFlags(outDir, product, targetRelease string) error {
+func (config *ReleaseConfig) WritePartitionBuildFlags(outDir string) error {
 	var err error
 	for partition, flags := range config.PartitionBuildFlags {
 		slices.SortFunc(flags.FlagArtifacts, func(a, b *rc_proto.FlagArtifact) int {
 			return cmp.Compare(*a.FlagDeclaration.Name, *b.FlagDeclaration.Name)
 		})
-		if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s-%s-%s.json", partition, config.Name, product)), flags); err != nil {
+		// The json file name must not be modified as this is read from
+		// build_flags_json module
+		if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s.json", partition)), flags); err != nil {
 			return err
 		}
 	}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index e168edc..fd3b27f 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -74,11 +74,11 @@
 type prebuiltEtcProperties struct {
 	// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
 	// Mutually exclusive with srcs.
-	Src *string `android:"path,arch_variant"`
+	Src proptools.Configurable[string] `android:"path,arch_variant,replace_instead_of_append"`
 
 	// Source files of this prebuilt. Can reference a genrule type module with the ":module" syntax.
 	// Mutually exclusive with src. When used, filename_from_src is set to true.
-	Srcs []string `android:"path,arch_variant"`
+	Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
 
 	// Optional name for the installed file. If unspecified, name of the module is used as the file
 	// name. Only available when using a single source (src).
@@ -158,6 +158,8 @@
 	installDirPath         android.InstallPath
 	additionalDependencies *android.Paths
 
+	usedSrcsProperty bool
+
 	makeClass string
 }
 
@@ -247,10 +249,10 @@
 }
 
 func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
-	if len(p.properties.Srcs) > 0 {
+	if len(p.properties.Srcs.GetOrDefault(ctx, nil)) > 0 {
 		panic(fmt.Errorf("SourceFilePath not available on multi-source prebuilt %q", p.Name()))
 	}
-	return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
+	return android.PathForModuleSrc(ctx, p.properties.Src.GetOrDefault(ctx, ""))
 }
 
 func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
@@ -264,7 +266,7 @@
 }
 
 func (p *PrebuiltEtc) OutputFile() android.OutputPath {
-	if len(p.properties.Srcs) > 0 {
+	if p.usedSrcsProperty {
 		panic(fmt.Errorf("OutputFile not available on multi-source prebuilt %q", p.Name()))
 	}
 	return p.outputFilePaths[0]
@@ -319,7 +321,9 @@
 func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	var installs []installProperties
 
-	if p.properties.Src != nil && len(p.properties.Srcs) > 0 {
+	srcProperty := p.properties.Src.Get(ctx)
+	srcsProperty := p.properties.Srcs.GetOrDefault(ctx, nil)
+	if srcProperty.IsPresent() && len(srcsProperty) > 0 {
 		ctx.PropertyErrorf("src", "src is set. Cannot set srcs")
 	}
 
@@ -331,8 +335,8 @@
 
 	filename := proptools.String(p.properties.Filename)
 	filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
-	if p.properties.Src != nil {
-		p.sourceFilePaths = android.PathsForModuleSrc(ctx, []string{proptools.String(p.properties.Src)})
+	if srcProperty.IsPresent() {
+		p.sourceFilePaths = android.PathsForModuleSrc(ctx, []string{srcProperty.Get()})
 		// If the source was not found, set a fake source path to
 		// support AllowMissingDependencies executions.
 		if len(p.sourceFilePaths) == 0 {
@@ -367,7 +371,8 @@
 			symlinks:       p.properties.Symlinks,
 		}
 		installs = append(installs, ip)
-	} else if len(p.properties.Srcs) > 0 {
+	} else if len(srcsProperty) > 0 {
+		p.usedSrcsProperty = true
 		if filename != "" {
 			ctx.PropertyErrorf("filename", "filename cannot be set when using srcs")
 		}
@@ -377,7 +382,7 @@
 		if p.properties.Filename_from_src != nil {
 			ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
 		}
-		p.sourceFilePaths = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+		p.sourceFilePaths = android.PathsForModuleSrc(ctx, srcsProperty)
 		for _, src := range p.sourceFilePaths {
 			filename := src.Base()
 			output := android.PathForModuleOut(ctx, filename).OutputPath
diff --git a/go.mod b/go.mod
index 1174958..13834fc 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module android/soong
 
-go 1.21
+go 1.22
 
 require (
 	github.com/google/blueprint v0.0.0
diff --git a/go.work b/go.work
index 7c6022b..9a7e6db 100644
--- a/go.work
+++ b/go.work
@@ -1,4 +1,4 @@
-go 1.21
+go 1.22
 
 use (
 	.
diff --git a/java/base.go b/java/base.go
index b9e236c..056dbd5 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1650,11 +1650,23 @@
 				classesJar:    implementationAndResourcesJar,
 				jarName:       jarName,
 			}
-			dexOutputFile = j.dexer.compileDex(ctx, params)
+			if j.EnableProfileRewriting() {
+				profile := j.GetProfile()
+				if profile == "" || !j.GetProfileGuided() {
+					ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
+				}
+				params.artProfileInput = &profile
+			}
+			dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
 			if ctx.Failed() {
 				return
 			}
 
+			// If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
+			if dexArtProfileOutput != nil {
+				j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput)
+			}
+
 			// merge dex jar with resources if necessary
 			if j.resourceJar != nil {
 				jars := android.Paths{dexOutputFile, j.resourceJar}
diff --git a/java/dex.go b/java/dex.go
index 8cfffaf..f072226 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -253,17 +253,25 @@
 	return flags, deps
 }
 
-func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
+func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
+	flags := dexParams.flags
 	d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
 	d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
 
 	d8Deps = append(d8Deps, flags.bootClasspath...)
 	d8Deps = append(d8Deps, flags.dexClasspath...)
 
-	return d8Flags, d8Deps
+	if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+		d8Flags = append(d8Flags, flags...)
+		d8Deps = append(d8Deps, deps...)
+		artProfileOutput = profileOutput
+	}
+
+	return d8Flags, d8Deps, artProfileOutput
 }
 
-func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
+	flags := dexParams.flags
 	opt := d.dexProperties.Optimize
 
 	// When an app contains references to APIs that are not in the SDK specified by
@@ -375,18 +383,44 @@
 		}
 	}
 
-	return r8Flags, r8Deps
+	if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+		r8Flags = append(r8Flags, flags...)
+		r8Deps = append(r8Deps, deps...)
+		artProfileOutput = profileOutput
+	}
+
+	return r8Flags, r8Deps, artProfileOutput
 }
 
 type compileDexParams struct {
-	flags         javaBuilderFlags
-	sdkVersion    android.SdkSpec
-	minSdkVersion android.ApiLevel
-	classesJar    android.Path
-	jarName       string
+	flags           javaBuilderFlags
+	sdkVersion      android.SdkSpec
+	minSdkVersion   android.ApiLevel
+	classesJar      android.Path
+	jarName         string
+	artProfileInput *string
 }
 
-func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) android.OutputPath {
+// Adds --art-profile to r8/d8 command.
+// r8/d8 will output a generated profile file to match the optimized dex code.
+func (d *dexer) addArtProfile(ctx android.ModuleContext, dexParams *compileDexParams) (flags []string, deps android.Paths, artProfileOutputPath *android.OutputPath) {
+	if dexParams.artProfileInput != nil {
+		artProfileInputPath := android.PathForModuleSrc(ctx, *dexParams.artProfileInput)
+		artProfileOutputPathValue := android.PathForModuleOut(ctx, "profile.prof.txt").OutputPath
+		artProfileOutputPath = &artProfileOutputPathValue
+		flags = []string{
+			"--art-profile",
+			artProfileInputPath.String(),
+			artProfileOutputPath.String(),
+		}
+		deps = append(deps, artProfileInputPath)
+	}
+	return flags, deps, artProfileOutputPath
+
+}
+
+// Return the compiled dex jar and (optional) profile _after_ r8 optimization
+func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.OutputPath, *android.OutputPath) {
 
 	// Compile classes.jar into classes.dex and then javalib.jar
 	javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
@@ -406,6 +440,7 @@
 	}
 
 	useR8 := d.effectiveOptimizeEnabled()
+	var artProfileOutputPath *android.OutputPath
 	if useR8 {
 		proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
 		d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
@@ -418,8 +453,19 @@
 		d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
 		resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
 		d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
-		r8Flags, r8Deps := d.r8Flags(ctx, dexParams.flags)
-		r8Deps = append(r8Deps, commonDeps...)
+		implicitOutputs := android.WritablePaths{
+			proguardDictionary,
+			proguardUsageZip,
+			proguardConfiguration,
+		}
+		r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams)
+		if r8ArtProfileOutputPath != nil {
+			artProfileOutputPath = r8ArtProfileOutputPath
+			implicitOutputs = append(
+				implicitOutputs,
+				artProfileOutputPath,
+			)
+		}
 		rule := r8
 		args := map[string]string{
 			"r8Flags":        strings.Join(append(commonFlags, r8Flags...), " "),
@@ -436,10 +482,6 @@
 			rule = r8RE
 			args["implicits"] = strings.Join(r8Deps.Strings(), ",")
 		}
-		implicitOutputs := android.WritablePaths{
-			proguardDictionary,
-			proguardUsageZip,
-			proguardConfiguration}
 		if d.resourcesInput.Valid() {
 			implicitOutputs = append(implicitOutputs, resourcesOutput)
 			args["resourcesOutput"] = resourcesOutput.String()
@@ -454,18 +496,27 @@
 			Args:            args,
 		})
 	} else {
-		d8Flags, d8Deps := d8Flags(dexParams.flags)
+		implicitOutputs := android.WritablePaths{}
+		d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+		if d8ArtProfileOutputPath != nil {
+			artProfileOutputPath = d8ArtProfileOutputPath
+			implicitOutputs = append(
+				implicitOutputs,
+				artProfileOutputPath,
+			)
+		}
 		d8Deps = append(d8Deps, commonDeps...)
 		rule := d8
 		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
 			rule = d8RE
 		}
 		ctx.Build(pctx, android.BuildParams{
-			Rule:        rule,
-			Description: "d8",
-			Output:      javalibJar,
-			Input:       dexParams.classesJar,
-			Implicits:   d8Deps,
+			Rule:            rule,
+			Description:     "d8",
+			Output:          javalibJar,
+			Input:           dexParams.classesJar,
+			ImplicitOutputs: implicitOutputs,
+			Implicits:       d8Deps,
 			Args: map[string]string{
 				"d8Flags":        strings.Join(append(commonFlags, d8Flags...), " "),
 				"zipFlags":       zipFlags,
@@ -480,5 +531,5 @@
 		javalibJar = alignedJavalibJar
 	}
 
-	return javalibJar
+	return javalibJar, artProfileOutputPath
 }
diff --git a/java/dex_test.go b/java/dex_test.go
index 1ecdae0..eb017d5 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -662,3 +662,30 @@
 	android.AssertStringDoesContain(t, "expected aarimports's proguard flags",
 		appR8.Args["r8Flags"], "proguard.txt")
 }
+
+func TestR8FlagsArtProfile(t *testing.T) {
+	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
+		android_app {
+			name: "app",
+			srcs: ["foo.java"],
+			platform_apis: true,
+			dex_preopt: {
+				profile_guided: true,
+				profile: "profile.txt.prof",
+				enable_profile_rewriting: true,
+			},
+		}
+	`)
+
+	app := result.ModuleForTests("app", "android_common")
+	appR8 := app.Rule("r8")
+	android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags",
+		appR8.Args["r8Flags"], "--art-profile")
+
+	appDexpreopt := app.Rule("dexpreopt")
+	android.AssertStringDoesContain(t,
+		"expected --art-profile output to be used to create .prof binary",
+		appDexpreopt.RuleParams.Command,
+		"--create-profile-from=out/soong/.intermediates/app/android_common/profile.prof.txt --output-profile-type=app",
+	)
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4d6dbff..832b850 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -19,6 +19,8 @@
 	"sort"
 	"strings"
 
+	"github.com/google/blueprint/proptools"
+
 	"android/soong/android"
 	"android/soong/dexpreopt"
 )
@@ -139,6 +141,10 @@
 	// The path to the profile that dexpreopter accepts. It must be in the binary format. If this is
 	// set, it overrides the profile settings in `dexpreoptProperties`.
 	inputProfilePathOnHost android.Path
+
+	// The path to the profile that matches the dex optimized by r8/d8. It is in text format. If this is
+	// set, it will be converted to a binary profile which will be subsequently used for dexpreopt.
+	rewrittenProfile android.Path
 }
 
 type DexpreoptProperties struct {
@@ -158,6 +164,11 @@
 		// defaults to searching for a file that matches the name of this module in the default
 		// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
 		Profile *string `android:"path"`
+
+		// If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
+		// the optimized dex.
+		// The new profile will be subsequently used as the profile to dexpreopt the dex file.
+		Enable_profile_rewriting *bool
 	}
 
 	Dex_preopt_result struct {
@@ -421,13 +432,17 @@
 	if d.inputProfilePathOnHost != nil {
 		profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
 	} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
-		// If dex_preopt.profile_guided is not set, default it based on the existence of the
-		// dexprepot.profile option or the profile class listing.
-		if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
+		// If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
+		if d.EnableProfileRewriting() {
+			profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
+			profileIsTextListing = true
+		} else if profile := d.GetProfile(); profile != "" {
+			// If dex_preopt.profile_guided is not set, default it based on the existence of the
+			// dexprepot.profile option or the profile class listing.
 			profileClassListing = android.OptionalPathForPath(
-				android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile)))
+				android.PathForModuleSrc(ctx, profile))
 			profileBootListing = android.ExistentPathForSource(ctx,
-				ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
+				ctx.ModuleDir(), profile+"-boot")
 			profileIsTextListing = true
 		} else if global.ProfileDir != "" {
 			profileClassListing = android.ExistentPathForSource(ctx,
@@ -588,3 +603,23 @@
 func (d *dexpreopter) disableDexpreopt() {
 	d.shouldDisableDexpreopt = true
 }
+
+func (d *dexpreopter) EnableProfileRewriting() bool {
+	return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting)
+}
+
+func (d *dexpreopter) GetProfile() string {
+	return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile)
+}
+
+func (d *dexpreopter) GetProfileGuided() bool {
+	return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
+func (d *dexpreopter) GetRewrittenProfile() android.Path {
+	return d.rewrittenProfile
+}
+
+func (d *dexpreopter) SetRewrittenProfile(p android.Path) {
+	d.rewrittenProfile = p
+}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index ca81343..b94ad16 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -993,6 +993,7 @@
 func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
 
 	// Add API lint options.
+	treatDocumentationIssuesAsErrors := false
 	if doApiLint {
 		var newSince android.Paths
 		if d.properties.Check_api.Api_lint.New_since != nil {
@@ -1006,7 +1007,7 @@
 		// TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
 		if d.Name() != "android.car-system-stubs-docs" &&
 			d.Name() != "android.car-stubs-docs" {
-			cmd.Flag("--lints-as-errors")
+			treatDocumentationIssuesAsErrors = true
 			cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
 		}
 
@@ -1052,6 +1053,11 @@
 		cmd.FlagWithArg("--error-message:api-lint ", msg)
 	}
 
+	if !treatDocumentationIssuesAsErrors {
+		// Treat documentation issues as warnings, but error when new.
+		cmd.Flag("--error-when-new-category").Flag("Documentation")
+	}
+
 	// Add "check released" options. (Detect incompatible API changes from the last public release)
 	if doCheckReleased {
 		baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
diff --git a/java/java.go b/java/java.go
index 9fe7a2f..9fa6175 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2339,7 +2339,7 @@
 		classesJar:    al.stubsJar,
 		jarName:       ctx.ModuleName() + ".jar",
 	}
-	dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+	dexOutputFile, _ := al.dexer.compileDex(ctx, dexParams)
 	uncompressed := true
 	al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
 	dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
@@ -2723,7 +2723,7 @@
 				jarName:       jarName,
 			}
 
-			dexOutputFile = j.dexer.compileDex(ctx, dexParams)
+			dexOutputFile, _ = j.dexer.compileDex(ctx, dexParams)
 			if ctx.Failed() {
 				return
 			}
diff --git a/rust/compiler.go b/rust/compiler.go
index efc3dee..a2546a1 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -197,7 +197,7 @@
 	Features []string `android:"arch_variant"`
 
 	// list of configuration options to enable for this crate. To enable features, use the "features" property.
-	Cfgs []string `android:"arch_variant"`
+	Cfgs proptools.Configurable[[]string] `android:"arch_variant"`
 
 	// specific rust edition that should be used if the default version is not desired
 	Edition *string `android:"arch_variant"`
@@ -338,7 +338,7 @@
 }
 
 func cfgsToFlags(cfgs []string) []string {
-	flags := []string{}
+	flags := make([]string, 0, len(cfgs))
 	for _, cfg := range cfgs {
 		flags = append(flags, "--cfg '"+cfg+"'")
 	}
@@ -385,8 +385,9 @@
 func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = CommonDefaultCfgFlags(flags, ctx.RustModule().InVendor(), ctx.RustModule().InProduct())
 
-	flags.RustFlags = append(flags.RustFlags, cfgsToFlags(compiler.Properties.Cfgs)...)
-	flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(compiler.Properties.Cfgs)...)
+	cfgFlags := cfgsToFlags(compiler.Properties.Cfgs.GetOrDefault(ctx, nil))
+	flags.RustFlags = append(flags.RustFlags, cfgFlags...)
+	flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...)
 
 	return flags
 }
diff --git a/rust/library.go b/rust/library.go
index 1eb0c5e..2a21263 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -504,15 +504,19 @@
 	flags = library.baseCompiler.cfgFlags(ctx, flags)
 	flags = CommonLibraryCfgFlags(ctx, flags)
 
+	cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil)
+
 	if library.dylib() {
 		// We need to add a dependency on std in order to link crates as dylibs.
 		// The hack to add this dependency is guarded by the following cfg so
 		// that we don't force a dependency when it isn't needed.
-		library.baseCompiler.Properties.Cfgs = append(library.baseCompiler.Properties.Cfgs, "android_dylib")
+		cfgs = append(cfgs, "android_dylib")
 	}
 
-	flags.RustFlags = append(flags.RustFlags, cfgsToFlags(library.baseCompiler.Properties.Cfgs)...)
-	flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(library.baseCompiler.Properties.Cfgs)...)
+	cfgFlags := cfgsToFlags(cfgs)
+
+	flags.RustFlags = append(flags.RustFlags, cfgFlags...)
+	flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...)
 
 	return flags
 }
diff --git a/rust/rust.go b/rust/rust.go
index 93853e5..5790dd6 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -341,10 +341,6 @@
 	return Bool(mod.Properties.Bootstrap)
 }
 
-func (mod *Module) MustUseVendorVariant() bool {
-	return true
-}
-
 func (mod *Module) SubName() string {
 	return mod.Properties.SubName
 }