dex2oat: Fix vdex file invalidation.

We erroneously stored the invalid vdex magic "wdex" after
the header because we already read the header and did not
seek back to the start of the file.

(cherry picked from commit 4b62522c9d7d5cb4177d337b9a162df9471f4aff)

Test: Updated dex2oat_test#RunUnquickenMultiDex.
Test: m test-art-host-gtest
Bug: 155366778
Merged-In: Ie369a8822d08be731b8d272fa8556c3939aeb66f
Change-Id: I8f7a0d06dbb9cedd319b9c0d7c340107ce88e56c
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ee838da..d769543 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1559,18 +1559,17 @@
     // Note: we're only invalidating the magic data in the file, as dex2oat needs the rest of
     // the information to remain valid.
     if (update_input_vdex_) {
-      std::unique_ptr<BufferedOutputStream> vdex_out =
-          std::make_unique<BufferedOutputStream>(
-              std::make_unique<FileOutputStream>(vdex_files_.back().get()));
-      if (!vdex_out->WriteFully(&VdexFile::VerifierDepsHeader::kVdexInvalidMagic,
-                                arraysize(VdexFile::VerifierDepsHeader::kVdexInvalidMagic))) {
-        PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_out->GetLocation();
+      File* vdex_file = vdex_files_.back().get();
+      if (!vdex_file->PwriteFully(&VdexFile::VerifierDepsHeader::kVdexInvalidMagic,
+                                  arraysize(VdexFile::VerifierDepsHeader::kVdexInvalidMagic),
+                                  /*offset=*/ 0u)) {
+        PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_file->GetPath();
         return false;
       }
 
-      if (!vdex_out->Flush()) {
+      if (vdex_file->Flush() != 0) {
         PLOG(ERROR) << "Failed to flush stream after invalidating header of vdex file."
-                    << " File: " << vdex_out->GetLocation();
+                    << " File: " << vdex_file->GetPath();
         return false;
       }
     }
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 45b7e4a..54d5196 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -896,6 +896,9 @@
                                       /* use_fd= */ true));
       EXPECT_GT(vdex_file1->GetLength(), 0u);
     }
+    // Get the dex file checksums.
+    std::vector<uint32_t> checksums1;
+    GetDexFileChecksums(dex_location, odex_location, &checksums1);
     // Unquicken by running the verify compiler filter on the vdex file.
     {
       std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
@@ -909,6 +912,13 @@
     }
     ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
     CheckResult(dex_location, odex_location);
+    // Verify that the checksums did not change.
+    std::vector<uint32_t> checksums2;
+    GetDexFileChecksums(dex_location, odex_location, &checksums2);
+    ASSERT_EQ(checksums1.size(), checksums2.size());
+    for (size_t i = 0; i != checksums1.size(); ++i) {
+      EXPECT_EQ(checksums1[i], checksums2[i]) << i;
+    }
     ASSERT_TRUE(success_);
   }
 
@@ -937,7 +947,6 @@
                                       /* use_fd= */ true));
       EXPECT_GT(vdex_file1->GetLength(), 0u);
     }
-
     // Unquicken by running the verify compiler filter on the vdex file.
     {
       std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
@@ -979,6 +988,24 @@
       }
     }
   }
+
+  void GetDexFileChecksums(const std::string& dex_location,
+                           const std::string& odex_location,
+                           /*out*/std::vector<uint32_t>* checksums) {
+    std::string error_msg;
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
+                                                     odex_location.c_str(),
+                                                     odex_location.c_str(),
+                                                     /*executable=*/ false,
+                                                     /*low_4gb=*/ false,
+                                                     dex_location,
+                                                     &error_msg));
+    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
+    ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
+    for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
+      checksums->push_back(oat_dex_file->GetDexFileLocationChecksum());
+    }
+  }
 };
 
 TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {