Merge "Add support for ANDROID_RUNTIME_ROOT variable"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index e610bb1..9a5e26b 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -422,6 +422,8 @@
   ART_GTEST_TARGET_ANDROID_ROOT := $(ART_TEST_ANDROID_ROOT)
 endif
 
+ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := '/apex/com.android.runtime'
+
 # Define a make rule for a target device gtest.
 # $(1): gtest name - the name of the test we're building such as leb128_test.
 # $(2): path relative to $OUT to the test binary
@@ -472,7 +474,9 @@
 	$(hide) $(ADB) shell $$(PRIVATE_MAYBE_CHROOT_COMMAND) chmod 755 $$(PRIVATE_TARGET_EXE)
 	$(hide) $$(call ART_TEST_SKIP,$$@) && \
 	  ($(ADB) shell "$$(PRIVATE_MAYBE_CHROOT_COMMAND) env $(GCOV_ENV) LD_LIBRARY_PATH=$(4) \
-	       ANDROID_ROOT=$(ART_GTEST_TARGET_ANDROID_ROOT) $$(PRIVATE_TARGET_EXE) \
+	       ANDROID_ROOT=$(ART_GTEST_TARGET_ANDROID_ROOT) \
+	       ANDROID_RUNTIME_ROOT=$(ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT) \
+	       $$(PRIVATE_TARGET_EXE) \
 	     && touch $$(PRIVATE_GTEST_WITNESS)" \
 	   && ($(ADB) pull $$(PRIVATE_GTEST_WITNESS) /tmp/ && $$(call ART_TEST_PASSED,$$@)) \
 	   || $$(call ART_TEST_FAILED,$$@))
@@ -717,6 +721,7 @@
 ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST_RULES :=
 ART_GTEST_TARGET_ANDROID_ROOT :=
+ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT :=
 ART_GTEST_class_linker_test_DEX_DEPS :=
 ART_GTEST_class_table_test_DEX_DEPS :=
 ART_GTEST_compiler_driver_test_DEX_DEPS :=
diff --git a/compiler/utils/assembler_test_base.h b/compiler/utils/assembler_test_base.h
index 778a015..5fa0b3c 100644
--- a/compiler/utils/assembler_test_base.h
+++ b/compiler/utils/assembler_test_base.h
@@ -59,12 +59,12 @@
       disassembler_cmd_name_(disasm),
       disassembler_parameters_(disasm_params) {
     // Fake a runtime test for ScratchFile
-    CommonRuntimeTest::SetUpAndroidData(android_data_);
+    CommonRuntimeTest::SetUpAndroidDataDir(android_data_);
   }
 
   virtual ~AssemblerTestInfrastructure() {
     // We leave temporaries in case this failed so we can debug issues.
-    CommonRuntimeTest::TearDownAndroidData(android_data_, false);
+    CommonRuntimeTest::TearDownAndroidDataDir(android_data_, false);
     tmpnam_ = "";
   }
 
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index 987ceb6..5a0b425 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -110,49 +110,59 @@
   CHECK_EQ(0, unlink_result);
 }
 
