Convert to StandardDex in fixup_dex_dex_file

In fixup_dex_file, run dexlayout to convert compact dex back to
standard dex since the output is supposed to be standard dex.

Fixed a bug in dexlayout where conversion from compact dex ->
standard dex was not supported becuase the dex header was always
preserved.

Test: test/testrunner/testrunner.py  --host ---redefine-stress --compact-dex-level fast
Bug: 63756964

Change-Id: Id13e8593458213e7040d053c35e8914404ae5381
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index a18a2cf..489a6b1 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -774,9 +774,16 @@
 
 void DexWriter::WriteHeader() {
   StandardDexFile::Header header;
-  static constexpr size_t kMagicAndVersionLen =
-      StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
-  std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
+  if (CompactDexFile::IsMagicValid(header_->Magic())) {
+    StandardDexFile::WriteMagic(header.magic_);
+    // TODO: Should we write older versions based on the feature flags?
+    StandardDexFile::WriteCurrentVersion(header.magic_);
+  } else {
+    // Standard dex -> standard dex, just reuse the same header.
+    static constexpr size_t kMagicAndVersionLen =
+        StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
+    std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
+  }
   header.checksum_ = header_->Checksum();
   std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
   header.file_size_ = header_->FileSize();
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 47a3e94..000d135 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1912,7 +1912,8 @@
     if (do_layout) {
       LayoutOutputFile(dex_file);
     }
-    OutputDexFile(dex_file, do_layout);
+    // If we didn't set the offsets eagerly, we definitely need to compute them here.
+    OutputDexFile(dex_file, do_layout || !eagerly_assign_offsets);
 
     // Clear header before verifying to reduce peak RAM usage.
     const size_t file_size = header_->FileSize();
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 9ba7068..0283999 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -68,6 +68,7 @@
     shared_libs: [
         "libart",
         "libart-compiler",
+        "libart-dexlayout",
     ],
 }
 
@@ -80,5 +81,6 @@
     shared_libs: [
         "libartd",
         "libartd-compiler",
+        "libartd-dexlayout",
     ],
 }
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index ad928d9..da7d60a 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -34,7 +34,9 @@
 #include "dex/dex_file_loader.h"
 
 // Runtime includes.
+#include "dex/compact_dex_level.h"
 #include "dex_to_dex_decompiler.h"
+#include "dexlayout.h"
 #include "oat_file.h"
 #include "vdex_file.h"
 
@@ -85,6 +87,33 @@
   }
 
   DoDexUnquicken(*new_dex_file, original);
+
+  if (original.IsCompactDexFile()) {
+    // Since we are supposed to return a standard dex, convert back using dexlayout.
+    art::Options options;
+    options.output_to_memmap_ = true;
+    options.compact_dex_level_ = art::CompactDexLevel::kCompactDexLevelNone;
+    options.update_checksum_ = true;
+    art::DexLayout dex_layout(options, nullptr, nullptr);
+    dex_layout.ProcessDexFile(new_dex_file->GetLocation().c_str(), new_dex_file.get(), 0);
+    std::unique_ptr<art::MemMap> mem_map(dex_layout.GetAndReleaseMemMap());
+
+    const uint32_t dex_file_size =
+        reinterpret_cast<const art::DexFile::Header*>(mem_map->Begin())->file_size_;
+    // Overwrite the dex file stored in data with the new result.
+    data.clear();
+    data.insert(data.end(), mem_map->Begin(), mem_map->Begin() + dex_file_size);
+    new_dex_file = art::DexFileLoader::Open(
+        data.data(),
+        data.size(),
+        /*location*/"Unquickening_dexfile.dex",
+        /*location_checksum*/0,
+        /*oat_dex_file*/nullptr,
+        /*verify*/false,
+        /*verify_checksum*/false,
+        &error);
+  }
+
   RecomputeDexChecksum(const_cast<art::DexFile*>(new_dex_file.get()));
   std::unique_ptr<FixedUpDexFile> ret(new FixedUpDexFile(std::move(new_dex_file), std::move(data)));
   return ret;
diff --git a/runtime/dex/dex_file_verifier.cc b/runtime/dex/dex_file_verifier.cc
index c2f772e..7265aad 100644
--- a/runtime/dex/dex_file_verifier.cc
+++ b/runtime/dex/dex_file_verifier.cc
@@ -386,15 +386,14 @@
     return false;
   }
 
-  bool size_matches = false;
-  if (dex_file_->IsCompactDexFile()) {
-    size_matches = header_->header_size_ == sizeof(CompactDexFile::Header);
-  } else {
-    size_matches = header_->header_size_ == sizeof(StandardDexFile::Header);
-  }
+  const uint32_t expected_header_size = dex_file_->IsCompactDexFile()
+      ? sizeof(CompactDexFile::Header)
+      : sizeof(StandardDexFile::Header);
 
-  if (!size_matches) {
-    ErrorStringPrintf("Bad header size: %ud", header_->header_size_);
+  if (header_->header_size_ != expected_header_size) {
+    ErrorStringPrintf("Bad header size: %ud expected %ud",
+                      header_->header_size_,
+                      expected_header_size);
     return false;
   }