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

This reverts commit 0c63f76d90ed5b5dc4bc420fc51ffc383f8d87d9.

Reason: (some) build failures are fixed after reworking the patch.

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: m com.android.art deapexer \
    && find $ANDROID_BUILD_TOP -type f -name 'com.android.art.*.apex \
        | xargs deapexer | grep boot \
    Expect to find javalib/$ARCH/boot*.{art,oat,vdex} files.
Test: art/build/apex/runtests.sh

Bug: 143594594
Bug: 143593500

Change-Id: Ic09fab122f4e2acda1fa5d3c8addf1feaf9b6b8d
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..98a2963 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,13 @@
     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
+    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 {