-void CommonArtTestImpl::SetUpAndroidRoot() {
+void CommonArtTestImpl::SetUpAndroidRootEnvVars() {
   if (IsHost()) {
-    // $ANDROID_ROOT is set on the device, but not necessarily on the host.
-    // But it needs to be set so that icu4c can find its locale data.
-    const char* android_root_from_env = getenv("ANDROID_ROOT");
-    if (android_root_from_env == nullptr) {
-      // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
-      const char* android_host_out = getenv("ANDROID_HOST_OUT");
-      if (android_host_out != nullptr) {
-        setenv("ANDROID_ROOT", android_host_out, 1);
-      } else {
-        // Build it from ANDROID_BUILD_TOP or cwd
-        std::string root;
-        const char* android_build_top = getenv("ANDROID_BUILD_TOP");
-        if (android_build_top != nullptr) {
-          root += android_build_top;
-        } else {
-          // Not set by build server, so default to current directory
-          char* cwd = getcwd(nullptr, 0);
-          setenv("ANDROID_BUILD_TOP", cwd, 1);
-          root += cwd;
-          free(cwd);
-        }
+    // Make sure that ANDROID_BUILD_TOP is set. If not, set it from CWD.
+    const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
+    if (android_build_top_from_env == nullptr) {
+      // Not set by build server, so default to current directory.
+      char* cwd = getcwd(nullptr, 0);
+      setenv("ANDROID_BUILD_TOP", cwd, 1);
+      free(cwd);
+      android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
+    }
+
+    const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT");
+    if (android_host_out_from_env == nullptr) {
+      // Not set by build server, so default to the usual value of
+      // ANDROID_HOST_OUT.
+      std::string android_host_out = android_build_top_from_env;
 #if defined(__linux__)
-        root += "/out/host/linux-x86";
+      android_host_out += "/out/host/linux-x86";
 #elif defined(__APPLE__)
-        root += "/out/host/darwin-x86";
+      android_host_out += "/out/host/darwin-x86";
 #else
 #error unsupported OS
 #endif
-        setenv("ANDROID_ROOT", root.c_str(), 1);
-      }
+      setenv("ANDROID_HOST_OUT", android_host_out.c_str(), 1);
+      android_host_out_from_env = getenv("ANDROID_HOST_OUT");
     }
-    setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
 
-    // Not set by build server, so default
-    if (getenv("ANDROID_HOST_OUT") == nullptr) {
-      setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
+    // Environment variable ANDROID_ROOT is set on the device, but not
+    // necessarily on the host.
+    const char* android_root_from_env = getenv("ANDROID_ROOT");
+    if (android_root_from_env == nullptr) {
+      // Use ANDROID_HOST_OUT for ANDROID_ROOT.
+      setenv("ANDROID_ROOT", android_host_out_from_env, 1);
+      android_root_from_env = getenv("ANDROID_ROOT");
     }
+
+    // Environment variable ANDROID_RUNTIME_ROOT is set on the device, but not
+    // necessarily on the host. It needs to be set so that various libraries
+    // like icu4c can find their data files.
+    const char* android_runtime_root_from_env = getenv("ANDROID_RUNTIME_ROOT");
+    if (android_runtime_root_from_env == nullptr) {
+      // Use ${ANDROID_HOST_OUT}/com.android.runtime for ANDROID_RUNTIME_ROOT.
+      std::string android_runtime_root = android_host_out_from_env;
+      android_runtime_root += "/com.android.runtime";
+      setenv("ANDROID_RUNTIME_ROOT", android_runtime_root.c_str(), 1);
+    }
+
+    setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
   }
 }
 
-void CommonArtTestImpl::SetUpAndroidData(std::string& android_data) {
+void CommonArtTestImpl::SetUpAndroidDataDir(std::string& android_data) {
   // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
   if (IsHost()) {
     const char* tmpdir = getenv("TMPDIR");
@@ -172,15 +182,16 @@
 }
 
 void CommonArtTestImpl::SetUp() {
-  SetUpAndroidRoot();
-  SetUpAndroidData(android_data_);
+  SetUpAndroidRootEnvVars();
+  SetUpAndroidDataDir(android_data_);
   dalvik_cache_.append(android_data_.c_str());
   dalvik_cache_.append("/dalvik-cache");
   int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
   ASSERT_EQ(mkdir_result, 0);
 }
 
-void CommonArtTestImpl::TearDownAndroidData(const std::string& android_data, bool fail_on_error) {
+void CommonArtTestImpl::TearDownAndroidDataDir(const std::string& android_data,
+                                               bool fail_on_error) {
   if (fail_on_error) {
     ASSERT_EQ(rmdir(android_data.c_str()), 0);
   } else {
@@ -295,7 +306,7 @@
   ClearDirectory(dalvik_cache_.c_str());
   int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
   ASSERT_EQ(0, rmdir_cache_result);
-  TearDownAndroidData(android_data_, true);
+  TearDownAndroidDataDir(android_data_, true);
   dalvik_cache_.clear();
 }
 
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index 32a2628..0f4800d 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -85,13 +85,16 @@
   CommonArtTestImpl() = default;
   virtual ~CommonArtTestImpl() = default;
 
-  static void SetUpAndroidRoot();
+  // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT and ANDROID_RUNTIME_ROOT
+  // environment variables using sensible defaults if not already set.
+  static void SetUpAndroidRootEnvVars();
 
+  // Set up the ANDROID_DATA environment variable, creating the directory if required.
   // Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
   // non-derived class, be sure to also call the corresponding tear-down below.
-  static void SetUpAndroidData(std::string& android_data);
+  static void SetUpAndroidDataDir(std::string& android_data);
 
-  static void TearDownAndroidData(const std::string& android_data, bool fail_on_error);
+  static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
 
   // Gets the paths of the libcore dex files.
   static std::vector<std::string> GetLibCoreDexFileNames();
diff --git a/libartbase/base/unix_file/random_access_file_test.h b/libartbase/base/unix_file/random_access_file_test.h
index dbe6ca9..178f89d 100644
--- a/libartbase/base/unix_file/random_access_file_test.h
+++ b/libartbase/base/unix_file/random_access_file_test.h
@@ -35,11 +35,11 @@
   virtual RandomAccessFile* MakeTestFile() = 0;
 
   virtual void SetUp() {
-    art::CommonArtTest::SetUpAndroidData(android_data_);
+    art::CommonArtTest::SetUpAndroidDataDir(android_data_);
   }
 
   virtual void TearDown() {
-    art::CommonArtTest::TearDownAndroidData(android_data_, true);
+    art::CommonArtTest::TearDownAndroidDataDir(android_data_, true);
   }
 
   std::string GetTmpPath(const std::string& name) {
diff --git a/runtime/parsed_options_test.cc b/runtime/parsed_options_test.cc
index 9e5d9ab..705cc6c 100644
--- a/runtime/parsed_options_test.cc
+++ b/runtime/parsed_options_test.cc
@@ -26,7 +26,7 @@
 class ParsedOptionsTest : public ::testing::Test {
  public:
   static void SetUpTestCase() {
-    CommonRuntimeTest::SetUpAndroidRoot();
+    CommonRuntimeTest::SetUpAndroidRootEnvVars();
   }
 };
 
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 6488d24..ac6002b 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -9,6 +9,7 @@
 }
 
 ANDROID_ROOT="/system"
+ANDROID_RUNTIME_ROOT="/apex/com.android.runtime"
 ARCHITECTURES_32="(arm|x86|mips|none)"
 ARCHITECTURES_64="(arm64|x86_64|mips64|none)"
 ARCHITECTURES_PATTERN="${ARCHITECTURES_32}"
@@ -209,7 +210,8 @@
         shift
     elif [ "x$1" = "x--host" ]; then
         HOST="y"
-        ANDROID_ROOT="$ANDROID_HOST_OUT"
+        ANDROID_ROOT="${ANDROID_HOST_OUT}"
+        ANDROID_RUNTIME_ROOT="${ANDROID_HOST_OUT}/com.android.runtime"
         shift
     elif [ "x$1" = "x--bionic" ]; then
         BIONIC="y"
@@ -902,6 +904,7 @@
              export ANDROID_ADDITIONAL_PUBLIC_LIBRARIES=$PUBLIC_LIBS && \
              export DEX_LOCATION=$DEX_LOCATION && \
              export ANDROID_ROOT=$ANDROID_ROOT && \
+             export ANDROID_RUNTIME_ROOT=$ANDROID_RUNTIME_ROOT && \
              export ANDROID_LOG_TAGS=$ANDROID_LOG_TAGS && \
              rm -rf ${DEX_LOCATION}/dalvik-cache/ && \
              mkdir -p ${mkdir_locations} && \
@@ -946,6 +949,7 @@
 
     export ANDROID_DATA="$DEX_LOCATION"
     export ANDROID_ROOT="${ANDROID_ROOT}"
+    export ANDROID_RUNTIME_ROOT="${ANDROID_RUNTIME_ROOT}"
     export LD_LIBRARY_PATH="${ANDROID_ROOT}/${LIBRARY_DIRECTORY}:${ANDROID_ROOT}/${TEST_DIRECTORY}"
     export DYLD_LIBRARY_PATH="${ANDROID_ROOT}/${LIBRARY_DIRECTORY}:${ANDROID_ROOT}/${TEST_DIRECTORY}"
     export PATH="$PATH:${ANDROID_ROOT}/bin"
diff --git a/tools/art b/tools/art
index fbc7992..eeb7c68 100644
--- a/tools/art
+++ b/tools/art
@@ -261,6 +261,7 @@
   # Run dalvikvm.
   verbose_run ANDROID_DATA="$ANDROID_DATA"                  \
               ANDROID_ROOT="$ANDROID_ROOT"                  \
+              ANDROID_RUNTIME_ROOT="$ANDROID_RUNTIME_ROOT"  \
               LD_LIBRARY_PATH="$LD_LIBRARY_PATH"            \
               PATH="$ANDROID_ROOT/bin:$PATH"                \
               LD_USE_LOAD_BIAS=1                            \
@@ -386,6 +387,7 @@
 
 PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
 ANDROID_ROOT=$PROG_DIR/..
+ANDROID_RUNTIME_ROOT=$ANDROID_ROOT/com.android.runtime
 ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
 
 if [ ! -x "$ART_BINARY_PATH" ]; then
diff --git a/tools/common/common.py b/tools/common/common.py
index b728e8d..6206dfb 100755
--- a/tools/common/common.py
+++ b/tools/common/common.py
@@ -299,11 +299,13 @@
       os.mkdir(arch_cache_path)
     lib = 'lib64' if x64 else 'lib'
     android_root = GetEnvVariableOrError('ANDROID_HOST_OUT')
+    android_runtime_root = android_root + '/com.android.runtime'
     library_path = android_root + '/' + lib
     path = android_root + '/bin'
     self._shell_env = os.environ.copy()
     self._shell_env['ANDROID_DATA'] = self._env_path
     self._shell_env['ANDROID_ROOT'] = android_root
+    self._shell_env['ANDROID_RUNTIME_ROOT'] = android_runtime_root
     self._shell_env['LD_LIBRARY_PATH'] = library_path
     self._shell_env['DYLD_LIBRARY_PATH'] = library_path
     self._shell_env['PATH'] = (path + ':' + self._shell_env['PATH'])