Remove icu .dat file from Runtime module

Bug: 137009149
Bug: 130295968
Test: device boots
Test: m out/target/common/obj/JAVA_LIBRARIES/ahat-test-dump_intermediates/test-dump.hprof
Test: art/build/apex/runtests.sh fails due to bug 138103882
Test: art/tools/buildbot-build.sh
Test: m test-art-host-gtest
Change-Id: I0501fd6dd02dac3cf9780f5f1c0103e4b0475e1f
diff --git a/Android.mk b/Android.mk
index bdf81dc..3efffb0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -605,7 +605,7 @@
 
 # Also include:
 # - a copy of the ICU prebuilt .dat file in /system/etc/icu on target
-#   (see module `icu-data-art-test-runtime`); and
+#   (see module `icu-data-art-test-i18n`); and
 # so that it can be found even if the Runtime APEX is not available,
 # by setting the environment variable `ART_TEST_ANDROID_RUNTIME_ROOT`
 # to "/system" on device. This is a temporary change needed
@@ -638,7 +638,7 @@
                         $(TARGET_CORE_IMG_OUT_BASE).art \
                         $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art \
                         libc.bootstrap libdl.bootstrap libm.bootstrap \
-                        icu-data-art-test-runtime \
+                        icu-data-art-test-i18n \
                         tzdata-art-test-tzdata tzlookup.xml-art-test-tzdata \
                         tz_version-art-test-tzdata icu_overlay-art-test-tzdata \
                         standalone-apex-files
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f59de64..a3f9279 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -86,6 +86,10 @@
 # Runtime APEX in lieu of the Debug Runtime APEX for ART testing.
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex)
 
+# Remove the icu .dat file from /apex/com.android.runtime and the host equivalent.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex)
+$(call add-clean-step, rm -rf $(HOST_OUT)/com.android.runtime/etc/icu/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/icu)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index f793dee..9da8a5f 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -463,6 +463,11 @@
   ART_GTEST_TARGET_ANDROID_ROOT := $(ART_TEST_ANDROID_ROOT)
 endif
 
+ART_GTEST_TARGET_ANDROID_I18N_ROOT := '/apex/com.android.i18n'
+ifneq ($(ART_TEST_ANDROID_I18N_ROOT),)
+  ART_GTEST_TARGET_ANDROID_I18N_ROOT := $(ART_TEST_ANDROID_I18N_ROOT)
+endif
+
 ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := '/apex/com.android.runtime'
 ifneq ($(ART_TEST_ANDROID_RUNTIME_ROOT),)
   ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := $(ART_TEST_ANDROID_RUNTIME_ROOT)
@@ -522,6 +527,7 @@
 	$(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) \
+	       ANDROID_I18N_ROOT=$(ART_GTEST_TARGET_ANDROID_I18N_ROOT) \
 	       ANDROID_RUNTIME_ROOT=$(ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT) \
 	       ANDROID_TZDATA_ROOT=$(ART_GTEST_TARGET_ANDROID_TZDATA_ROOT) \
 	       $$(PRIVATE_TARGET_EXE) \
@@ -774,6 +780,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_I18N_ROOT :=
 ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT :=
 ART_GTEST_TARGET_ANDROID_TZDATA_ROOT :=
 ART_GTEST_class_linker_test_DEX_DEPS :=
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 299456b..d72ad8d 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -81,11 +81,6 @@
     "libopenjdkjvmtid",
 ]
 
-// Data files associated with bionic / managed core library APIs.
-art_runtime_data_file_prebuilts = [
-    "apex_icu.dat",
-]
-
 // Tools common to both device APEX and host APEX. Derived from art-tools in art/Android.mk.
 art_tools_common_binaries = [
     "dexdump",
@@ -240,10 +235,12 @@
         "art_preinstall_hook_system_server",
         "art_prepostinstall_utils",
     ],
-    prebuilts: art_runtime_data_file_prebuilts +
-        ["com.android.runtime.ld.config.txt"],
+    prebuilts: ["com.android.runtime.ld.config.txt"],
     key: "com.android.runtime.key",
