Use the full boot image on U and above.

Bug: 280776428
Test: atest art_standalone_dexpreopt_tests
Test: atest odsign_e2e_tests_full
Change-Id: I0e1cc58204021ed7baaf98520c930f485fe93f53
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 84b797b..951599d 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -70,6 +70,7 @@
             },
             static_libs: [
                 "libcap",
+                "libmodules-utils-build",
                 // ZipArchive support, the order matters here to get all symbols.
                 "libziparchive",
             ],
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 899cea7..b3f42ee 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -64,6 +64,10 @@
 #include <linux/unistd.h>
 #endif
 
+#ifdef ART_TARGET_ANDROID
+#include "android-modules-utils/sdk_level.h"
+#endif
+
 namespace art {
 
 using android::base::StringPrintf;
@@ -459,23 +463,36 @@
     }
   }
 
-  // Boot image consists of three parts:
-  //  - the primary boot image (contains the Core Libraries)
-  //  - the boot image framework extension (contains framework libraries)
+  // Boot image consists of two parts:
+  //  - the primary boot image (contains the Core Libraries and framework libraries)
   //  - the boot image mainline extension (contains mainline framework libraries)
-  // Typically "/system/framework/boot.art!/apex/com.android.art/etc/boot-image.prof:
-  // /system/framework/boot-framework.art!/system/etc/boot-image.prof:
+  // Typically "/system/framework/boot.art
+  // !/apex/com.android.art/etc/boot-image.prof!/system/etc/boot-image.prof:
   // /system/framework/boot-framework-adservices.art".
 
-  std::string location = StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
+  std::string location = StringPrintf("%s/%s.art!%s/%s!%s/%s",
                                       GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
                                       kBootImageStem,
                                       kAndroidArtApexDefaultPath,
                                       kEtcBootImageProf,
                                       android_root.c_str(),
-                                      kBootImageStem,
-                                      android_root.c_str(),
                                       kEtcBootImageProf);
