Revert^4 "Package dexpreopt artifacts for libcore jars in the ART apex."

This reverts commit 0f7c792f12905558836cc01f3406d6ba364cefd7.

Reason for revert: coverage build with EMMA_INSTRUMENT_FRAMEWORK=true
is fixed by inspecting the environment variable and not generating
boot image in case it is set.

This patch set adds precompiled dexpreopt files for the libcore part
of boot class path in the ART apex. The dexpreopt files are packaged
in javalib/$ARCH/ subdirectory and have names prefixed with 'boot'
to match the boot image on the system partition.

Test: m
Test: art/build/apex/runtests.sh

Bug: 144091989
Change-Id: I8378f42708a64339b0c9d70fd0d7804bc885859e
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 2556923..809b8fc 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -263,7 +263,7 @@
 // Release version of the ART APEX module (not containing debug
 // variants nor tools), included in user builds. Also used for
 // storage-constrained devices in userdebug and eng builds.
-apex {
+art_apex {
     name: "com.android.art.release",
     defaults: ["com.android.art-defaults"],
     certificate: ":com.android.art.certificate",
@@ -272,7 +272,7 @@
 // "Debug" version of the ART APEX module (containing both release and
 // debug variants, as well as additional tools), included in userdebug and
 // eng build.
-apex {
+art_apex {
     name: "com.android.art.debug",
     defaults: ["com.android.art-dev-defaults"],
     certificate: ":com.android.art.certificate",
@@ -305,7 +305,7 @@
 // "Testing" version of the ART APEX module (containing both release
 // and debug variants, additional tools, and ART gtests), for testing
 // purposes only.
-apex_test {
+art_apex_test {
     name: "com.android.art.testing",
     defaults: ["com.android.art-dev-defaults"],
     file_contexts: "com.android.art.debug",
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 27b5cf4..7d2c79a 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -267,6 +267,14 @@
       return False, '%s is a directory'
     return True, ''
 
+  def is_dir(self, path):
+    fs_object = self._provider.get(path)
+    if fs_object is None:
+      return False, 'Could not find %s'
+    if not fs_object.is_dir:
+      return False, '%s is not a directory'
+    return True, ''
+
   def check_file(self, path):
     ok, msg = self.is_file(path)
     if not ok:
@@ -294,27 +302,30 @@
       self.fail('%s is not a symlink', path)
     self._expected_file_globs.add(path)
 
-  def check_art_test_executable(self, filename):
-    # This is a simplistic implementation, as we declare victory as soon as the
-    # test binary is found for one of the supported (not built) architectures.
-    # Ideally we would propagate the built architectures from the build system
-    # to this script and require test binaries for all of them to be present.
-    # Note that this behavior is not specific to this method: there are other
-    # places in this script where we rely on this simplified strategy.
+  def arch_dirs_for_path(self, path):
+    # Look for target-specific subdirectories for the given directory path.
+    # This is needed because the list of build targets is not propagated
+    # to this script.
     #
-    # TODO: Implement the suggestion above (here and in other places in this
-    # script).
-    test_found = False
+    # TODO: Pass build target information to this script and fix all places
+    # where this function in used (or similar workarounds).
+    dirs = []
     for arch in ARCHS:
-      test_path = '%s/%s/%s' % (ART_TEST_DIR, arch, filename)
-      test_is_file, _ = self.is_file(test_path)
-      if test_is_file:
-        test_found = True
-        self._expected_file_globs.add(test_path)
-        if not self._provider.get(test_path).is_exec:
-          self.fail('%s is not executable', test_path)
-    if not test_found:
+      dir = '%s/%s' % (path, arch)
+      found, _ = self.is_dir(dir)
+      if found:
+        dirs.append(dir)
+    return dirs
+
+  def check_art_test_executable(self, filename):
+    dirs = self.arch_dirs_for_path(ART_TEST_DIR)
+    if not dirs:
       self.fail('ART test binary missing: %s', filename)
+    for dir in dirs:
+      test_path = '%s/%s' % (dir, filename)
+      self._expected_file_globs.add(test_path)
+      if not self._provider.get(test_path).is_exec:
+        self.fail('%s is not executable', test_path)
 
   def check_single_library(self, filename):
     lib_path = 'lib/%s' % filename
@@ -328,6 +339,14 @@
     if not lib_is_file and not lib64_is_file:
       self.fail('Library missing: %s', filename)
 
+  def check_dexpreopt(self, basename):
+    dirs = self.arch_dirs_for_path('javalib')
+    if not dirs:
+      self.fail('Could not find javalib directory for any arch.')
+    for dir in dirs:
+      for ext in ['art', 'oat', 'vdex']:
+        self.check_file('%s/%s.%s' % (dir, basename, ext))
+
   def check_java_library(self, basename):
     return self.check_file('javalib/%s.jar' % basename)
 
@@ -523,6 +542,17 @@
     self._checker.check_optional_native_library('libclang_rt.hwasan*')
     self._checker.check_optional_native_library('libclang_rt.ubsan*')
 
+    # Check dexpreopt files for libcore bootclasspath jars, unless this is a
+    # coverage build with EMMA_INSTRUMENT_FRAMEWORK=true (in that case we do not
+    # generate dexpreopt files because ART boot jars depend on framework and
+    # cannot be dexpreopted in isolation).
+    if 'EMMA_INSTRUMENT_FRAMEWORK' not in os.environ or not os.environ['EMMA_INSTRUMENT_FRAMEWORK']:
+      self._checker.check_dexpreopt('boot')
+      self._checker.check_dexpreopt('boot-apache-xml')
+      self._checker.check_dexpreopt('boot-bouncycastle')
+      self._checker.check_dexpreopt('boot-core-icu4j')
+      self._checker.check_dexpreopt('boot-core-libart')
+      self._checker.check_dexpreopt('boot-okhttp')
 
 class ReleaseTargetChecker:
   def __init__(self, checker):
diff --git a/build/art.go b/build/art.go
index 56eec54..4c1099b 100644
--- a/build/art.go
+++ b/build/art.go
@@ -312,6 +312,10 @@
 	android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
 	android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory)
 
+	// ART apex is special because it must include dexpreopt files for bootclasspath jars.
+	android.RegisterModuleType("art_apex", artApexBundleFactory)
+	android.RegisterModuleType("art_apex_test", artTestApexBundleFactory)
+
 	// TODO: This makes the module disable itself for host if HOST_PREFER_32_BIT is
 	// set. We need this because the multilib types of binaries listed in the apex
 	// rule must match the declared type. This is normally not difficult but HOST_PREFER_32_BIT
@@ -321,8 +325,16 @@
 	android.RegisterModuleType("art_apex_test_host", artHostTestApexBundleFactory)
 }
 
+func artApexBundleFactory() android.Module {
+	return apex.ApexBundleFactory(false /*testApex*/, true /*artApex*/)
+}
+
+func artTestApexBundleFactory() android.Module {
+	return apex.ApexBundleFactory(true /*testApex*/, true /*artApex*/)
+}
+
 func artHostTestApexBundleFactory() android.Module {
-	module := apex.ApexBundleFactory( /*testApex*/ true)
+	module := apex.ApexBundleFactory(true /*testApex*/, true /*artApex*/)
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
 		if envTrue(ctx, "HOST_PREFER_32_BIT") {
 			type props struct {