-    required: ["art_apex_boot_integrity"],
+    required: [
+        "art_apex_boot_integrity",
+        "com.android.i18n",
+    ],
 }
 
 // Default values shared by (device) Debug and Testing Runtime APEXes.
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index e2e85f2..da3320d 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -173,6 +173,17 @@
       android_root_from_env = getenv("ANDROID_ROOT");
     }
 
+    // Environment variable ANDROID_I18N_ROOT is set on the device, but not
+    // necessarily on the host. It needs to be set so that various libraries
+    // like libcore / icu4j / icu4c can find their data files.
+    const char* android_i18n_root_from_env = getenv("ANDROID_I18N_ROOT");
+    if (android_i18n_root_from_env == nullptr) {
+      // Use ${ANDROID_I18N_OUT}/com.android.i18n for ANDROID_I18N_ROOT.
+      std::string android_i18n_root = android_host_out_from_env;
+      android_i18n_root += "/com.android.i18n";
+      setenv("ANDROID_I18N_ROOT", android_i18n_root.c_str(), 1);
+    }
+
     // 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 libcore / icu4j / icu4c can find their data files.
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index 09264a7..32f1ef5 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -80,8 +80,9 @@
   CommonArtTestImpl() = default;
   virtual ~CommonArtTestImpl() = default;
 
-  // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_RUNTIME_ROOT,
-  // and ANDROID_TZDATA_ROOT environment variables using sensible defaults if not already set.
+  // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_I18N_ROOT,
+  // ANDROID_RUNTIME_ROOT, and ANDROID_TZDATA_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.
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index a217770..b26395b 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -102,20 +102,25 @@
 
 TEST_F(FileUtilsTest, GetAndroidRuntimeRootSafe) {
   std::string error_msg;
+  std::string android_runtime_root;
+  std::string android_runtime_root_env;
 
-  // We don't expect null returns for most cases, so don't check and let std::string crash.
+  // TODO(b/130295968): Re-enable this part when the directory exists on host
+  if (kIsTargetBuild) {
+    // We don't expect null returns for most cases, so don't check and let std::string crash.
 
-  // CommonArtTest sets ANDROID_RUNTIME_ROOT, so expect this to be the same.
-  std::string android_runtime_root = GetAndroidRuntimeRootSafe(&error_msg);
-  std::string android_runtime_root_env = getenv("ANDROID_RUNTIME_ROOT");
-  EXPECT_EQ(android_runtime_root, android_runtime_root_env) << error_msg;
+    // CommonArtTest sets ANDROID_RUNTIME_ROOT, so expect this to be the same.
+    android_runtime_root = GetAndroidRuntimeRootSafe(&error_msg);
+    android_runtime_root_env = getenv("ANDROID_RUNTIME_ROOT");
+    EXPECT_EQ(android_runtime_root, android_runtime_root_env) << error_msg;
 
-  // Set ANDROID_RUNTIME_ROOT to something else (but the directory must exist). So use dirname.
-  UniqueCPtr<char> root_dup(strdup(android_runtime_root_env.c_str()));
-  char* dir = dirname(root_dup.get());
-  ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", dir, /* overwrite */ 1));
-  std::string android_runtime_root2 = GetAndroidRuntimeRootSafe(&error_msg);
-  EXPECT_STREQ(dir, android_runtime_root2.c_str()) << error_msg;
+    // Set ANDROID_RUNTIME_ROOT to something else (but the directory must exist). So use dirname.
+    UniqueCPtr<char> root_dup(strdup(android_runtime_root_env.c_str()));
+    char* dir = dirname(root_dup.get());
+    ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", dir, /* overwrite */ 1));
+    std::string android_runtime_root2 = GetAndroidRuntimeRootSafe(&error_msg);
+    EXPECT_STREQ(dir, android_runtime_root2.c_str()) << error_msg;
+  }
 
   // Set a bogus value for ANDROID_RUNTIME_ROOT. This should be an error.
   ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", "/this/is/obviously/bogus", /* overwrite */ 1));
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 0ba55a1..e7636d2 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -14,6 +14,7 @@
 }
 
 ANDROID_ROOT="/system"
+ANDROID_I18N_ROOT="/apex/com.android.i18n"
 ANDROID_RUNTIME_ROOT="/apex/com.android.runtime"
 ANDROID_TZDATA_ROOT="/apex/com.android.tzdata"
 ARCHITECTURES_32="(arm|x86|mips|none)"
@@ -232,6 +233,7 @@
     elif [ "x$1" = "x--host" ]; then
         HOST="y"
         ANDROID_ROOT="${ANDROID_HOST_OUT}"
+        ANDROID_I18N_ROOT="${ANDROID_HOST_OUT}/com.android.i18n"
         ANDROID_RUNTIME_ROOT="${ANDROID_HOST_OUT}/com.android.runtime"
         ANDROID_TZDATA_ROOT="${ANDROID_HOST_OUT}/com.android.tzdata"
         shift
@@ -305,6 +307,7 @@
         TIME_OUT="n"
         HOST="y"
         ANDROID_ROOT="${ANDROID_HOST_OUT}"
+        ANDROID_I18N_ROOT="${ANDROID_HOST_OUT}/com.android.i18n"
         ANDROID_RUNTIME_ROOT="${ANDROID_HOST_OUT}/com.android.runtime"
         ANDROID_TZDATA_ROOT="${ANDROID_HOST_OUT}/com.android.tzdata"
         shift
@@ -367,6 +370,10 @@
         shift
         ANDROID_ROOT="$1"
         shift
+    elif [ "x$1" = "x--android-i18n-root" ]; then
+        shift
+        ANDROID_I18N_ROOT="$1"
+        shift
     elif [ "x$1" = "x--android-runtime-root" ]; then
         shift
         ANDROID_RUNTIME_ROOT="$1"
@@ -1048,6 +1055,7 @@
              export ANDROID_ADDITIONAL_PUBLIC_LIBRARIES=$PUBLIC_LIBS && \
              export DEX_LOCATION=$DEX_LOCATION && \
              export ANDROID_ROOT=$ANDROID_ROOT && \
+             export ANDROID_I18N_ROOT=$ANDROID_I18N_ROOT && \
              export ANDROID_RUNTIME_ROOT=$ANDROID_RUNTIME_ROOT && \
              export ANDROID_TZDATA_ROOT=$ANDROID_TZDATA_ROOT && \
              export ANDROID_LOG_TAGS=$ANDROID_LOG_TAGS && \
@@ -1094,6 +1102,7 @@
 
     export ANDROID_DATA="$DEX_LOCATION"
     export ANDROID_ROOT="${ANDROID_ROOT}"
+    export ANDROID_I18N_ROOT="${ANDROID_I18N_ROOT}"
     export ANDROID_RUNTIME_ROOT="${ANDROID_RUNTIME_ROOT}"
     export ANDROID_TZDATA_ROOT="${ANDROID_TZDATA_ROOT}"
     if [ "$USE_ZIPAPEX" = "y" ] || [ "$USE_EXRACTED_ZIPAPEX" = "y" ]; then
@@ -1141,7 +1150,7 @@
     fi
 
     if [ "$DEV_MODE" = "y" ]; then
-      for var in ANDROID_PRINTF_LOG ANDROID_DATA ANDROID_ROOT ANDROID_TZDATA_ROOT ANDROID_RUNTIME_ROOT LD_LIBRARY_PATH DYLD_LIBRARY_PATH PATH LD_USE_LOAD_BIAS; do
+      for var in ANDROID_PRINTF_LOG ANDROID_DATA ANDROID_ROOT ANDROID_I18N_ROOT ANDROID_TZDATA_ROOT ANDROID_RUNTIME_ROOT LD_LIBRARY_PATH DYLD_LIBRARY_PATH PATH LD_USE_LOAD_BIAS; do
         echo EXPORT $var=${!var}
       done
       echo "$(declare -f linkdirs)"
diff --git a/test/run-test b/test/run-test
index 3e535eb..a75642b 100755
--- a/test/run-test
+++ b/test/run-test
@@ -806,6 +806,9 @@
         echo "    --never-clean         Keep the test files even if the test succeeds."
         echo "    --chroot [newroot]    Run with root directory set to newroot."
         echo "    --android-root [path] The path on target for the android root. (/system by default)."
+        echo "    --android-i18n-root [path]"
+        echo "                          The path on target for the i18n module root."
+        echo "                          (/apex/com.android.i18n by default)."
         echo "    --android-runtime-root [path]"
         echo "                          The path on target for the Android Runtime root."
         echo "                          (/apex/com.android.runtime by default)."
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index a8360cb..56d372d 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -90,6 +90,7 @@
 
 ART_TEST_CHROOT = _env.get('ART_TEST_CHROOT')
 ART_TEST_ANDROID_ROOT = _env.get('ART_TEST_ANDROID_ROOT')
+ART_TEST_ANDROID_I18N_ROOT = _env.get('ART_TEST_ANDROID_I18N_ROOT')
 ART_TEST_ANDROID_RUNTIME_ROOT = _env.get('ART_TEST_ANDROID_RUNTIME_ROOT')
 ART_TEST_ANDROID_TZDATA_ROOT = _env.get('ART_TEST_ANDROID_TZDATA_ROOT')
 
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 301b225..80c8933 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -371,12 +371,14 @@
         options_test += ' --jvm'
 
       # Honor ART_TEST_CHROOT, ART_TEST_ANDROID_ROOT, ART_TEST_ANDROID_RUNTIME_ROOT,
-      # and ART_TEST_ANDROID_TZDATA_ROOT but only for target tests.
+      # ART_TEST_ANDROID_I18N_ROOT, and ART_TEST_ANDROID_TZDATA_ROOT but only for target tests.
       if target == 'target':
         if env.ART_TEST_CHROOT:
           options_test += ' --chroot ' + env.ART_TEST_CHROOT
         if env.ART_TEST_ANDROID_ROOT:
           options_test += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
+        if env.ART_TEST_ANDROID_I18N_ROOT:
+            options_test += ' --android-i18n-root ' + env.ART_TEST_ANDROID_I18N_ROOT
         if env.ART_TEST_ANDROID_RUNTIME_ROOT:
           options_test += ' --android-runtime-root ' + env.ART_TEST_ANDROID_RUNTIME_ROOT
         if env.ART_TEST_ANDROID_TZDATA_ROOT:
diff --git a/tools/art b/tools/art
index 4898781..69609b0 100644
--- a/tools/art
+++ b/tools/art
@@ -199,6 +199,7 @@
     # (see run_art function)
     verbose_run ANDROID_DATA=$ANDROID_DATA                    \
           ANDROID_ROOT=$ANDROID_ROOT                          \
+          ANDROID_I18N_ROOT=$ANDROID_I18N_ROOT                \
           ANDROID_RUNTIME_ROOT=$ANDROID_RUNTIME_ROOT          \
           ANDROID_TZDATA_ROOT=$ANDROID_TZDATA_ROOT            \
           LD_LIBRARY_PATH=$LD_LIBRARY_PATH                    \
@@ -275,6 +276,7 @@
   # Run dalvikvm.
   verbose_run ANDROID_DATA="$ANDROID_DATA"                  \
               ANDROID_ROOT="$ANDROID_ROOT"                  \
+              ANDROID_I18N_ROOT=$ANDROID_I18N_ROOT          \
               ANDROID_RUNTIME_ROOT="$ANDROID_RUNTIME_ROOT"  \
               ANDROID_TZDATA_ROOT="$ANDROID_TZDATA_ROOT"    \
               LD_LIBRARY_PATH="$LD_LIBRARY_PATH"            \
@@ -403,6 +405,27 @@
 PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
 ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
 
