Merge "Ensure loaded plugins are not copied."
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index b16c56a..6b75595 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1716,6 +1716,34 @@
   }
 }
 
+TEST_F(Dex2oatTest, CompactDexGenerationFailureMultiDex) {
+  // Create a multidex file with only one dex that gets rejected for cdex conversion.
+  ScratchFile apk_file;
+  {
+    FILE* file = fdopen(apk_file.GetFd(), "w+b");
+    ZipWriter writer(file);
+    // Add vdex to zip.
+    writer.StartEntry("classes.dex", ZipWriter::kCompress);
+    size_t length = 0u;
+    std::unique_ptr<uint8_t[]> bytes(DecodeBase64(kDuplicateMethodInputDex, &length));
+    ASSERT_GE(writer.WriteBytes(&bytes[0], length), 0);
+    writer.FinishEntry();
+    writer.StartEntry("classes2.dex", ZipWriter::kCompress);
+    std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
+    ASSERT_GE(writer.WriteBytes(dex->Begin(), dex->Size()), 0);
+    writer.FinishEntry();
+    writer.Finish();
+    ASSERT_EQ(apk_file.GetFile()->Flush(), 0);
+  }
+  const std::string dex_location = apk_file.GetFilename();
+  const std::string odex_location = GetOdexDir() + "/output.odex";
+  GenerateOdexForTest(dex_location,
+                      odex_location,
+                      CompilerFilter::kQuicken,
+                      { "--compact-dex-level=fast" },
+                      true);
+}
+
 TEST_F(Dex2oatTest, StderrLoggerOutput) {
   std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
   std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index c980320..2feb14a 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -3372,6 +3372,7 @@
       CHECK(!update_input_vdex) << "Update input vdex should have empty dex container";
       DexContainer::Section* const section = dex_container_->GetDataSection();
       if (section->Size() > 0) {
+        CHECK(compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone);
         const off_t existing_offset = out->Seek(0, kSeekCurrent);
         if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
           PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
@@ -3395,7 +3396,10 @@
             PLOG(ERROR) << "Failed to read dex header for updating";
             return false;
           }
-          CHECK(CompactDexFile::IsMagicValid(header.magic_)) << "Must be compact dex";
+          if (!CompactDexFile::IsMagicValid(header.magic_)) {
+            // Non-compact dex file, probably failed to convert due to duplicate methods.
+            continue;
+          }
           CHECK_GT(vdex_dex_shared_data_offset_, oat_dex_file.dex_file_offset_);
           // Offset is from the dex file base.
           header.data_off_ = vdex_dex_shared_data_offset_ - oat_dex_file.dex_file_offset_;