Merge "Add optimized build features in build_test_suites" into main
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f8c96ff..f562279 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -787,6 +787,10 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/)
 $(call add-clean-step, find $(OUT_DIR) -type f -name "*.jar" -print0 | xargs -0 rm -f)
 
+# Remove obsolete dexpreopt_config artifacts
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/dexpreopt_config/dexpreopt.config)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/dexpreopt_config/dexpreopt_soong.config)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index a215d31..a16365d 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -7055,18 +7055,19 @@
 
 endif
 
-$(DEXPREOPT_CONFIG_ZIP): $(SOONG_ZIP)
-	$(hide) mkdir -p $(dir $@) $(PRODUCT_OUT)/dexpreopt_config
-
+$(DEXPREOPT_CONFIG_ZIP): PRIVATE_DEXPREOPT_CONFIG_ZIP_PARAMS :=
 ifeq (,$(TARGET_BUILD_UNBUNDLED))
 ifneq (,$(DEX_PREOPT_CONFIG_FOR_MAKE))
-	$(hide) cp $(DEX_PREOPT_CONFIG_FOR_MAKE) $(PRODUCT_OUT)/dexpreopt_config
+$(DEXPREOPT_CONFIG_ZIP): PRIVATE_DEXPREOPT_CONFIG_ZIP_PARAMS += -e $(notdir $(DEX_PREOPT_CONFIG_FOR_MAKE)) -f $(DEX_PREOPT_CONFIG_FOR_MAKE)
 endif
 ifneq (,$(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE))
-	$(hide) cp $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE) $(PRODUCT_OUT)/dexpreopt_config
+$(DEXPREOPT_CONFIG_ZIP): PRIVATE_DEXPREOPT_CONFIG_ZIP_PARAMS += -e $(notdir $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE)) -f $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE)
 endif
 endif #!TARGET_BUILD_UNBUNDLED
-	$(hide) $(SOONG_ZIP) -d -o $@ -C $(PRODUCT_OUT)/dexpreopt_config -D $(PRODUCT_OUT)/dexpreopt_config
+
+$(DEXPREOPT_CONFIG_ZIP): $(SOONG_ZIP)
+	$(hide) mkdir -p $(dir $@) $(PRODUCT_OUT)/dexpreopt_config
+	$(hide) $(SOONG_ZIP) -d -o $@ -C $(PRODUCT_OUT)/dexpreopt_config -D $(PRODUCT_OUT)/dexpreopt_config $(PRIVATE_DEXPREOPT_CONFIG_ZIP_PARAMS)
 
 .PHONY: dexpreopt_config_zip
 dexpreopt_config_zip: $(DEXPREOPT_CONFIG_ZIP)
@@ -7605,6 +7606,7 @@
 sdk_dep_file := $(sdk_dir)/sdk_deps.mk
 
 ATREE_FILES :=
+include development/build/tools/sdk-preprocess-files.mk
 -include $(sdk_dep_file)
 
 # if we don't have a real list, then use "everything"
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index ea6ebd3..274a7de 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -111,6 +111,8 @@
 
 $(call add_soong_config_var_value,ANDROID,release_binder_death_recipient_weak_from_jni,$(RELEASE_BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI))
 
+$(call add_soong_config_var_value,ANDROID,release_libpower_no_lock_binder_txn,$(RELEASE_LIBPOWER_NO_LOCK_BINDER_TXN))
+
 $(call add_soong_config_var_value,ANDROID,release_package_libandroid_runtime_punch_holes,$(RELEASE_PACKAGE_LIBANDROID_RUNTIME_PUNCH_HOLES))
 
 $(call add_soong_config_var_value,ANDROID,release_selinux_data_data_ignore,$(RELEASE_SELINUX_DATA_DATA_IGNORE))
diff --git a/core/config.mk b/core/config.mk
index c7567e3..43304d5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1255,14 +1255,12 @@
 
 include $(BUILD_SYSTEM)/dumpvar.mk
 
-ifneq ($(KEEP_VNDK),true)
 ifdef BOARD_VNDK_VERSION
 BOARD_VNDK_VERSION=
 endif
 ifdef PLATFORM_VNDK_VERSION
 PLATFORM_VNDK_VERSION=
 endif
-endif
 
 ifeq (true,$(FULL_SYSTEM_OPTIMIZE_JAVA))
 ifeq (false,$(SYSTEM_OPTIMIZE_JAVA))
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 93cec64..c063f60 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -50,13 +50,6 @@
 # Release config
 include $(BUILD_SYSTEM)/release_config.mk
 
-# Set default value of KEEP_VNDK.
-ifeq ($(RELEASE_DEPRECATE_VNDK),true)
-  KEEP_VNDK ?= false
-else
-  KEEP_VNDK ?= true
-endif
-
 # ---------------------------------------------------------------
 # Set up version information
 include $(BUILD_SYSTEM)/version_util.mk
diff --git a/core/node_fns.mk b/core/node_fns.mk
index 144eb8b..d2cee9e 100644
--- a/core/node_fns.mk
+++ b/core/node_fns.mk
@@ -203,7 +203,7 @@
   $(call _expand-inherited-values,$(1),$(2),$(3),$(4))
 
   $(eval $(1).$(2).inherited :=)
-  $(eval _include_stack := $(wordlist 2,9999,$$(_include_stack)))
+  $(eval _include_stack := $(wordlist 2,9999,$(_include_stack)))
 endef
 
 #
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index e715fd1..a96ea8f 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -22,50 +22,6 @@
 
 
 # -----------------------------------------------------------------
-# Release Config Flags
-
-# Create a summary file of build flags for each partition
-# $(1): built build flags json file
-# $(2): installed build flags json file
-# $(3): flag names
-define generate-partition-build-flag-file
-$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
-$(eval $(strip $(1)): PRIVATE_FLAG_NAMES := $(strip $(3)))
-$(strip $(1)):
-	mkdir -p $$(dir $$(PRIVATE_OUT))
-	echo '{' > $$(PRIVATE_OUT)
-	echo '"flags": [' >> $$(PRIVATE_OUT)
-	$$(foreach flag, $$(PRIVATE_FLAG_NAMES), \
-		( \
-			printf '  { "name": "%s", "value": "%s", ' \
-					'$$(flag)' \
-					'$$(_ALL_RELEASE_FLAGS.$$(flag).VALUE)' \
-					; \
-			printf '"set": "%s", "default": "%s", "declared": "%s" }' \
-					'$$(_ALL_RELEASE_FLAGS.$$(flag).SET_IN)' \
-					'$$(_ALL_RELEASE_FLAGS.$$(flag).DEFAULT)' \
-					'$$(_ALL_RELEASE_FLAGS.$$(flag).DECLARED_IN)' \
-					; \
-			printf '$$(if $$(filter $$(lastword $$(PRIVATE_FLAG_NAMES)),$$(flag)),,$$(comma))\n' ; \
-		) >> $$(PRIVATE_OUT) ; \
-	)
-	echo "]" >> $$(PRIVATE_OUT)
-	echo "}" >> $$(PRIVATE_OUT)
-$(call copy-one-file, $(1), $(2))
-endef
-
-$(foreach partition, $(_FLAG_PARTITIONS), \
-	$(eval build_flag_summaries.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/build_flags.json) \
-	$(eval $(call generate-partition-build-flag-file, \
-				$(TARGET_OUT_FLAGS)/$(partition)/build_flags.json, \
-				$(build_flag_summaries.$(partition)), \
-				$(_ALL_RELEASE_FLAGS.PARTITIONS.$(partition)) \
-			) \
-	) \
-)
-
-
-# -----------------------------------------------------------------
 # Aconfig Flags
 
 # Create a summary file of build flags for each partition
diff --git a/core/product.mk b/core/product.mk
index 68d7721..7908e1d 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -304,9 +304,6 @@
 # This flag implies PRODUCT_USE_DYNAMIC_PARTITIONS.
 _product_single_value_vars += PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
 
-# List of tags that will be used to gate blueprint modules from the build graph
-_product_list_vars += PRODUCT_INCLUDE_TAGS
-
 # List of directories that will be used to gate blueprint modules from the build graph
 _product_list_vars += PRODUCT_SOURCE_ROOT_DIRS
 
@@ -491,6 +488,11 @@
 # Enables 16KB developer option for device if set.
 _product_single_value_vars += PRODUCT_16K_DEVELOPER_OPTION
 
+# If set, adb root will be disabled (really ro.debuggable=0) in userdebug
+# builds. It's already off disabled in user builds. Eng builds are unaffected
+# by this flag.
+_product_single_value_vars += PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
+
 .KATI_READONLY := _product_single_value_vars _product_list_vars
 _product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
 
diff --git a/core/product_config.mk b/core/product_config.mk
index f21c1c4..f939690 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -280,27 +280,6 @@
 
 current_product_makefile :=
 
-#############################################################################
-# Check product include tag allowlist
-BLUEPRINT_INCLUDE_TAGS_ALLOWLIST := \
-  com.android.mainline_go \
-  com.android.mainline \
-  mainline_module_prebuilt_nightly \
-  mainline_module_prebuilt_monthly_release
-.KATI_READONLY := BLUEPRINT_INCLUDE_TAGS_ALLOWLIST
-$(foreach include_tag,$(PRODUCT_INCLUDE_TAGS), \
-	$(if $(filter $(include_tag),$(BLUEPRINT_INCLUDE_TAGS_ALLOWLIST)),,\
-	$(call pretty-error, $(include_tag) is not in BLUEPRINT_INCLUDE_TAGS_ALLOWLIST: $(BLUEPRINT_INCLUDE_TAGS_ALLOWLIST))))
-# Create default PRODUCT_INCLUDE_TAGS
-ifeq (, $(PRODUCT_INCLUDE_TAGS))
-# Soong analysis is global: even though a module might not be relevant to a specific product (e.g. build_tools for aosp_arm),
-# we still analyse it.
-# This means that in setups where we two have two prebuilts of module_sdk, we need a "default" to use in analysis
-# This should be a no-op in aosp and internal since no Android.bp file contains blueprint_package_includes
-# Use the big android one and main-based prebuilts by default
-PRODUCT_INCLUDE_TAGS += com.android.mainline mainline_module_prebuilt_nightly
-endif
-
 # AOSP and Google products currently share the same `apex_contributions` in next.
 # This causes issues when building <aosp_product>-next-userdebug in main.
 # Create a temporary allowlist to ignore the google apexes listed in `contents` of apex_contributions of `next`
diff --git a/core/soong_config.mk b/core/soong_config.mk
index be5a6e6..dd7e4e6 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -282,7 +282,7 @@
 $(call add_json_bool, BoardMoveRecoveryResourcesToVendorBoot, $(filter true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
 $(call add_json_str,  PrebuiltHiddenApiDir, $(BOARD_PREBUILT_HIDDENAPI_DIR))
 
-$(call add_json_str,  ShippingApiLevel, $(PRODUCT_SHIPPING_API_LEVEL))
+$(call add_json_str,  Shipping_api_level, $(PRODUCT_SHIPPING_API_LEVEL))
 
 $(call add_json_list, BuildBrokenPluginValidation,         $(BUILD_BROKEN_PLUGIN_VALIDATION))
 $(call add_json_bool, BuildBrokenClangProperty,            $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
@@ -313,7 +313,6 @@
 
 $(call add_json_bool, IgnorePrefer32OnDevice, $(filter true,$(IGNORE_PREFER32_ON_DEVICE)))
 
-$(call add_json_list, IncludeTags,                $(PRODUCT_INCLUDE_TAGS))
 $(call add_json_list, SourceRootDirs,             $(PRODUCT_SOURCE_ROOT_DIRS))
 
 $(call add_json_list, AfdoProfiles,                $(ALL_AFDO_PROFILES))
@@ -327,8 +326,6 @@
 
 $(call add_json_bool, ReleaseDefaultModuleBuildFromSource,   $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE))
 
-$(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
-
 $(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
 
 $(call add_json_bool, BuildIgnoreApexContributionContents, $(PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS))
diff --git a/core/sysprop_config.mk b/core/sysprop_config.mk
index e8428c8..6e3da72 100644
--- a/core/sysprop_config.mk
+++ b/core/sysprop_config.mk
@@ -195,6 +195,7 @@
 
 user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
 enable_target_debugging := true
+enable_dalvik_lock_contention_logging := true
 ifneq (,$(user_variant))
   # Target is secure in user builds.
   ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=1
@@ -207,6 +208,13 @@
   ifneq ($(user_variant),userdebug)
     # Disable debugging in plain user builds.
     enable_target_debugging :=
+    enable_dalvik_lock_contention_logging :=
+  else
+    # Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
+    # is set.
+    ifneq (,$(strip $(PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG)))
+      enable_target_debugging :=
+    endif
   endif
 
   # Disallow mock locations by default for user builds
@@ -221,16 +229,22 @@
   ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=1
 endif # !user_variant
 
+ifeq (true,$(strip $(enable_dalvik_lock_contention_logging)))
+  # Enable Dalvik lock contention logging.
+  ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500
+endif # !enable_dalvik_lock_contention_logging
+
 ifeq (true,$(strip $(enable_target_debugging)))
   # Target is more debuggable and adbd is on by default
   ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=1
-  # Enable Dalvik lock contention logging.
-  ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500
 else # !enable_target_debugging
   # Target is less debuggable and adbd is off by default
   ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=0
 endif # !enable_target_debugging
 
+enable_target_debugging:=
+enable_dalvik_lock_contention_logging:=
+
 ifneq ($(filter sdk sdk_addon,$(MAKECMDGOALS)),)
 _is_sdk_build := true
 endif
diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk
index c41de63..17c76af 100644
--- a/core/tasks/meta-lic.mk
+++ b/core/tasks/meta-lic.mk
@@ -147,3 +147,24 @@
 # Moved here from hardware/interfaces/tv/Android.mk
 $(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_0.xml))
 $(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_1.xml))
+
+# Moved here from device/generic/goldfish/Android.mk
+$(eval $(call declare-1p-copy-files,device/generic/goldfish/data,))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish/input,))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish/wifi,))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish/camera,))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,hals.conf))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,init.qemu-adb-keys.sh))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,init.system_ext.rc))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,.json))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,ueventd.rc))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,wpa_supplicant.conf))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,media_profiles_V1_0.xml))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,init.ranchu.rc))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,fstab.ranchu))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,display_settings.xml))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,display_settings_freeform.xml))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,device_state_configuration.xml))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,init.ranchu-core.sh))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,init.ranchu-net.sh))
+$(eval $(call declare-1p-copy-files,device/generic/goldfish,audio_policy_configuration.xml))
diff --git a/envsetup.sh b/envsetup.sh
index 352d664..0ccb631 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -865,49 +865,6 @@
     run_tool_with_logging "ADB" $ADB "${@}"
 }
 
-function run_tool_with_logging() {
-  # Run commands in a subshell for us to handle forced terminations with a trap
-  # handler.
-  (
-  local tool_tag="$1"
-  shift
-  local tool_binary="$1"
-  shift
-
-  # If the logger is not configured, run the original command and return.
-  if [[ -z "${ANDROID_TOOL_LOGGER}" ]]; then
-     "${tool_binary}" "${@}"
-     return $?
-  fi
-
-  # Otherwise, run the original command and call the logger when done.
-  local start_time
-  start_time=$(date +%s.%N)
-  local logger=${ANDROID_TOOL_LOGGER}
-
-  # Install a trap to call the logger even when the process terminates abnormally.
-  # The logger is run in the background and its output suppressed to avoid
-  # interference with the user flow.
-  trap '
-  exit_code=$?;
-  # Remove the trap to prevent duplicate log.
-  trap - EXIT;
-  "${logger}" \
-    --tool_tag="${tool_tag}" \
-    --start_timestamp="${start_time}" \
-    --end_timestamp="$(date +%s.%N)" \
-    --tool_args="$*" \
-    --exit_code="${exit_code}" \
-    ${ANDROID_TOOL_LOGGER_EXTRA_ARGS} \
-    > /dev/null 2>&1 &
-  exit ${exit_code}
-  ' SIGINT SIGTERM SIGQUIT EXIT
-
-  # Run the original command.
-  "${tool_binary}" "${@}"
-  )
-}
-
 # communicate with a running device or emulator, set up necessary state,
 # and run the hat command.
 function runhat()
@@ -1195,6 +1152,7 @@
 unset refreshmod
 unset resgrep
 unset rsgrep
+unset run_tool_with_logging
 unset sepgrep
 unset sgrep
 unset startviewserver
diff --git a/shell_utils.sh b/shell_utils.sh
index 450bb83..86f3f49 100644
--- a/shell_utils.sh
+++ b/shell_utils.sh
@@ -126,4 +126,27 @@
 }
 
 
+function log_tool_invocation()
+{
+    if [[ -z $ANDROID_TOOL_LOGGER ]]; then
+        return
+    fi
+
+    LOG_TOOL_TAG=$1
+    LOG_START_TIME=$(date +%s.%N)
+    trap '
+        exit_code=$?;
+        # Remove the trap to prevent duplicate log.
+        trap - EXIT;
+        $ANDROID_TOOL_LOGGER \
+                --tool_tag="${LOG_TOOL_TAG}" \
+                --start_timestamp="${LOG_START_TIME}" \
+                --end_timestamp="$(date +%s.%N)" \
+                --tool_args="$*" \
+                --exit_code="${exit_code}" \
+                ${ANDROID_TOOL_LOGGER_EXTRA_ARGS} \
+           > /dev/null 2>&1 &
+        exit ${exit_code}
+    ' SIGINT SIGTERM SIGQUIT EXIT
+}
 
diff --git a/target/product/base_product.mk b/target/product/base_product.mk
index 5446064..0ac220b 100644
--- a/target/product/base_product.mk
+++ b/target/product/base_product.mk
@@ -16,6 +16,7 @@
 
 # Base modules and settings for the product partition.
 PRODUCT_PACKAGES += \
+    build_flag_product \
     fs_config_dirs_product \
     fs_config_files_product \
     group_product \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 634bf66..98adba5 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -45,6 +45,7 @@
     bu \
     bugreport \
     bugreportz \
+    build_flag_system \
     cgroups.json \
     charger \
     cmd \
diff --git a/target/product/base_system_ext.mk b/target/product/base_system_ext.mk
index 76f008f..92ca227 100644
--- a/target/product/base_system_ext.mk
+++ b/target/product/base_system_ext.mk
@@ -16,6 +16,7 @@
 
 # Base modules and settings for the system_ext partition.
 PRODUCT_PACKAGES += \
+    build_flag_system_ext \
     fs_config_dirs_system_ext \
     fs_config_files_system_ext \
     group_system_ext \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index ec3de75..1854f97 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -18,6 +18,7 @@
 PRODUCT_PACKAGES += \
     adbd.recovery \
     android.hardware.health@2.0-impl-default.recovery \
+    build_flag_vendor \
     cgroups.recovery.json \
     charger.recovery \
     init_second_stage.recovery \
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 5044a39..da1284e 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -58,9 +58,6 @@
         device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
 endif
 
-# b/308878144 no more VNDK on 24Q1 and beyond
-KEEP_VNDK ?= false
-
 # Support additional VNDK snapshots
 PRODUCT_EXTRA_VNDK_VERSIONS := \
     30 \
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index d9c3c9a..dc78368 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -176,4 +176,5 @@
     dalvik.vm.usap_pool_refill_delay_ms?=3000
 
 PRODUCT_SYSTEM_PROPERTIES += \
-    dalvik.vm.useartservice=true
+    dalvik.vm.useartservice=true \
+    dalvik.vm.enable_pr_dexopt=true
diff --git a/tests/Android.bp b/tests/Android.bp
deleted file mode 100644
index 39debf5..0000000
--- a/tests/Android.bp
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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 {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-    default_team: "trendy_team_build",
-}
-
-python_test_host {
-    name: "run_tool_with_logging_test",
-    main: "run_tool_with_logging_test.py",
-    pkg_path: "testdata",
-    srcs: [
-        "run_tool_with_logging_test.py",
-    ],
-    test_options: {
-        unit_test: true,
-    },
-    data: [
-        ":envsetup_minimum.zip",
-        ":tool_event_logger",
-    ],
-    test_suites: [
-        "general-tests",
-    ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
-}
diff --git a/tests/run_tool_with_logging_test.py b/tests/run_tool_with_logging_test.py
deleted file mode 100644
index 6f9b59c..0000000
--- a/tests/run_tool_with_logging_test.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# Copyright 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 dataclasses
-import glob
-from importlib import resources
-import logging
-import os
-from pathlib import Path
-import re
-import shutil
-import signal
-import stat
-import subprocess
-import sys
-import tempfile
-import textwrap
-import time
-import unittest
-import zipfile
-
-EXII_RETURN_CODE = 0
-INTERRUPTED_RETURN_CODE = 130
-
-
-class RunToolWithLoggingTest(unittest.TestCase):
-
-  @classmethod
-  def setUpClass(cls):
-    super().setUpClass()
-    # Configure to print logging to stdout.
-    logging.basicConfig(filename=None, level=logging.DEBUG)
-    console = logging.StreamHandler(sys.stdout)
-    logging.getLogger("").addHandler(console)
-
-  def setUp(self):
-    super().setUp()
-    self.working_dir = tempfile.TemporaryDirectory()
-    # Run all the tests from working_dir which is our temp Android build top.
-    os.chdir(self.working_dir.name)
-    # Extract envsetup.zip which contains the envsetup.sh and other dependent
-    # scripts required to set up the build environments.
-    with resources.files("testdata").joinpath("envsetup.zip").open("rb") as p:
-      with zipfile.ZipFile(p, "r") as zip_f:
-        zip_f.extractall()
-
-  def tearDown(self):
-    self.working_dir.cleanup()
-    super().tearDown()
-
-  def test_does_not_log_when_logger_var_empty(self):
-    test_tool = TestScript.create(self.working_dir)
-
-    self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER=""
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    test_tool.assert_called_once_with_args("arg1 arg2")
-
-  def test_does_not_log_with_logger_unset(self):
-    test_tool = TestScript.create(self.working_dir)
-
-    self._run_script_and_wait(f"""
-      unset ANDROID_TOOL_LOGGER
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    test_tool.assert_called_once_with_args("arg1 arg2")
-
-  def test_log_success_with_logger_enabled(self):
-    test_tool = TestScript.create(self.working_dir)
-    test_logger = TestScript.create(self.working_dir)
-
-    self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    test_tool.assert_called_once_with_args("arg1 arg2")
-    expected_logger_args = (
-        "--tool_tag=FAKE_TOOL --start_timestamp=\d+\.\d+ --end_timestamp="
-        "\d+\.\d+ --tool_args=arg1 arg2 --exit_code=0"
-    )
-    test_logger.assert_called_once_with_args(expected_logger_args)
-
-  def test_run_tool_output_is_same_with_and_without_logging(self):
-    test_tool = TestScript.create(self.working_dir, "echo 'tool called'")
-    test_logger = TestScript.create(self.working_dir)
-
-    run_tool_with_logging_stdout, run_tool_with_logging_stderr = (
-        self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-    )
-
-    run_tool_without_logging_stdout, run_tool_without_logging_stderr = (
-        self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      {test_tool.executable} arg1 arg2
-    """)
-    )
-
-    self.assertEqual(
-        run_tool_with_logging_stdout, run_tool_without_logging_stdout
-    )
-    self.assertEqual(
-        run_tool_with_logging_stderr, run_tool_without_logging_stderr
-    )
-
-  def test_logger_output_is_suppressed(self):
-    test_tool = TestScript.create(self.working_dir)
-    test_logger = TestScript.create(self.working_dir, "echo 'logger called'")
-
-    run_tool_with_logging_output, _ = self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    self.assertNotIn("logger called", run_tool_with_logging_output)
-
-  def test_logger_error_is_suppressed(self):
-    test_tool = TestScript.create(self.working_dir)
-    test_logger = TestScript.create(
-        self.working_dir, "echo 'logger failed' > /dev/stderr; exit 1"
-    )
-
-    _, err = self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    self.assertNotIn("logger failed", err)
-
-  def test_log_success_when_tool_interrupted(self):
-    test_tool = TestScript.create(self.working_dir, script_body="sleep 100")
-    test_logger = TestScript.create(self.working_dir)
-
-    process = self._run_script_in_build_env(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    pgid = os.getpgid(process.pid)
-    # Give sometime for the subprocess to start.
-    time.sleep(1)
-    # Kill the subprocess and any processes created in the same group.
-    os.killpg(pgid, signal.SIGINT)
-
-    returncode, _, _ = self._wait_for_process(process)
-    self.assertEqual(returncode, INTERRUPTED_RETURN_CODE)
-
-    expected_logger_args = (
-        "--tool_tag=FAKE_TOOL --start_timestamp=\d+\.\d+ --end_timestamp="
-        "\d+\.\d+ --tool_args=arg1 arg2 --exit_code=130"
-    )
-    test_logger.assert_called_once_with_args(expected_logger_args)
-
-  def test_logger_can_be_toggled_on(self):
-    test_tool = TestScript.create(self.working_dir)
-    test_logger = TestScript.create(self.working_dir)
-
-    self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER=""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    test_logger.assert_called_with_times(1)
-
-  def test_logger_can_be_toggled_off(self):
-    test_tool = TestScript.create(self.working_dir)
-    test_logger = TestScript.create(self.working_dir)
-
-    self._run_script_and_wait(f"""
-      ANDROID_TOOL_LOGGER="{test_logger.executable}"
-      ANDROID_TOOL_LOGGER=""
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    test_logger.assert_not_called()
-
-  def test_integration_tool_event_logger_dry_run(self):
-    test_tool = TestScript.create(self.working_dir)
-    logger_path = self._import_logger()
-
-    self._run_script_and_wait(f"""
-      TMPDIR="{self.working_dir.name}"
-      ANDROID_TOOL_LOGGER="{logger_path}"
-      ANDROID_TOOL_LOGGER_EXTRA_ARGS="--dry_run"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2
-    """)
-
-    self._assert_logger_dry_run()
-
-  def test_tool_args_do_not_fail_logger(self):
-    test_tool = TestScript.create(self.working_dir)
-    logger_path = self._import_logger()
-
-    self._run_script_and_wait(f"""
-      TMPDIR="{self.working_dir.name}"
-      ANDROID_TOOL_LOGGER="{logger_path}"
-      ANDROID_TOOL_LOGGER_EXTRA_ARGS="--dry_run"
-      run_tool_with_logging "FAKE_TOOL" {test_tool.executable} --tool-arg1
-    """)
-
-    self._assert_logger_dry_run()
-
-  def _import_logger(self) -> Path:
-    logger = "tool_event_logger"
-    logger_path = Path(self.working_dir.name).joinpath(logger)
-    with resources.as_file(resources.files("testdata").joinpath(logger)) as p:
-      shutil.copy(p, logger_path)
-    Path.chmod(logger_path, 0o755)
-    return logger_path
-
-  def _assert_logger_dry_run(self):
-    log_files = glob.glob(self.working_dir.name + "/tool_event_logger_*/*.log")
-    self.assertEqual(len(log_files), 1)
-
-    with open(log_files[0], "r") as f:
-      lines = f.readlines()
-      self.assertEqual(len(lines), 1)
-      self.assertIn("dry run", lines[0])
-
-  def _create_build_env_script(self) -> str:
-    return f"""
-      source {Path(self.working_dir.name).joinpath("build/make/envsetup.sh")}
-    """
-
-  def _run_script_and_wait(self, test_script: str) -> tuple[str, str]:
-    process = self._run_script_in_build_env(test_script)
-    returncode, out, err = self._wait_for_process(process)
-    logging.debug("script stdout: %s", out)
-    logging.debug("script stderr: %s", err)
-    self.assertEqual(returncode, EXII_RETURN_CODE)
-    return out, err
-
-  def _run_script_in_build_env(self, test_script: str) -> subprocess.Popen:
-    setup_build_env_script = self._create_build_env_script()
-    return subprocess.Popen(
-        setup_build_env_script + test_script,
-        shell=True,
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE,
-        text=True,
-        start_new_session=True,
-        executable="/bin/bash",
-        )
-
-  def _wait_for_process(
-      self, process: subprocess.Popen
-  ) -> tuple[int, str, str]:
-    pgid = os.getpgid(process.pid)
-    out, err = process.communicate()
-    # Wait for all process in the same group to complete since the logger runs
-    # as a separate detached process.
-    self._wait_for_process_group(pgid)
-    return (process.returncode, out, err)
-
-  def _wait_for_process_group(self, pgid: int, timeout: int = 5):
-    """Waits for all subprocesses within the process group to complete."""
-    start_time = time.time()
-    while True:
-      if time.time() - start_time > timeout:
-        raise TimeoutError(
-            f"Process group did not complete after {timeout} seconds"
-        )
-      for pid in os.listdir("/proc"):
-        if pid.isdigit():
-          try:
-            if os.getpgid(int(pid)) == pgid:
-              time.sleep(0.1)
-              break
-          except (FileNotFoundError, PermissionError, ProcessLookupError):
-            pass
-      else:
-        # All processes have completed.
-        break
-
-
-@dataclasses.dataclass
-class TestScript:
-  executable: Path
-  output_file: Path
-
-  def create(temp_dir: Path, script_body: str = ""):
-    with tempfile.NamedTemporaryFile(dir=temp_dir.name, delete=False) as f:
-      output_file = f.name
-
-    with tempfile.NamedTemporaryFile(dir=temp_dir.name, delete=False) as f:
-      executable = f.name
-      executable_contents = textwrap.dedent(f"""
-      #!/bin/bash
-
-      echo "${{@}}" >> {output_file}
-      {script_body}
-      """)
-      f.write(executable_contents.encode("utf-8"))
-
-    Path.chmod(f.name, os.stat(f.name).st_mode | stat.S_IEXEC)
-
-    return TestScript(executable, output_file)
-
-  def assert_called_with_times(self, expected_call_times: int):
-    lines = self._read_contents_from_output_file()
-    assert len(lines) == expected_call_times, (
-        f"Expect to call {expected_call_times} times, but actually called"
-        f" {len(lines)} times."
-    )
-
-  def assert_called_with_args(self, expected_args: str):
-    lines = self._read_contents_from_output_file()
-    assert len(lines) > 0
-    assert re.search(expected_args, lines[0]), (
-        f"Expect to call with args {expected_args}, but actually called with"
-        f" args {lines[0]}."
-    )
-
-  def assert_not_called(self):
-    self.assert_called_with_times(0)
-
-  def assert_called_once_with_args(self, expected_args: str):
-    self.assert_called_with_times(1)
-    self.assert_called_with_args(expected_args)
-
-  def _read_contents_from_output_file(self) -> list[str]:
-    with open(self.output_file, "r") as f:
-      return f.readlines()
-
-
-if __name__ == "__main__":
-  unittest.main()