Merge "Revert "Add apex com.android.runtime.host artifact""
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index 96d3648..03e68ae 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -74,18 +74,21 @@
 TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art
 
 # Jar files for core.art.
-HOST_CORE_DEX_LOCATIONS   := $(foreach jar,$(HOST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
+TEST_CORE_JARS := core-oj core-libart core-simple conscrypt okhttp bouncycastle
+HOST_TEST_CORE_JARS   := $(addsuffix -hostdex,$(TEST_CORE_JARS))
+TARGET_TEST_CORE_JARS := $(addsuffix -testdex,$(TEST_CORE_JARS))
+HOST_CORE_DEX_LOCATIONS   := $(foreach jar,$(HOST_TEST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
 ifeq ($(ART_TEST_ANDROID_ROOT),)
-TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_CORE_JARS),/$(DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
+TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_TEST_CORE_JARS),/$(DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
 else
-TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_CORE_JARS),$(ART_TEST_ANDROID_ROOT)/framework/$(jar).jar)
+TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(ART_TEST_ANDROID_ROOT)/framework/$(jar).jar)
 endif
 
-HOST_CORE_DEX_FILES   := $(foreach jar,$(HOST_CORE_JARS),  $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
-TARGET_CORE_DEX_FILES := $(foreach jar,$(TARGET_CORE_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
+HOST_CORE_DEX_FILES   := $(foreach jar,$(HOST_TEST_CORE_JARS),  $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
+TARGET_CORE_DEX_FILES := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
 
-ART_HOST_DEX_DEPENDENCIES := $(foreach jar,$(HOST_CORE_JARS),$(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
-ART_TARGET_DEX_DEPENDENCIES := $(foreach jar,$(TARGET_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+ART_HOST_DEX_DEPENDENCIES := $(foreach jar,$(HOST_TEST_CORE_JARS),$(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
+ART_TARGET_DEX_DEPENDENCIES := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
 
 ART_CORE_SHARED_LIBRARIES := libjavacore libopenjdk libopenjdkjvm libopenjdkjvmti
 ART_CORE_SHARED_DEBUG_LIBRARIES := libopenjdkd libopenjdkjvmd libopenjdkjvmtid
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index 17d0232..d8014bd 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -129,7 +129,7 @@
     LOCAL_DEX_PREOPT := false
     LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_test.mk $(4)
     LOCAL_MODULE_TAGS := tests
-    LOCAL_JAVA_LIBRARIES := $(TARGET_CORE_JARS)
+    LOCAL_JAVA_LIBRARIES := $(TARGET_TEST_CORE_JARS)
     LOCAL_MODULE_PATH := $(3)
     LOCAL_DEX_PREOPT_IMAGE_LOCATION := $(TARGET_CORE_IMG_OUT)
     ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
@@ -145,7 +145,7 @@
     LOCAL_NO_STANDARD_LIBRARIES := true
     LOCAL_DEX_PREOPT := false
     LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_test.mk $(4)
-    LOCAL_JAVA_LIBRARIES := $(HOST_CORE_JARS)
+    LOCAL_JAVA_LIBRARIES := $(HOST_TEST_CORE_JARS)
     LOCAL_DEX_PREOPT_IMAGE := $(HOST_CORE_IMG_LOCATION)
     ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
       LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(LOCAL_PATH)/$(2)/main.list --minimal-main-dex
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 9a5e26b..6885946 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -454,7 +454,10 @@
     $$($(3)TARGET_OUT_SHARED_LIBRARIES)/libopenjdkd.so \
     $$(TARGET_OUT_JAVA_LIBRARIES)/core-libart-testdex.jar \
     $$(TARGET_OUT_JAVA_LIBRARIES)/core-oj-testdex.jar \
-    $$(TARGET_OUT_JAVA_LIBRARIES)/core-simple-testdex.jar
+    $$(TARGET_OUT_JAVA_LIBRARIES)/core-simple-testdex.jar \
+    $$(TARGET_OUT_JAVA_LIBRARIES)/conscrypt-testdex.jar \
+    $$(TARGET_OUT_JAVA_LIBRARIES)/okhttp-testdex.jar \
+    $$(TARGET_OUT_JAVA_LIBRARIES)/bouncycastle-testdex.jar
 
   ART_TEST_TARGET_GTEST_DEPENDENCIES += $$(gtest_deps)
 
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 159e5c1..f1a21e8 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -72,6 +72,13 @@
     private_key: "com.android.runtime.pem",
 }
 
+prebuilt_etc {
+    name: "com.android.runtime.ld.config.txt",
+    src: "ld.config.txt",
+    filename: "ld.config.txt",
+    installable: false,
+}
+
 // TODO: Introduce `apex_defaults` to factor common parts of `apex`
 // module definitions below?
 
@@ -97,9 +104,8 @@
             binaries: [],
         }
     },
+    prebuilts: ["com.android.runtime.ld.config.txt"],
     key: "com.android.runtime.key",
-    // TODO: Also package a `ld.config.txt` config file (to be placed in `etc/`).
-    // ...
 }
 
 // "Debug" version of the Runtime APEX module (containing both release and
@@ -126,7 +132,6 @@
             binaries: art_tools_binaries,
         }
     },
+    prebuilts: ["com.android.runtime.ld.config.txt"],
     key: "com.android.runtime.key",
-    // TODO: Also package a `ld.config.txt` config file (to be placed in `etc/`).
-    // ...
 }
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
new file mode 100644
index 0000000..ac4d1eb
--- /dev/null
+++ b/build/apex/ld.config.txt
@@ -0,0 +1 @@
+# TODO: Write me.
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 97a5f24..92dd932 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -192,24 +192,12 @@
   }
 
   int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
-    Runtime* runtime = Runtime::Current();
-
-    const std::vector<gc::space::ImageSpace*>& image_spaces =
-        runtime->GetHeap()->GetBootImageSpaces();
-    if (image_spaces.empty()) {
-      *error_msg = "No image location found for Dex2Oat.";
+    std::vector<std::string> argv;
+    if (!CommonRuntimeTest::StartDex2OatCommandLine(&argv, error_msg)) {
       return false;
     }
-    std::string image_location = image_spaces[0]->GetImageLocation();
 
-    std::vector<std::string> argv;
-    argv.push_back(runtime->GetCompilerExecutable());
-
-    if (runtime->IsJavaDebuggable()) {
-      argv.push_back("--debuggable");
-    }
-    runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
-
+    Runtime* runtime = Runtime::Current();
     if (!runtime->IsVerificationEnabled()) {
       argv.push_back("--compiler-filter=assume-verified");
     }
@@ -226,11 +214,6 @@
       argv.push_back("--host");
     }
 
-    argv.push_back("--boot-image=" + image_location);
-
-    std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
-    argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
-
     argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
 
     // We must set --android-root.
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 844a728..6ffcef1 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -442,6 +442,9 @@
   MemMap::Init();
 
   RuntimeOptions options;
+  options.emplace_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()), nullptr);
+  options.emplace_back(
+      GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()), nullptr);
   std::string image("-Ximage:");
   image.append(helper.image_locations[0].GetFilename());
   options.push_back(std::make_pair(image.c_str(), static_cast<void*>(nullptr)));
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index b9116f0..f6fd1fb 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -46,6 +46,10 @@
     if (assume_profile_changed) {
       argv_str.push_back("--assume-profile-changed");
     }