+# If ANDROID_I18N_ROOT is not set, try to detect whether we are running on
+# target or host and set that environment variable to the usual default value.
+if [ -z "$ANDROID_I18N_ROOT" ]; then
+  # This script is used on host and target (device). However, the (expected)
+  # default value `ANDROID_I18N_ROOT` is not the same on host and target:
+  # - on host, `ANDROID_I18N_ROOT` is expected to be
+  #   "$ANDROID_ROOT/com.android.i18n";
+  # - on target, `ANDROID_I18N_ROOT` is expected to be
+  #   "/apex/com.android.i18n".
+  #
+  # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
+  # determine whether we are on target or host (this is brittle, but simple).
+  if [ -d "$ANDROID_ROOT/../apex" ]; then
+    # Target case.
+    ANDROID_I18N_ROOT="/apex/com.android.i18n"
+  else
+    # Host case.
+    ANDROID_I18N_ROOT="$ANDROID_ROOT/com.android.i18n"
+  fi
+fi
+
 # If ANDROID_RUNTIME_ROOT is not set, try to detect whether we are running on
 # target or host and set that environment variable to the usual default value.
 if [ -z "$ANDROID_RUNTIME_ROOT" ]; then
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 62fa47c..6cd3483 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -91,6 +91,8 @@
   # - from /system/bin/linker(64) to /apex/com.android.runtime/bin/linker(64); and
   # - from /system/lib(64)/$lib to /apex/com.android.runtime/lib(64)/$lib.
   make_command+=" linker libc.bootstrap libdl.bootstrap libm.bootstrap"
+  # Build the i18n APEX.
+  make_command+=" com.android.i18n"
   # Build the Time Zone Data APEX.
   make_command+=" com.android.tzdata"
   mode_suffix="-target"
diff --git a/tools/buildbot-sync.sh b/tools/buildbot-sync.sh
index 6fac2d0..8c83a9d 100755
--- a/tools/buildbot-sync.sh
+++ b/tools/buildbot-sync.sh
@@ -156,6 +156,14 @@
 adb shell cp -a "$ART_TEST_CHROOT/system/apex/com.android.runtime.testing" \
   "$ART_TEST_CHROOT/apex/com.android.runtime"
 
+echo -e "${green}Activating i18n APEX...${nc}"
+# Manually "activate" the flattened i18n APEX by syncing it to the
+# /apex directory in the chroot.
+#
+# TODO: Likewise, handle the case of build targets using non-flatted APEX packages.
+adb shell rm -rf "$ART_TEST_CHROOT/apex/com.android.i18n"
+adb shell cp -a "$ART_TEST_CHROOT/system/apex/com.android.i18n" "$ART_TEST_CHROOT/apex/"
+
 echo -e "${green}Activating Time Zone Data APEX...${nc}"
 # Manually "activate" the flattened Time Zone Data APEX by syncing it to the
 # /apex directory in the chroot.
diff --git a/tools/common/common.py b/tools/common/common.py
index 4171dfe..c80ebf5 100755
--- a/tools/common/common.py
+++ b/tools/common/common.py
@@ -299,6 +299,7 @@
       os.mkdir(arch_cache_path)
     lib = 'lib64' if x64 else 'lib'
     android_root = GetEnvVariableOrError('ANDROID_HOST_OUT')
+    android_i18n_root = android_root + '/com.android.i18n'
     android_runtime_root = android_root + '/com.android.runtime'
     android_tzdata_root = android_root + '/com.android.tzdata'
     library_path = android_root + '/' + lib
@@ -306,6 +307,7 @@
     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_I18N_ROOT'] = android_i18n_root
     self._shell_env['ANDROID_RUNTIME_ROOT'] = android_runtime_root
     self._shell_env['ANDROID_TZDATA_ROOT'] = android_tzdata_root
     self._shell_env['LD_LIBRARY_PATH'] = library_path
diff --git a/tools/run-gtests.sh b/tools/run-gtests.sh
index b8e592b..a1df7c3 100755
--- a/tools/run-gtests.sh
+++ b/tools/run-gtests.sh
@@ -23,6 +23,7 @@
 
 adb="${ADB:-adb}"
 
+android_i18n_root=/apex/com.android.i18n
 android_runtime_root=/apex/com.android.runtime
 android_tzdata_root=/apex/com.android.tzdata
 
@@ -35,7 +36,7 @@
 for t in $tests; do
   echo "$t"
   "$adb" shell chroot "$ART_TEST_CHROOT" \
-    env ANDROID_RUNTIME_ROOT="$android_runtime_root" ANDROID_TZDATA_ROOT="$android_tzdata_root" $t \
+    env ANDROID_I18N_ROOT="$android_i18n_root" ANDROID_RUNTIME_ROOT="$android_runtime_root" ANDROID_TZDATA_ROOT="$android_tzdata_root" $t \
     || failing_tests+=("$t")
 done