Revert "Revert "Don't embed the dex code in the oat file if dex is uncompressed.""

Bug: 63920015
Bug: 70854754

Test: oat_writer_test.cc, test.py

Revert was due to userdebug/user differences, which is fixed with:
https://googleplex-android-review.googlesource.com/#/c/platform/build/+/3434091/

This CL also fixes oatdump when the dex code is not in the .vdex file.

This reverts commit e166e67666bf4b23e4ed0a98f5e2bb3cae9cee7d.

Change-Id: Iec924be2ff8f03cf2ebe306e7a0018241f33beb0
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c03dbcc..9fd9905 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -620,14 +620,6 @@
                                 dex_file_location.c_str());
       return false;
     }
-    if (UNLIKELY(dex_file_offset == 0U)) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
-                                    "file offset",
-                                GetLocation().c_str(),
-                                i,
-                                dex_file_location.c_str());
-      return false;
-    }
     if (UNLIKELY(dex_file_offset > DexSize())) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
                                     "offset %u > %zu",
@@ -638,20 +630,45 @@
                                 DexSize());
       return false;
     }
-    if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
-                                    "offset %u of %zu but the size of dex file header is %zu",
-                                GetLocation().c_str(),
-                                i,
-                                dex_file_location.c_str(),
-                                dex_file_offset,
-                                DexSize(),
-                                sizeof(DexFile::Header));
-      return false;
+    const uint8_t* dex_file_pointer = nullptr;
+    if (UNLIKELY(dex_file_offset == 0U)) {
+      if (uncompressed_dex_files_ == nullptr) {
+        uncompressed_dex_files_.reset(new std::vector<std::unique_ptr<const DexFile>>());
+        // No dex files, load it from location.
+        const ArtDexFileLoader dex_file_loader;
+        if (!dex_file_loader.Open(dex_file_location.c_str(),
+                                  dex_file_location,
+                                  /* verify */ false,
+                                  /* verify_checksum */ false,
+                                  error_msg,
+                                  uncompressed_dex_files_.get())) {
+          if (Runtime::Current() == nullptr) {
+            // If there's no runtime, we're running oatdump, so return
+            // a half constructed oat file that oatdump knows how to deal with.
+            LOG(WARNING) << "Could not find associated dex files of oat file. "
+                         << "Oatdump will only dump the header.";
+            return true;
+          } else {
+            return false;
+          }
+        }
+      }
+      dex_file_pointer = uncompressed_dex_files_.get()->at(i)->Begin();
+    } else {
+      if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
+        *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
+                                      "offset %u of %zu but the size of dex file header is %zu",
+                                  GetLocation().c_str(),
+                                  i,
+                                  dex_file_location.c_str(),
+                                  dex_file_offset,
+                                  DexSize(),
+                                  sizeof(DexFile::Header));
+        return false;
+      }
+      dex_file_pointer = DexBegin() + dex_file_offset;
     }
 
-    const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset;
-
     const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
     if (UNLIKELY(!valid_magic)) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
@@ -672,7 +689,7 @@
       return false;
     }
     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
-    if (DexSize() - dex_file_offset < header->file_size_) {
+    if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
                                     "offset %u and size %u truncated at %zu",
                                 GetLocation().c_str(),
@@ -1297,13 +1314,15 @@
 
 std::string OatFile::ResolveRelativeEncodedDexLocation(
       const char* abs_dex_location, const std::string& rel_dex_location) {
-  if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
+  // For host, we still do resolution as the rel_dex_location might be absolute
+  // for a target dex (for example /system/foo/foo.apk).
+  if (abs_dex_location != nullptr && (rel_dex_location[0] != '/' || !kIsTargetBuild)) {
     // Strip :classes<N>.dex used for secondary multidex files.
     std::string base = DexFileLoader::GetBaseLocation(rel_dex_location);
     std::string multidex_suffix = DexFileLoader::GetMultiDexSuffix(rel_dex_location);
 
     // Check if the base is a suffix of the provided abs_dex_location.
-    std::string target_suffix = "/" + base;
+    std::string target_suffix = ((rel_dex_location[0] != '/') ? "/" : "") + base;
     std::string abs_location(abs_dex_location);
     if (abs_location.size() > target_suffix.size()) {
       size_t pos = abs_location.size() - target_suffix.size();