+
+#ifdef ART_TARGET_ANDROID
+  // Prior to U, there was a framework extension.
+  if (!android::modules::sdklevel::IsAtLeastU()) {
+    location = StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
+                            GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
+                            kBootImageStem,
+                            kAndroidArtApexDefaultPath,
+                            kEtcBootImageProf,
+                            android_root.c_str(),
+                            kBootImageStem,
+                            android_root.c_str(),
+                            kEtcBootImageProf);
+  }
+#endif
+
   if (!MaybeAppendBootImageMainlineExtension(android_root,
                                              /*deny_system_files=*/false,
                                              deny_art_apex_data_files,
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index a0b1a1c..6384685 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -923,7 +923,10 @@
     locations.push_back(GetPrimaryBootImage(/*on_system=*/false, /*minimal=*/false));
   } else {
     locations.push_back(GetPrimaryBootImage(/*on_system=*/true, /*minimal=*/false));
-    locations.push_back(GetSystemBootImageFrameworkExtension());
+    if (!IsAtLeastU()) {
+      // Prior to U, there was a framework extension.
+      locations.push_back(GetSystemBootImageFrameworkExtension());
+    }
   }
   if (include_mainline_extension) {
     if (BootImageMainlineExtensionExist(/*on_system=*/false, isa, &unused_error_msg)) {
@@ -978,9 +981,9 @@
   if (!ArtifactsExist(artifacts, /*check_art_file=*/true, error_msg, checked_artifacts)) {
     return false;
   }
-  // There is a split between the primary boot image and the extension on /system, so they need to
-  // be checked separately. This does not apply to the boot image on /data.
-  if (on_system) {
+  // Prior to U, there was a split between the primary boot image and the extension on /system, so
+  // they need to be checked separately. This does not apply to the boot image on /data.
+  if (on_system && !IsAtLeastU()) {
     std::string extension_path = GetSystemBootImageFrameworkExtensionPath(isa);
     OdrArtifacts extension_artifacts = OdrArtifacts::ForBootImage(extension_path);
     if (!ArtifactsExist(
diff --git a/odrefresh/odrefresh_test.cc b/odrefresh/odrefresh_test.cc
index 802c0f0..f4a3c4c 100644
--- a/odrefresh/odrefresh_test.cc
+++ b/odrefresh/odrefresh_test.cc
@@ -48,6 +48,7 @@
 namespace odrefresh {
 
 using ::android::base::Split;
+using ::android::modules::sdklevel::IsAtLeastU;
 using ::testing::_;
 using ::testing::AllOf;
 using ::testing::Contains;
@@ -613,7 +614,7 @@
                                         Contains("--compiler-filter=speed"))))
       .WillOnce(Return(0));
   // Only on U+ should we use the profile by default if available.
-  if (android::modules::sdklevel::IsAtLeastU()) {
+  if (IsAtLeastU()) {
     EXPECT_CALL(
         *mock_exec_utils_,
         DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
@@ -703,23 +704,43 @@
   auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
   auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
 
-  EXPECT_CALL(
-      *mock_exec_utils_,
-      DoExecAndReturnCode(AllOf(
-          Contains(Flag("--dex-file=", conscrypt_jar_)),
-          Contains(ListFlag(
-              "--boot-image=",
-              ElementsAre(framework_dir_ + "/boot.art", framework_dir_ + "/boot-framework.art"))),
-          Contains(ListFlag(
-              "-Xbootclasspathimagefds:",
-              ElementsAre(FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
-          Contains(ListFlag(
-              "-Xbootclasspathvdexfds:",
-              ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
-          Contains(ListFlag(
-              "-Xbootclasspathoatfds:",
-              ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
-      .WillOnce(Return(0));
+  if (IsAtLeastU()) {
+    EXPECT_CALL(
+        *mock_exec_utils_,
+        DoExecAndReturnCode(AllOf(
+            Contains(Flag("--dex-file=", conscrypt_jar_)),
+            Contains(ListFlag("--boot-image=", ElementsAre(framework_dir_ + "/boot.art"))),
+            Contains(ListFlag(
+                "-Xbootclasspathimagefds:",
+                ElementsAre(
+                    FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
+            Contains(ListFlag(
+                "-Xbootclasspathvdexfds:",
+                ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
+            Contains(ListFlag(
+                "-Xbootclasspathoatfds:",
+                ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
+        .WillOnce(Return(0));
+  } else {
+    EXPECT_CALL(
+        *mock_exec_utils_,
+        DoExecAndReturnCode(AllOf(
+            Contains(Flag("--dex-file=", conscrypt_jar_)),
+            Contains(ListFlag(
+                "--boot-image=",
+                ElementsAre(framework_dir_ + "/boot.art", framework_dir_ + "/boot-framework.art"))),
+            Contains(ListFlag(
+                "-Xbootclasspathimagefds:",
+                ElementsAre(
+                    FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
+            Contains(ListFlag(
+                "-Xbootclasspathvdexfds:",
+                ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
+            Contains(ListFlag(
+                "-Xbootclasspathoatfds:",
+                ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
+        .WillOnce(Return(0));
+  }
 
   EXPECT_EQ(odrefresh_->Compile(
                 *metrics_,
@@ -784,29 +805,55 @@
   auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
   auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
 
-  EXPECT_CALL(*mock_exec_utils_,
-              DoExecAndReturnCode(AllOf(
-                  Contains(ListFlag("--boot-image=",
-                                    ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
-                                                framework_dir_ + "/boot-framework.art",
-                                                dalvik_cache_dir_ + "/boot-conscrypt.art"))),
-                  Contains(ListFlag("-Xbootclasspathimagefds:",
-                                    ElementsAre(FdOf(primary.ImagePath()),
-                                                FdOf(framework_ext.ImagePath()),
-                                                FdOf(mainline_ext.ImagePath()),
-                                                "-1"))),
-                  Contains(ListFlag("-Xbootclasspathvdexfds:",
-                                    ElementsAre(FdOf(primary.VdexPath()),
-                                                FdOf(framework_ext.VdexPath()),
-                                                FdOf(mainline_ext.VdexPath()),
-                                                "-1"))),
-                  Contains(ListFlag("-Xbootclasspathoatfds:",
-                                    ElementsAre(FdOf(primary.OatPath()),
-                                                FdOf(framework_ext.OatPath()),
-                                                FdOf(mainline_ext.OatPath()),
-                                                "-1"))))))
-      .Times(odrefresh_->AllSystemServerJars().size())
-      .WillRepeatedly(Return(0));
+  if (IsAtLeastU()) {
+    EXPECT_CALL(*mock_exec_utils_,
+                DoExecAndReturnCode(AllOf(
+                    Contains(ListFlag("--boot-image=",
+                                      ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
+                                                  dalvik_cache_dir_ + "/boot-conscrypt.art"))),
+                    Contains(ListFlag("-Xbootclasspathimagefds:",
+                                      ElementsAre(FdOf(primary.ImagePath()),
+                                                  FdOf(framework_ext.ImagePath()),
+                                                  FdOf(mainline_ext.ImagePath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathvdexfds:",
+                                      ElementsAre(FdOf(primary.VdexPath()),
+                                                  FdOf(framework_ext.VdexPath()),
+                                                  FdOf(mainline_ext.VdexPath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathoatfds:",
+                                      ElementsAre(FdOf(primary.OatPath()),
+                                                  FdOf(framework_ext.OatPath()),
+                                                  FdOf(mainline_ext.OatPath()),
+                                                  "-1"))))))
+        .Times(odrefresh_->AllSystemServerJars().size())
+        .WillRepeatedly(Return(0));
+  } else {
+    EXPECT_CALL(*mock_exec_utils_,
+                DoExecAndReturnCode(AllOf(
+                    Contains(ListFlag("--boot-image=",
+                                      ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
+                                                  framework_dir_ + "/boot-framework.art",
+                                                  dalvik_cache_dir_ + "/boot-conscrypt.art"))),
+                    Contains(ListFlag("-Xbootclasspathimagefds:",
+                                      ElementsAre(FdOf(primary.ImagePath()),
+                                                  FdOf(framework_ext.ImagePath()),
+                                                  FdOf(mainline_ext.ImagePath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathvdexfds:",
+                                      ElementsAre(FdOf(primary.VdexPath()),
+                                                  FdOf(framework_ext.VdexPath()),
+                                                  FdOf(mainline_ext.VdexPath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathoatfds:",
+                                      ElementsAre(FdOf(primary.OatPath()),
+                                                  FdOf(framework_ext.OatPath()),
+                                                  FdOf(mainline_ext.OatPath()),
+                                                  "-1"))))))
+        .Times(odrefresh_->AllSystemServerJars().size())
+        .WillRepeatedly(Return(0));
+  }
+
   EXPECT_EQ(
       odrefresh_->Compile(*metrics_,
                           CompilationOptions{
@@ -832,29 +879,55 @@
   auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
   auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
 
-  EXPECT_CALL(*mock_exec_utils_,
-              DoExecAndReturnCode(AllOf(
-                  Contains(ListFlag("--boot-image=",
-                                    ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
-                                                framework_dir_ + "/boot-framework.art",
-                                                framework_dir_ + "/boot-conscrypt.art"))),
-                  Contains(ListFlag("-Xbootclasspathimagefds:",
-                                    ElementsAre(FdOf(primary.ImagePath()),
-                                                FdOf(framework_ext.ImagePath()),
-                                                FdOf(mainline_ext.ImagePath()),
-                                                "-1"))),
-                  Contains(ListFlag("-Xbootclasspathvdexfds:",
-                                    ElementsAre(FdOf(primary.VdexPath()),
-                                                FdOf(framework_ext.VdexPath()),
-                                                FdOf(mainline_ext.VdexPath()),
-                                                "-1"))),
-                  Contains(ListFlag("-Xbootclasspathoatfds:",
-                                    ElementsAre(FdOf(primary.OatPath()),
-                                                FdOf(framework_ext.OatPath()),
-                                                FdOf(mainline_ext.OatPath()),
-                                                "-1"))))))
-      .Times(odrefresh_->AllSystemServerJars().size())
-      .WillRepeatedly(Return(0));
+  if (IsAtLeastU()) {
+    EXPECT_CALL(*mock_exec_utils_,
+                DoExecAndReturnCode(AllOf(
+                    Contains(ListFlag("--boot-image=",
+                                      ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
+                                                  framework_dir_ + "/boot-conscrypt.art"))),
+                    Contains(ListFlag("-Xbootclasspathimagefds:",
+                                      ElementsAre(FdOf(primary.ImagePath()),
+                                                  FdOf(framework_ext.ImagePath()),
+                                                  FdOf(mainline_ext.ImagePath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathvdexfds:",
+                                      ElementsAre(FdOf(primary.VdexPath()),
+                                                  FdOf(framework_ext.VdexPath()),
+                                                  FdOf(mainline_ext.VdexPath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathoatfds:",
+                                      ElementsAre(FdOf(primary.OatPath()),
+                                                  FdOf(framework_ext.OatPath()),
+                                                  FdOf(mainline_ext.OatPath()),
+                                                  "-1"))))))
+        .Times(odrefresh_->AllSystemServerJars().size())
+        .WillRepeatedly(Return(0));
+  } else {
+    EXPECT_CALL(*mock_exec_utils_,
+                DoExecAndReturnCode(AllOf(
+                    Contains(ListFlag("--boot-image=",
+                                      ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
+                                                  framework_dir_ + "/boot-framework.art",
+                                                  framework_dir_ + "/boot-conscrypt.art"))),
+                    Contains(ListFlag("-Xbootclasspathimagefds:",
+                                      ElementsAre(FdOf(primary.ImagePath()),
+                                                  FdOf(framework_ext.ImagePath()),
+                                                  FdOf(mainline_ext.ImagePath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathvdexfds:",
+                                      ElementsAre(FdOf(primary.VdexPath()),
+                                                  FdOf(framework_ext.VdexPath()),
+                                                  FdOf(mainline_ext.VdexPath()),
+                                                  "-1"))),
+                    Contains(ListFlag("-Xbootclasspathoatfds:",
+                                      ElementsAre(FdOf(primary.OatPath()),
+                                                  FdOf(framework_ext.OatPath()),
+                                                  FdOf(mainline_ext.OatPath()),
+                                                  "-1"))))))
+        .Times(odrefresh_->AllSystemServerJars().size())
+        .WillRepeatedly(Return(0));
+  }
+
   EXPECT_EQ(
       odrefresh_->Compile(*metrics_,
                           CompilationOptions{