+    argv_str.push_back("--runtime-arg");
+    argv_str.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
+    argv_str.push_back("--runtime-arg");
+    argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
     argv_str.push_back("--image=" + GetImageLocation());
     argv_str.push_back("--android-data=" + android_data_);
 
diff --git a/imgdiag/imgdiag_test.cc b/imgdiag/imgdiag_test.cc
index 73df2a2..739d9b8 100644
--- a/imgdiag/imgdiag_test.cc
+++ b/imgdiag/imgdiag_test.cc
@@ -34,12 +34,8 @@
 
 namespace art {
 
-static const char* kImgDiagDiffPid = "--image-diff-pid";
-static const char* kImgDiagBootImage = "--boot-image";
 static const char* kImgDiagBinaryName = "imgdiag";
 
-static const char* kImgDiagZygoteDiffPid = "--zygote-diff-pid";
-
 // from kernel <include/linux/threads.h>
 #define PID_MAX_LIMIT (4*1024*1024)  // Upper bound. Most kernel configs will have smaller max pid.
 
@@ -93,25 +89,15 @@
     EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
 
     // Run imgdiag --image-diff-pid=$image_diff_pid and wait until it's done with a 0 exit code.
-    std::string diff_pid_args;
-    std::string zygote_diff_pid_args;
-    {
-      std::stringstream diff_pid_args_ss;
-      diff_pid_args_ss << kImgDiagDiffPid << "=" << image_diff_pid;
-      diff_pid_args = diff_pid_args_ss.str();
-    }
-    {
-      std::stringstream zygote_pid_args_ss;
-      zygote_pid_args_ss << kImgDiagZygoteDiffPid << "=" << image_diff_pid;
-      zygote_diff_pid_args = zygote_pid_args_ss.str();
-    }
-    std::string boot_image_args = std::string(kImgDiagBootImage) + "=" + boot_image;
-
     std::vector<std::string> exec_argv = {
         file_path,
-        diff_pid_args,
-        zygote_diff_pid_args,
-        boot_image_args
+        "--image-diff-pid=" + std::to_string(image_diff_pid),
+        "--zygote-diff-pid=" + std::to_string(image_diff_pid),
+        "--runtime-arg",
+        GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()),
+        "--runtime-arg",
+        GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()),
+        "--boot-image=" + boot_image
     };
 
     return ::art::Exec(exec_argv, error_msg);
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index 5a0b425..278203d 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -24,6 +24,7 @@
 #include "nativehelper/scoped_local_ref.h"
 
 #include "android-base/stringprintf.h"
+#include "android-base/strings.h"
 #include "android-base/unique_fd.h"
 #include <unicode/uvernum.h>
 
@@ -328,9 +329,48 @@
 }
 
 std::vector<std::string> CommonArtTestImpl::GetLibCoreDexFileNames() {
-  return std::vector<std::string>({GetDexFileName("core-oj", IsHost()),
-                                   GetDexFileName("core-libart", IsHost()),
-                                   GetDexFileName("core-simple", IsHost())});
+  // Note: This must match the TEST_CORE_JARS in Android.common_path.mk
+  // because that's what we use for compiling the core.art image.
+  static const char* const kLibcoreModules[] = {
+      "core-oj",
+      "core-libart",
+      "core-simple",
+      "conscrypt",
+      "okhttp",
+      "bouncycastle",
+  };
+
+  std::vector<std::string> result;
+  result.reserve(arraysize(kLibcoreModules));
+  for (const char* module : kLibcoreModules) {
+    result.push_back(GetDexFileName(module, IsHost()));
+  }
+  return result;
+}
+
+std::vector<std::string> CommonArtTestImpl::GetLibCoreDexLocations() {
+  std::vector<std::string> result = GetLibCoreDexFileNames();
+  if (IsHost()) {
+    // Strip the ANDROID_BUILD_TOP directory including the directory separator '/'.
+    const char* host_dir = getenv("ANDROID_BUILD_TOP");
+    CHECK(host_dir != nullptr);
+    std::string prefix = host_dir;
+    CHECK(!prefix.empty());
+    if (prefix.back() != '/') {
+      prefix += '/';
+    }
+    for (std::string& location : result) {
+      CHECK_GT(location.size(), prefix.size());
+      CHECK_EQ(location.compare(0u, prefix.size(), prefix), 0);
+      location.erase(0u, prefix.size());
+    }
+  }
+  return result;
+}
+
+std::string CommonArtTestImpl::GetClassPathOption(const char* option,
+                                                  const std::vector<std::string>& class_path) {
+  return option + android::base::Join(class_path, ':');
 }
 
 std::string CommonArtTestImpl::GetTestAndroidRoot() {
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index 0f4800d..3e2340f 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -99,6 +99,12 @@
   // Gets the paths of the libcore dex files.
   static std::vector<std::string> GetLibCoreDexFileNames();
 
+  // Gets the locations of the libcore dex files.
+  static std::vector<std::string> GetLibCoreDexLocations();
+
+  static std::string GetClassPathOption(const char* option,
+                                        const std::vector<std::string>& class_path);
+
   // Returns bin directory which contains host's prebuild tools.
   static std::string GetAndroidHostToolsDir();
 
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index 4ee5101..728939f 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -122,6 +122,10 @@
         "-Xmx512m",
         "--runtime-arg",
         "-Xnorelocate",
+        "--runtime-arg",
+        GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()),
+        "--runtime-arg",
+        GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()),
         "--boot-image=" + GetCoreArtLocation(),
         "--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA)),
         "--dex-file=" + GetTestDexFileName(GetAppBaseName().c_str()),
@@ -181,6 +185,11 @@
         expected_prefixes.push_back("IMAGE BEGIN:");
         expected_prefixes.push_back("kDexCaches:");
       } else if (mode == kModeOatWithBootImage) {
+        exec_argv.push_back("--runtime-arg");
+        exec_argv.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
+        exec_argv.push_back("--runtime-arg");
+        exec_argv.push_back(
+            GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
         exec_argv.push_back("--boot-image=" + GetCoreArtLocation());
         exec_argv.push_back("--instruction-set=" + std::string(
             GetInstructionSetString(kRuntimeISA)));
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index 2131120..051db4c 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -91,7 +91,8 @@
         self->GetThreadName(name);
         if (name != "JDWP" &&
             name != "Signal Catcher" &&
-            !android::base::StartsWith(name, "Jit thread pool")) {
+            !android::base::StartsWith(name, "Jit thread pool") &&
+            !android::base::StartsWith(name, "Runtime worker thread")) {
           LOG(FATAL) << "Unexpected thread before start: " << name << " id: "
                      << self->GetThreadId();
         }
diff --git a/runtime/arch/arm/instruction_set_features_arm.cc b/runtime/arch/arm/instruction_set_features_arm.cc
index e97d2cb..58ae394 100644
--- a/runtime/arch/arm/instruction_set_features_arm.cc
+++ b/runtime/arch/arm/instruction_set_features_arm.cc
@@ -54,7 +54,8 @@
       "cortex-a76",
       "exynos-m1",
       "denver",
-      "kryo"
+      "kryo",
+      "kryo385",
   };
   bool has_armv8a = FindVariantInArray(arm_variants_with_armv8a,
                                        arraysize(arm_variants_with_armv8a),
diff --git a/runtime/arch/arm64/instruction_set_features_arm64.cc b/runtime/arch/arm64/instruction_set_features_arm64.cc
index 7796ca7..963c207 100644
--- a/runtime/arch/arm64/instruction_set_features_arm64.cc
+++ b/runtime/arch/arm64/instruction_set_features_arm64.cc
@@ -57,10 +57,6 @@
   static const char* arm64_variants_with_crc[] = {
       "default",
       "generic",
-      "kryo",
-      "exynos-m1",
-      "exynos-m2",
-      "exynos-m3",
       "cortex-a35",
       "cortex-a53",
       "cortex-a53.a57",
@@ -71,18 +67,25 @@
       "cortex-a55",
       "cortex-a75",
       "cortex-a76",
+      "exynos-m1",
+      "exynos-m2",
+      "exynos-m3",
+      "kryo",
+      "kryo385",
   };
 
   static const char* arm64_variants_with_lse[] = {
       "cortex-a55",
       "cortex-a75",
       "cortex-a76",
+      "kryo385",
   };
 
   static const char* arm64_variants_with_fp16[] = {
       "cortex-a55",
       "cortex-a75",
       "cortex-a76",
+      "kryo385",
   };
 
   static const char* arm64_variants_with_dotprod[] = {
@@ -124,7 +127,8 @@
         "exynos-m2",
         "exynos-m3",
         "denver64",
-        "kryo"
+        "kryo",
+        "kryo385",
     };
     if (!FindVariantInArray(arm64_known_variants, arraysize(arm64_known_variants), variant)) {
       std::ostringstream os;
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 0300fa1..a101976 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -44,6 +44,7 @@
 #include "dex/dex_file_loader.h"
 #include "dex/primitive.h"
 #include "gc/heap.h"
+#include "gc/space/image_space.h"
 #include "gc_root-inl.h"
 #include "gtest/gtest.h"
 #include "handle_scope-inl.h"
@@ -111,15 +112,14 @@
   std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
   std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
 
-
   RuntimeOptions options;
-  std::string boot_class_path_string = "-Xbootclasspath";
-  for (const std::string &core_dex_file_name : GetLibCoreDexFileNames()) {
-    boot_class_path_string += ":";
-    boot_class_path_string += core_dex_file_name;
-  }
+  std::string boot_class_path_string =
+      GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames());
+  std::string boot_class_path_locations_string =
+      GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations());
 
   options.push_back(std::make_pair(boot_class_path_string, nullptr));
+  options.push_back(std::make_pair(boot_class_path_locations_string, nullptr));
   options.push_back(std::make_pair("-Xcheck:jni", nullptr));
   options.push_back(std::make_pair(min_heap_string, nullptr));
   options.push_back(std::make_pair(max_heap_string, nullptr));
@@ -386,6 +386,38 @@
   }
 }
 
+bool CommonRuntimeTestImpl::StartDex2OatCommandLine(/*out*/std::vector<std::string>* argv,
+                                                    /*out*/std::string* error_msg) {
+  DCHECK(argv != nullptr);
+  DCHECK(argv->empty());
+
+  Runtime* runtime = Runtime::Current();
+  const std::vector<gc::space::ImageSpace*>& image_spaces =
+      runtime->GetHeap()->GetBootImageSpaces();
+  if (image_spaces.empty()) {
+    *error_msg = "No image location found for Dex2Oat.";
+    return false;
+  }
+  std::string image_location = image_spaces[0]->GetImageLocation();
+
+  argv->push_back(runtime->GetCompilerExecutable());
+  if (runtime->IsJavaDebuggable()) {
+    argv->push_back("--debuggable");
+  }
+  runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(argv);
+
+  argv->push_back("--runtime-arg");
+  argv->push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
+  argv->push_back("--runtime-arg");
+  argv->push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
+
+  argv->push_back("--boot-image=" + image_location);
+
+  std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
+  argv->insert(argv->end(), compiler_options.begin(), compiler_options.end());
+  return true;
+}
+
 CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
   vm_->SetCheckJniAbortHook(Hook, &actual_);
 }
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 0fee797..319c7c7 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -97,6 +97,9 @@
     return true;
   }
 
+  static bool StartDex2OatCommandLine(/*out*/std::vector<std::string>* argv,
+                                      /*out*/std::string* error_msg);
+
  protected:
   // Allow subclases such as CommonCompilerTest to add extra options.
   virtual void SetUpRuntimeOptions(RuntimeOptions* options ATTRIBUTE_UNUSED) {}
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index f52a0f9..b46c933 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -46,26 +46,13 @@
   ReserveImageSpace();
 }
 
-static std::string ImageLocation() {
-  Runtime* runtime = Runtime::Current();
-  const std::vector<gc::space::ImageSpace*>& image_spaces =
-      runtime->GetHeap()->GetBootImageSpaces();
-  if (image_spaces.empty()) {
-    return "";
-  }
-  return image_spaces[0]->GetImageLocation();
-}
-
 bool DexoptTest::Dex2Oat(const std::vector<std::string>& args, std::string* error_msg) {
-  Runtime* runtime = Runtime::Current();
-
   std::vector<std::string> argv;
-  argv.push_back(runtime->GetCompilerExecutable());
-  if (runtime->IsJavaDebuggable()) {
-    argv.push_back("--debuggable");
+  if (!CommonRuntimeTest::StartDex2OatCommandLine(&argv, error_msg)) {
+    return false;
   }
-  runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
 
+  Runtime* runtime = Runtime::Current();
   if (runtime->GetHiddenApiEnforcementPolicy() != hiddenapi::EnforcementPolicy::kDisabled) {
     argv.push_back("--runtime-arg");
     argv.push_back("-Xhidden-api-checks");
@@ -75,11 +62,6 @@
     argv.push_back("--host");
   }
 
-  argv.push_back("--boot-image=" + ImageLocation());
-
-  std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
-  argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
-
   argv.insert(argv.end(), args.begin(), args.end());
 
   std::string command_line(android::base::Join(argv, ' '));
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 8477c9d..46ff7dc 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -90,6 +90,7 @@
   Thread* self = Thread::Current();
   uint64_t start_time = NanoTime();
   uint64_t thread_cpu_start_time = ThreadCpuNanoTime();
+  GetHeap()->CalculateWeightedAllocatedBytes();
   Iteration* current_iteration = GetCurrentIteration();
   current_iteration->Reset(gc_cause, clear_soft_references);
   // Note transaction mode is single-threaded and there's no asynchronous GC and this flag doesn't
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index f767360..86135c1 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -210,6 +210,9 @@
       low_memory_mode_(low_memory_mode),
       long_pause_log_threshold_(long_pause_log_threshold),
       long_gc_log_threshold_(long_gc_log_threshold),
+      process_cpu_start_time_ns_(ProcessCpuNanoTime()),
+      last_process_cpu_time_ns_(process_cpu_start_time_ns_),
+      weighted_allocated_bytes_(0u),
       ignore_max_footprint_(ignore_max_footprint),
       zygote_creation_lock_("zygote creation lock", kZygoteCreationLock),
       zygote_space_(nullptr),
@@ -1062,6 +1065,14 @@
   }
 }
 
+void Heap::CalculateWeightedAllocatedBytes() {
+  uint64_t current_process_cpu_time = ProcessCpuNanoTime();
+  uint64_t bytes_allocated = GetBytesAllocated();
+  uint64_t weight = current_process_cpu_time - last_process_cpu_time_ns_;
+  weighted_allocated_bytes_ += weight * bytes_allocated;
+  last_process_cpu_time_ns_ = current_process_cpu_time;
+}
+
 uint64_t Heap::GetTotalGcCpuTime() {
   uint64_t sum = 0;
   for (auto* collector : garbage_collectors_) {
@@ -1139,6 +1150,11 @@
   for (auto* collector : garbage_collectors_) {
     collector->ResetMeasurements();
   }
+
+  process_cpu_start_time_ns_ = ProcessCpuNanoTime();
+  last_process_cpu_time_ns_ = process_cpu_start_time_ns_;
+  weighted_allocated_bytes_ = 0u;
+
   total_bytes_freed_ever_ = 0;
   total_objects_freed_ever_ = 0;
   total_wait_time_ = 0;
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index a43f315..411a446 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -395,8 +395,17 @@
     REQUIRES(!Locks::heap_bitmap_lock_)
     REQUIRES(Locks::mutator_lock_);
 
+  uint64_t GetWeightedAllocatedBytes() const {
+    return weighted_allocated_bytes_;
+  }
+
+  void CalculateWeightedAllocatedBytes();
   uint64_t GetTotalGcCpuTime();
 
+  uint64_t GetProcessCpuStartTime() const {
+    return process_cpu_start_time_ns_;
+  }
+
   // Set target ideal heap utilization ratio, implements
   // dalvik.system.VMRuntime.setTargetHeapUtilization.
   void SetTargetHeapUtilization(float target);
@@ -1161,6 +1170,15 @@
   // If we get a GC longer than long GC log threshold, then we print out the GC after it finishes.
   const size_t long_gc_log_threshold_;
 
+  // Starting time of the new process; meant to be used for measuring total process CPU time.
+  uint64_t process_cpu_start_time_ns_;
+
+  // Last time GC started; meant to be used to measure the duration between two GCs.
+  uint64_t last_process_cpu_time_ns_;
+
+  // allocated_bytes * (current_process_cpu_time - last_process_cpu_time)
+  uint64_t weighted_allocated_bytes_;
+
   // If we ignore the max footprint it lets the heap grow until it hits the heap capacity, this is
   // useful for benchmarking since it reduces time spent in GC to a low %.
   const bool ignore_max_footprint_;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index c772bda..e494bd6 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -627,16 +627,36 @@
         return MemMap::Invalid();
       }
       memcpy(map.Begin(), &image_header, sizeof(ImageHeader));
+
       const uint64_t start = NanoTime();
+      ThreadPool* pool = Runtime::Current()->GetThreadPool();
+      Thread* const self = Thread::Current();
+      const size_t kMinBlocks = 2;
+      const bool use_parallel = pool != nullptr &&image_header.GetBlockCount() >= kMinBlocks;
       for (const ImageHeader::Block& block : image_header.GetBlocks(temp_map.Begin())) {
-        TimingLogger::ScopedTiming timing2("LZ4 decompress image", logger);
-        if (!block.Decompress(/*out_ptr=*/map.Begin(), /*in_ptr=*/temp_map.Begin(), error_msg)) {
-          if (error_msg != nullptr) {
-            *error_msg = "Failed to decompress image block " + *error_msg;
+        auto function = [&](Thread*) {
+          const uint64_t start2 = NanoTime();
+          ScopedTrace trace("LZ4 decompress block");
+          if (!block.Decompress(/*out_ptr=*/map.Begin(),
+                                /*in_ptr=*/temp_map.Begin(),
+                                error_msg)) {
+            if (error_msg != nullptr) {
+              *error_msg = "Failed to decompress image block " + *error_msg;
+            }
           }
-          return MemMap::Invalid();
+          VLOG(image) << "Decompress block " << block.GetDataSize() << " -> "
+                      << block.GetImageSize() << " in " << PrettyDuration(NanoTime() - start2);
+        };
+        if (use_parallel) {
+          pool->AddTask(self, new FunctionTask(std::move(function)));
+        } else {
+          function(self);
         }
       }
+      if (use_parallel) {
+        ScopedTrace trace("Waiting for workers");
+        pool->Wait(self, true, false);
+      }
       const uint64_t time = NanoTime() - start;
       // Add one 1 ns to prevent possible divide by 0.
       VLOG(image) << "Decompressing image took " << PrettyDuration(time) << " ("
diff --git a/runtime/image.h b/runtime/image.h
index 76fb3b7..9d98431 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -116,6 +116,14 @@
       return storage_mode_;
     }
 
+    uint32_t GetDataSize() const {
+      return data_size_;
+    }
+
+    uint32_t GetImageSize() const {
+      return image_size_;
+    }
+
    private:
     // Storage method for the image, the image may be compressed.
     StorageMode storage_mode_ = kDefaultStorageMode;
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 530371d..0f655b9 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -44,10 +44,6 @@
 #include "thread_list.h"
 #include "trace.h"
 
-#if defined(__linux__)
-#include <sys/prctl.h>
-#endif
-
 #include <sys/resource.h>
 
 namespace art {
@@ -59,37 +55,6 @@
 
 using android::base::StringPrintf;
 
-static void EnableDebugger() {
-#if defined(__linux__)
-  // To let a non-privileged gdbserver attach to this
-  // process, we must set our dumpable flag.
-  if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
-    PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid();
-  }
-
-  // Even if Yama is on a non-privileged native debugger should
-  // be able to attach to the debuggable app.
-  if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) == -1) {
-    // if Yama is off prctl(PR_SET_PTRACER) returns EINVAL - don't log in this
-    // case since it's expected behaviour.
-    if (errno != EINVAL) {
-      PLOG(ERROR) << "prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) failed for pid " << getpid();
-    }
-  }
-#endif
-  // We don't want core dumps, though, so set the soft limit on core dump size
-  // to 0 without changing the hard limit.
-  rlimit rl;
-  if (getrlimit(RLIMIT_CORE, &rl) == -1) {
-    PLOG(ERROR) << "getrlimit(RLIMIT_CORE) failed for pid " << getpid();
-  } else {
-    rl.rlim_cur = 0;
-    if (setrlimit(RLIMIT_CORE, &rl) == -1) {
-      PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();
-    }
-  }
-}
-
 class ClassSet {
  public:
   // The number of classes we reasonably expect to have to look at. Realistically the number is more
@@ -211,9 +176,6 @@
   }
 
   Dbg::SetJdwpAllowed((runtime_flags & DEBUG_ENABLE_JDWP) != 0);
-  if ((runtime_flags & DEBUG_ENABLE_JDWP) != 0) {
-    EnableDebugger();
-  }
   runtime_flags &= ~DEBUG_ENABLE_JDWP;
 
   const bool safe_mode = (runtime_flags & DEBUG_ENABLE_SAFEMODE) != 0;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index ab79b9e..84526f3 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -34,6 +34,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <limits>
+#include <thread>
 #include <vector>
 
 #include "android-base/strings.h"
@@ -278,7 +279,6 @@
       // Initially assume we perceive jank in case the process state is never updated.
       process_state_(kProcessStateJankPerceptible),
       zygote_no_threads_(false),
-      process_cpu_start_time_(ProcessCpuNanoTime()),
       verifier_logging_threshold_ms_(100) {
   static_assert(Runtime::kCalleeSaveSize ==
                     static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType), "Unexpected size");
@@ -322,20 +322,26 @@
   }
 
   if (dump_gc_performance_on_shutdown_) {
-    process_cpu_end_time_ = ProcessCpuNanoTime();
+    heap_->CalculateWeightedAllocatedBytes();
+    uint64_t process_cpu_end_time = ProcessCpuNanoTime();
     ScopedLogSeverity sls(LogSeverity::INFO);
     // This can't be called from the Heap destructor below because it
     // could call RosAlloc::InspectAll() which needs the thread_list
     // to be still alive.
     heap_->DumpGcPerformanceInfo(LOG_STREAM(INFO));
 
-    uint64_t process_cpu_time = process_cpu_end_time_ - process_cpu_start_time_;
+    uint64_t process_cpu_time = process_cpu_end_time - heap_->GetProcessCpuStartTime();
     uint64_t gc_cpu_time = heap_->GetTotalGcCpuTime();
     float ratio = static_cast<float>(gc_cpu_time) / process_cpu_time;
     LOG_STREAM(INFO) << "GC CPU time " << PrettyDuration(gc_cpu_time)
         << " out of process CPU time " << PrettyDuration(process_cpu_time)
         << " (" << ratio << ")"
         << "\n";
+    float weighted_allocated_bytes =
+      static_cast<float>(heap_->GetWeightedAllocatedBytes()) / process_cpu_time;
+    LOG_STREAM(INFO) << "Weighted bytes allocated over CPU time: "
+        << " (" <<  PrettySize(weighted_allocated_bytes)  << ")"
+        << "\n";
   }
 
   if (jit_ != nullptr) {
@@ -388,6 +394,11 @@
     jit_->DeleteThreadPool();
   }
 
+  // Thread pools must be deleted before the runtime shuts down to avoid hanging.
+  if (thread_pool_ != nullptr) {
+    thread_pool_.reset();
+  }
+
   // Make sure our internal threads are dead before we start tearing down things they're using.
   GetRuntimeCallbacks()->StopDebugger();
   delete signal_catcher_;
@@ -910,6 +921,15 @@
     jit_->CreateThreadPool();
   }
 
+  if (thread_pool_ == nullptr) {
+    constexpr size_t kStackSize = 64 * KB;
+    constexpr size_t kMaxRuntimeWorkers = 4u;
+    const size_t num_workers =
+        std::min(static_cast<size_t>(std::thread::hardware_concurrency()), kMaxRuntimeWorkers);
+    thread_pool_.reset(new ThreadPool("Runtime", num_workers, /*create_peers=*/false, kStackSize));
+    thread_pool_->StartWorkers(Thread::Current());
+  }
+
   // Create the thread pools.
   heap_->CreateThreadPool();
   // Reset the gc performance data at zygote fork so that the GCs
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 0ccc7b7..c74647e 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -99,6 +99,7 @@
 class StackOverflowHandler;
 class SuspensionHandler;
 class ThreadList;
+class ThreadPool;
 class Trace;
 struct TraceConfig;
 class Transaction;
@@ -789,6 +790,10 @@
     return verifier_logging_threshold_ms_;
   }
 
+  ThreadPool* GetThreadPool() {
+    return thread_pool_.get();
+  }
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -882,6 +887,9 @@
   // Shared linear alloc for now.
   std::unique_ptr<LinearAlloc> linear_alloc_;
 
+  // Thread pool
+  std::unique_ptr<ThreadPool> thread_pool_;
+
   // The number of spins that are done before thread suspension is used to forcibly inflate.
   size_t max_spins_before_thin_lock_inflation_;
   MonitorList* monitor_list_;
@@ -1101,9 +1109,6 @@
 
   MemMap protected_fault_page_;
 
-  uint64_t process_cpu_start_time_;
-  uint64_t process_cpu_end_time_;
-
   uint32_t verifier_logging_threshold_ms_;
 
   DISALLOW_COPY_AND_ASSIGN(Runtime);
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index 8723c99..0f96510 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -123,7 +123,10 @@
   tasks_.clear();
 }
 
-ThreadPool::ThreadPool(const char* name, size_t num_threads, bool create_peers)
+ThreadPool::ThreadPool(const char* name,
+                       size_t num_threads,
+                       bool create_peers,
+                       size_t worker_stack_size)
   : name_(name),
     task_queue_lock_("task queue lock"),
     task_queue_condition_("task queue condition", task_queue_lock_),
@@ -137,15 +140,13 @@
     creation_barier_(num_threads + 1),
     max_active_workers_(num_threads),
     create_peers_(create_peers) {
-  Thread* self = Thread::Current();
   while (GetThreadCount() < num_threads) {
     const std::string worker_name = StringPrintf("%s worker thread %zu", name_.c_str(),
                                                  GetThreadCount());
-    threads_.push_back(
-        new ThreadPoolWorker(this, worker_name, ThreadPoolWorker::kDefaultStackSize));
+    threads_.push_back(new ThreadPoolWorker(this, worker_name, worker_stack_size));
   }
   // Wait for all of the threads to attach.
-  creation_barier_.Wait(self);
+  creation_barier_.Wait(Thread::Current());
 }
 
 void ThreadPool::SetMaxActiveWorkers(size_t threads) {
diff --git a/runtime/thread_pool.h b/runtime/thread_pool.h
index 98a1193..fee009b 100644
--- a/runtime/thread_pool.h
+++ b/runtime/thread_pool.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_THREAD_POOL_H_
 
 #include <deque>
+#include <functional>
 #include <vector>
 
 #include "barrier.h"
@@ -48,6 +49,18 @@
   }
 };
 
+class FunctionTask : public SelfDeletingTask {
+ public:
+  explicit FunctionTask(std::function<void(Thread*)>&& func) : func_(std::move(func)) {}
+
+  void Run(Thread* self) override {
+    func_(self);
+  }
+
+ private:
+  std::function<void(Thread*)> func_;
+};
+
 class ThreadPoolWorker {
  public:
   static const size_t kDefaultStackSize = 1 * MB;
@@ -110,7 +123,10 @@
   // If create_peers is true, all worker threads will have a Java peer object. Note that if the
   // pool is asked to do work on the current thread (see Wait), a peer may not be available. Wait
   // will conservatively abort if create_peers and do_work are true.
-  ThreadPool(const char* name, size_t num_threads, bool create_peers = false);
+  ThreadPool(const char* name,
+             size_t num_threads,
+             bool create_peers = false,
+             size_t worker_stack_size = ThreadPoolWorker::kDefaultStackSize);
   virtual ~ThreadPool();
 
   // Wait for all tasks currently on queue to get completed. If the pool has been stopped, only
diff --git a/test/118-noimage-dex2oat/run b/test/118-noimage-dex2oat/run
index d68b0a0..d1b9725 100644
--- a/test/118-noimage-dex2oat/run
+++ b/test/118-noimage-dex2oat/run
@@ -31,39 +31,26 @@
   exit 1
 fi
 
-if [[ $@ == *--host* ]]; then
-    framework="${ANDROID_HOST_OUT}/framework"
-    bpath_suffix="-hostdex"
-else
-    framework="/system/framework"
-    bpath_suffix=""
-fi
-bpath="${framework}/core-libart${bpath_suffix}.jar"
-bpath="${bpath}:${framework}/conscrypt${bpath_suffix}.jar"
-bpath="${bpath}:${framework}/okhttp${bpath_suffix}.jar"
-bpath="${bpath}:${framework}/bouncycastle${bpath_suffix}.jar"
-bpath_arg="--runtime-option -Xbootclasspath:${bpath}"
-
 
 # Make sure we can run without an oat file.
 echo "Run -Xnoimage-dex2oat"
-${RUN} ${flags} ${bpath_arg} --runtime-option -Xnoimage-dex2oat
+${RUN} ${flags} --runtime-option -Xnoimage-dex2oat
 return_status1=$?
 
 # Make sure we cannot run without an oat file without fallback.
 echo "Run -Xnoimage-dex2oat -Xno-dex-file-fallback"
-${RUN} ${flags} ${bpath_arg} --runtime-option -Xnoimage-dex2oat \
+${RUN} ${flags} --runtime-option -Xnoimage-dex2oat \
   --runtime-option -Xno-dex-file-fallback
 return_status2=$?
 
 # Make sure we can run with the oat file.
 echo "Run -Ximage-dex2oat"
-${RUN} ${flags} ${bpath_arg} --runtime-option -Ximage-dex2oat
+${RUN} ${flags} --runtime-option -Ximage-dex2oat
 return_status3=$?
 
 # Make sure we can run with the default settings.
 echo "Run default"
-${RUN} ${flags} ${bpath_arg}
+${RUN} ${flags}
 return_status4=$?
 
 # Make sure we don't silently ignore an early failure.
diff --git a/test/924-threads/src/art/Test924.java b/test/924-threads/src/art/Test924.java
index e8e9781..e97c9c6 100644
--- a/test/924-threads/src/art/Test924.java
+++ b/test/924-threads/src/art/Test924.java
@@ -27,6 +27,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.time.Instant;
 
 public class Test924 {
   public static void run() throws Exception {
@@ -109,6 +110,7 @@
     final CountDownLatch cdl4 = new CountDownLatch(1);
     final CountDownLatch cdl5 = new CountDownLatch(1);
     final Holder h = new Holder();
+    final long ALMOST_INFINITE = 100000000;  // 1.1 days!
     final NativeWaiter w = new NativeWaiter();
     Runnable r = new Runnable() {
       @Override
@@ -121,7 +123,7 @@
 
           cdl2.countDown();
           synchronized(cdl2) {
-            cdl2.wait(1000);  // Wait a second.
+            cdl2.wait(ALMOST_INFINITE);
           }
 
           cdl3_1.await();
@@ -131,7 +133,9 @@
           }
 
           cdl4.countDown();
-          Thread.sleep(1000);
+          try {
+            Thread.sleep(ALMOST_INFINITE);
+          } catch (InterruptedException e) { }
 
           cdl5.countDown();
           while (!h.flag) {
@@ -152,18 +156,20 @@
 
     // Waiting.
     cdl1.await();
-    Thread.yield();
-    Thread.sleep(100);
-    printThreadState(t);
+    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
+    // up and continue
+    final int WAITING_INDEF = 0x191;
+    waitForState(t, WAITING_INDEF);
     synchronized(cdl1) {
       cdl1.notifyAll();
     }
 
     // Timed waiting.
     cdl2.await();
-    Thread.yield();
-    Thread.sleep(100);
-    printThreadState(t);
+    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
+    // up and continue
+    final int WAITING_TIMED = 0x1a1;
+    waitForState(t, WAITING_TIMED);
     synchronized(cdl2) {
       cdl2.notifyAll();
     }
@@ -185,14 +191,16 @@
 
     // Sleeping.
     cdl4.await();
-    Thread.yield();
-    Thread.sleep(100);
-    printThreadState(t);
+    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
+    // up and continue
+    final int WAITING_SLEEP = 0xe1;
+    waitForState(t, WAITING_SLEEP);
+    t.interrupt();
 
     // Running.
     cdl5.await();
     Thread.yield();
-    Thread.sleep(100);
+    Thread.sleep(1000);
     printThreadState(t);
     h.flag = true;
 
@@ -204,11 +212,26 @@
     // Dying.
     t.join();
     Thread.yield();
-    Thread.sleep(100);
+    Thread.sleep(1000);
 
     printThreadState(t);
   }
 
+  private static void waitForState(Thread t, int desired) throws Exception {
+    Thread.yield();
+    Thread.sleep(1000);
+    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
+    // up and continue
+    int state;
+    Instant deadline = Instant.now().plusSeconds(60 * 5);
+    while ((state = getThreadState(t)) != desired && deadline.isAfter(Instant.now())) {
+      Thread.yield();
+      Thread.sleep(100);
+      Thread.yield();
+    }
+    printThreadState(state);
+  }
+
   private static void doAllThreadsTests() {
     Thread[] threads = getAllThreads();
     List<Thread> threadList = new ArrayList<>(Arrays.asList(threads));
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 148aea4..5d07601 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -50,9 +50,9 @@
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/core-libart-testdex.jar
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/core-oj-testdex.jar
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/core-simple-testdex.jar
+ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/conscrypt-testdex.jar
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/okhttp-testdex.jar
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/bouncycastle-testdex.jar
-ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += $(TARGET_OUT_JAVA_LIBRARIES)/conscrypt-testdex.jar
 
 # All tests require the host executables. The tests also depend on the core images, but on
 # specific version depending on the compiler.
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index ac6002b..4e5152b 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -541,23 +541,38 @@
   exit
 fi
 
+bpath_modules="core-oj core-libart core-simple conscrypt okhttp bouncycastle"
+if [ "${HOST}" = "y" ]; then
+    framework="${ANDROID_HOST_OUT}/framework"
+    if [ "${ANDROID_HOST_OUT:0:${#ANDROID_BUILD_TOP}+1}" = "${ANDROID_BUILD_TOP}/" ]; then
+      framework_location="${ANDROID_HOST_OUT:${#ANDROID_BUILD_TOP}+1}/framework"
+    else
+      echo "error: ANDROID_BUILD_TOP/ is not a prefix of ANDROID_HOST_OUT"
+      echo "ANDROID_BUILD_TOP=${ANDROID_BUILD_TOP}"
+      echo "ANDROID_HOST_OUT=${ANDROID_HOST_OUT}"
+      exit
+    fi
+    bpath_suffix="-hostdex"
+else
+    framework="${ANDROID_ROOT}/framework"
+    framework_location="${ANDROID_ROOT}/framework"
+    bpath_suffix="-testdex"
+fi
+bpath=""
+bpath_locations=""
+bpath_separator=""
+for bpath_module in ${bpath_modules}; do
+  bpath+="${bpath_separator}${framework}/${bpath_module}${bpath_suffix}.jar"
+  bpath_locations+="${bpath_separator}${framework_location}/${bpath_module}${bpath_suffix}.jar"
+  bpath_separator=":"
+done
+# Pass down the bootclasspath
+FLAGS="${FLAGS} -Xbootclasspath:${bpath}"
+FLAGS="${FLAGS} -Xbootclasspath-locations:${bpath_locations}"
+COMPILE_FLAGS="${COMPILE_FLAGS} --runtime-arg -Xbootclasspath:${bpath}"
+COMPILE_FLAGS="${COMPILE_FLAGS} --runtime-arg -Xbootclasspath-locations:${bpath_locations}"
 
 if [ "$HAVE_IMAGE" = "n" ]; then
-    if [ "${HOST}" = "y" ]; then
-        framework="${ANDROID_HOST_OUT}/framework"
-        bpath_suffix="-hostdex"
-    else
-        framework="${ANDROID_ROOT}/framework"
-        bpath_suffix="-testdex"
-    fi
-    bpath="${framework}/core-libart${bpath_suffix}.jar"
-    bpath="${bpath}:${framework}/core-oj${bpath_suffix}.jar"
-    bpath="${bpath}:${framework}/core-simple${bpath_suffix}.jar"
-    bpath="${bpath}:${framework}/conscrypt${bpath_suffix}.jar"
-    bpath="${bpath}:${framework}/okhttp${bpath_suffix}.jar"
-    bpath="${bpath}:${framework}/bouncycastle${bpath_suffix}.jar"
-    # Pass down the bootclasspath
-    FLAGS="${FLAGS} -Xbootclasspath:${bpath}"
     # Disable image dex2oat - this will forbid the runtime to patch or compile an image.
     FLAGS="${FLAGS} -Xnoimage-dex2oat"
 
diff --git a/tools/bootjars.sh b/tools/bootjars.sh
index dca209d..ad6ee6b 100755
--- a/tools/bootjars.sh
+++ b/tools/bootjars.sh
@@ -54,7 +54,7 @@
 
 if [[ $mode == target ]]; then
   if [[ $core_jars_only == y ]]; then
-    selected_env_var=TARGET_CORE_JARS
+    selected_env_var=TARGET_TEST_CORE_JARS
   else
     selected_env_var=PRODUCT_BOOT_JARS
   fi
@@ -64,11 +64,31 @@
     echo "Error: --host does not have non-core boot jars, --core required" >&2
     exit 1
   fi
-  selected_env_var=HOST_CORE_JARS
+  selected_env_var=HOST_TEST_CORE_JARS
   intermediates_env_var=HOST_OUT_COMMON_INTERMEDIATES
 fi
 
-boot_jars_list=$(get_build_var "$selected_env_var")
+if [[ $core_jars_only == y ]]; then
+  # FIXME: The soong invocation we're using for getting the variables does not give us anything
+  # defined in Android.common_path.mk, otherwise we would just use HOST-/TARGET_TEST_CORE_JARS.
+
+  # The core_jars_list must match the TEST_CORE_JARS variable in the Android.common_path.mk .
+  core_jars_list="core-oj core-libart core-simple conscrypt okhttp bouncycastle"
+  core_jars_suffix=
+  if [[ $mode == target ]]; then
+    core_jars_suffix=-testdex
+  elif [[ $mode == host ]]; then
+    core_jars_suffix=-hostdex
+  fi
+  boot_jars_list=""
+  boot_separator=""
+  for boot_module in ${core_jars_list}; do
+    boot_jars_list+="${boot_separator}${boot_module}${core_jars_suffix}"
+    boot_separator=" "
+  done
+else
+  boot_jars_list=$(get_build_var "$selected_env_var")
+fi
 
 # Print only the list of boot jars.
 if [[ $print_file_path == n ]]; then
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index a5fa332..f97dd4f 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -157,7 +157,6 @@
 {
   description: "Missing resource in classpath",
   result: EXEC_FAILED,
-  modes: [device],
   names: ["libcore.java.util.prefs.OldAbstractPreferencesTest#testClear",
           "libcore.java.util.prefs.OldAbstractPreferencesTest#testExportNode",
           "libcore.java.util.prefs.OldAbstractPreferencesTest#testExportSubtree",
@@ -187,7 +186,8 @@
           "org.apache.harmony.tests.java.util.prefs.AbstractPreferencesTest#testExportSubtree",
           "org.apache.harmony.tests.java.util.prefs.AbstractPreferencesTest#testFlush",
           "org.apache.harmony.tests.java.util.prefs.AbstractPreferencesTest#testSync",
-          "org.apache.harmony.tests.java.util.prefs.FilePreferencesImplTest#testPutGet"]
+          "org.apache.harmony.tests.java.util.prefs.FilePreferencesImplTest#testPutGet"],
+  bug: 120526172
 },
 {
   description: "Only work with --mode=activity",