Pass the fd to OatFile::Setup to avoid selinux errors.

bug: 77853712
Test: test.py
Change-Id: I069cda5296b561284d71b067924e1bc4a8562710
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index bc8468e..a229d7d 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -135,7 +135,8 @@
       ASSERT_TRUE(success) << error_msg << std::endl << output_;
 
       // Verify the odex file was generated as expected.
-      std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+      std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                       odex_location.c_str(),
                                                        odex_location.c_str(),
                                                        nullptr,
                                                        nullptr,
@@ -154,7 +155,8 @@
 
       if (!test_accepts_odex_file_on_failure) {
         // Verify there's no loadable odex file.
-        std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+        std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                         odex_location.c_str(),
                                                          odex_location.c_str(),
                                                          nullptr,
                                                          nullptr,
@@ -542,7 +544,8 @@
     }
     // Host/target independent checks.
     std::string error_msg;
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                     odex_location.c_str(),
                                                      odex_location.c_str(),
                                                      nullptr,
                                                      nullptr,
@@ -812,7 +815,8 @@
                    const std::string& app_image_file_name) {
     // Host/target independent checks.
     std::string error_msg;
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                     odex_location.c_str(),
                                                      odex_location.c_str(),
                                                      nullptr,
                                                      nullptr,
@@ -973,7 +977,8 @@
 
   void CheckResult(const std::string& dex_location, const std::string& odex_location) {
     std::string error_msg;
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                     odex_location.c_str(),
                                                      odex_location.c_str(),
                                                      nullptr,
                                                      nullptr,
@@ -1366,7 +1371,8 @@
   EXPECT_EQ(res, 0);
 
   // Open our generated oat file.
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_filename.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_filename.c_str(),
                                                    oat_filename.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -1479,7 +1485,8 @@
       {"--compact-dex-level=fast"});
   EXPECT_EQ(res, 0);
   // Open our generated oat file.
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_filename.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_filename.c_str(),
                                                    oat_filename.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -1724,7 +1731,8 @@
                       });
   // Open our generated oat file.
   std::string error_msg;
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_filename.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_filename.c_str(),
                                                    oat_filename.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -1801,7 +1809,8 @@
                       { "--compilation-reason=install" },
                       true);
   std::string error_msg;
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   odex_location.c_str(),
                                                    odex_location.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -1826,7 +1835,8 @@
                       {},
                       true);
   std::string error_msg;
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   odex_location.c_str(),
                                                    odex_location.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -1863,7 +1873,8 @@
     ASSERT_TRUE(vdex != nullptr);
     EXPECT_FALSE(vdex->HasDexSection()) << output_;
   }
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   odex_location.c_str(),
                                                    odex_location.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -2106,7 +2117,8 @@
                       [](const OatFile&) {});
   // Open our generated oat file.
   std::string error_msg;
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   odex_location.c_str(),
                                                    odex_location.c_str(),
                                                    nullptr,
                                                    nullptr,
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 37e69f7..208e96f 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -426,7 +426,8 @@
   if (kCompile) {  // OatWriter strips the code, regenerate to compare
     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
   }
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                  tmp_oat.GetFilename(),
                                                   tmp_oat.GetFilename(),
                                                   nullptr,
                                                   nullptr,
@@ -560,7 +561,8 @@
                           /* verify */ false);
   ASSERT_TRUE(success);
 
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                  tmp_oat.GetFilename(),
                                                   tmp_oat.GetFilename(),
                                                   nullptr,
                                                   nullptr,
@@ -637,7 +639,8 @@
   ASSERT_TRUE(success);
 
   std::string error_msg;
-  std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(tmp_oat.GetFilename(),
+  std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                         tmp_oat.GetFilename(),
                                                          tmp_oat.GetFilename(),
                                                          nullptr,
                                                          nullptr,
@@ -767,7 +770,8 @@
       ASSERT_TRUE(success);
 
       std::string error_msg;
-      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(tmp_oat.GetFilename(),
+      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                             tmp_oat.GetFilename(),
                                                              tmp_oat.GetFilename(),
                                                              nullptr,
                                                              nullptr,
@@ -816,7 +820,8 @@
       ASSERT_TRUE(success);
 
       std::string error_msg;
-      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(tmp_oat.GetFilename(),
+      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                             tmp_oat.GetFilename(),
                                                              tmp_oat.GetFilename(),
                                                              nullptr,
                                                              nullptr,
diff --git a/dexlayout/dexdiag_test.cc b/dexlayout/dexdiag_test.cc
index 068949c..53145c2 100644
--- a/dexlayout/dexdiag_test.cc
+++ b/dexlayout/dexdiag_test.cc
@@ -68,7 +68,8 @@
     EXPECT_TRUE(!oat_location.empty());
     std::cout << "==" << oat_location << std::endl;
     std::string error_msg;
-    std::unique_ptr<OatFile> oat(OatFile::Open(oat_location.c_str(),
+    std::unique_ptr<OatFile> oat(OatFile::Open(/* zip_fd */ -1,
+                                               oat_location.c_str(),
                                                oat_location.c_str(),
                                                nullptr,
                                                nullptr,
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 6a68b55..44050ff 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -2156,7 +2156,8 @@
       oat_file = runtime->GetOatFileManager().FindOpenedOatFileFromOatLocation(oat_location);
     }
     if (oat_file == nullptr) {
-      oat_file = OatFile::Open(oat_location,
+      oat_file = OatFile::Open(/* zip_fd */ -1,
+                               oat_location,
                                oat_location,
                                nullptr,
                                nullptr,
@@ -3044,7 +3045,8 @@
     // We need to map the oat file in the low 4gb or else the fixup wont be able to fit oat file
     // pointers into 32 bit pointer sized ArtMethods.
     std::string error_msg;
-    std::unique_ptr<OatFile> oat_file(OatFile::Open(options->app_oat_,
+    std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                    options->app_oat_,
                                                     options->app_oat_,
                                                     nullptr,
                                                     nullptr,
@@ -3167,7 +3169,8 @@
                  << "oatdump might fail if the oat file does not contain the dex code.";
   }
   std::string error_msg;
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                  oat_filename,
                                                   oat_filename,
                                                   nullptr,
                                                   nullptr,
@@ -3192,7 +3195,8 @@
                         std::string& output_name,
                         bool no_bits) {
   std::string error_msg;
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                  oat_filename,
                                                   oat_filename,
                                                   nullptr,
                                                   nullptr,
@@ -3239,7 +3243,8 @@
 
     if (oat_filename != nullptr) {
       std::string error_msg;
-      std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
+      std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                      oat_filename,
                                                       oat_filename,
                                                       nullptr,
                                                       nullptr,
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 8f0f9c6..f8388f3 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -105,7 +105,8 @@
   }
 
   // Verify the odex file was generated as expected.
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_location.c_str(),
                                                    oat_location.c_str(),
                                                    nullptr,
                                                    nullptr,
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index e2154b8..dbe09e8 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1418,7 +1418,8 @@
 
     CHECK(image_header.GetOatDataBegin() != nullptr);
 
-    std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
+    std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
+                                                    oat_filename,
                                                     oat_filename,
                                                     image_header.GetOatDataBegin(),
                                                     image_header.GetOatFileBegin(),
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index fcc47d4..f202a43 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -43,7 +43,8 @@
   args.push_back("--oat-file=" + oat_location);
   ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
 
-  std::unique_ptr<OatFile> oat(OatFile::Open(oat_location.c_str(),
+  std::unique_ptr<OatFile> oat(OatFile::Open(/* zip_fd */ -1,
+                                             oat_location.c_str(),
                                              oat_location.c_str(),
                                              nullptr,
                                              nullptr,
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c7a558c..371678d 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -97,7 +97,8 @@
   virtual ~OatFileBase() {}
 
   template <typename kOatFileBaseSubType>
-  static OatFileBase* OpenOatFile(const std::string& vdex_filename,
+  static OatFileBase* OpenOatFile(int zip_fd,
+                                  const std::string& vdex_filename,
                                   const std::string& elf_filename,
                                   const std::string& location,
                                   uint8_t* requested_base,
@@ -109,7 +110,8 @@
                                   std::string* error_msg);
 
   template <typename kOatFileBaseSubType>
-  static OatFileBase* OpenOatFile(int vdex_fd,
+  static OatFileBase* OpenOatFile(int zip_fd,
+                                  int vdex_fd,
                                   int oat_fd,
                                   const std::string& vdex_filename,
                                   const std::string& oat_filename,
@@ -160,7 +162,7 @@
 
   virtual void PreSetup(const std::string& elf_filename) = 0;
 
-  bool Setup(const char* abs_dex_location, std::string* error_msg);
+  bool Setup(int zip_fd, const char* abs_dex_location, std::string* error_msg);
 
   // Setters exposed for ElfOatFile.
 
@@ -181,7 +183,8 @@
 };
 
 template <typename kOatFileBaseSubType>
-OatFileBase* OatFileBase::OpenOatFile(const std::string& vdex_filename,
+OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
+                                      const std::string& vdex_filename,
                                       const std::string& elf_filename,
                                       const std::string& location,
                                       uint8_t* requested_base,
@@ -214,7 +217,7 @@
 
   ret->PreSetup(elf_filename);
 
-  if (!ret->Setup(abs_dex_location, error_msg)) {
+  if (!ret->Setup(zip_fd, abs_dex_location, error_msg)) {
     return nullptr;
   }
 
@@ -222,7 +225,8 @@
 }
 
 template <typename kOatFileBaseSubType>
-OatFileBase* OatFileBase::OpenOatFile(int vdex_fd,
+OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
+                                      int vdex_fd,
                                       int oat_fd,
                                       const std::string& vdex_location,
                                       const std::string& oat_location,
@@ -254,7 +258,7 @@
 
   ret->PreSetup(oat_location);
 
-  if (!ret->Setup(abs_dex_location, error_msg)) {
+  if (!ret->Setup(zip_fd, abs_dex_location, error_msg)) {
     return nullptr;
   }
 
@@ -485,7 +489,7 @@
   }
 }
 
-bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
+bool OatFileBase::Setup(int zip_fd, const char* abs_dex_location, std::string* error_msg) {
   if (!GetOatHeader().IsValid()) {
     std::string cause = GetOatHeader().GetValidationErrorMessage();
     *error_msg = StringPrintf("Invalid oat header for '%s': %s",
@@ -641,12 +645,23 @@
         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())) {
+        bool loaded = false;
+        if (zip_fd != -1) {
+          loaded = dex_file_loader.OpenZip(zip_fd,
+                                           dex_file_location,
+                                           /* verify */ false,
+                                           /* verify_checksum */ false,
+                                           error_msg,
+                                           uncompressed_dex_files_.get());
+        } else {
+          loaded = dex_file_loader.Open(dex_file_location.c_str(),
+                                        dex_file_location,
+                                        /* verify */ false,
+                                        /* verify_checksum */ false,
+                                        error_msg,
+                                        uncompressed_dex_files_.get());
+        }
+        if (!loaded) {
           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.
@@ -1144,7 +1159,8 @@
  public:
   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
 
-  static ElfOatFile* OpenElfFile(File* file,
+  static ElfOatFile* OpenElfFile(int zip_fd,
+                                 File* file,
                                  const std::string& location,
                                  uint8_t* requested_base,
                                  uint8_t* oat_file_begin,  // Override base if not null
@@ -1154,7 +1170,8 @@
                                  const char* abs_dex_location,
                                  std::string* error_msg);
 
-  bool InitializeFromElfFile(ElfFile* elf_file,
+  bool InitializeFromElfFile(int zip_fd,
+                             ElfFile* elf_file,
                              VdexFile* vdex_file,
                              const char* abs_dex_location,
                              std::string* error_msg);
@@ -1204,7 +1221,8 @@
   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
 };
 
-ElfOatFile* ElfOatFile::OpenElfFile(File* file,
+ElfOatFile* ElfOatFile::OpenElfFile(int zip_fd,
+                                    File* file,
                                     const std::string& location,
                                     uint8_t* requested_base,
                                     uint8_t* oat_file_begin,  // Override base if not null
@@ -1231,14 +1249,15 @@
     return nullptr;
   }
 
-  if (!oat_file->Setup(abs_dex_location, error_msg)) {
+  if (!oat_file->Setup(zip_fd, abs_dex_location, error_msg)) {
     return nullptr;
   }
 
   return oat_file.release();
 }
 
-bool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
+bool ElfOatFile::InitializeFromElfFile(int zip_fd,
+                                       ElfFile* elf_file,
                                        VdexFile* vdex_file,
                                        const char* abs_dex_location,
                                        std::string* error_msg) {
@@ -1255,7 +1274,7 @@
   SetBegin(elf_file->Begin() + offset);
   SetEnd(elf_file->Begin() + size + offset);
   // Ignore the optional .bss section when opening non-executable.
-  return Setup(abs_dex_location, error_msg);
+  return Setup(zip_fd, abs_dex_location, error_msg);
 }
 
 bool ElfOatFile::Load(const std::string& elf_filename,
@@ -1356,18 +1375,20 @@
   CHECK(!location.empty());
 }
 
-OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
+OatFile* OatFile::OpenWithElfFile(int zip_fd,
+                                  ElfFile* elf_file,
                                   VdexFile* vdex_file,
                                   const std::string& location,
                                   const char* abs_dex_location,
                                   std::string* error_msg) {
   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */));
-  return oat_file->InitializeFromElfFile(elf_file, vdex_file, abs_dex_location, error_msg)
+  return oat_file->InitializeFromElfFile(zip_fd, elf_file, vdex_file, abs_dex_location, error_msg)
       ? oat_file.release()
       : nullptr;
 }
 
-OatFile* OatFile::Open(const std::string& oat_filename,
+OatFile* OatFile::Open(int zip_fd,
+                       const std::string& oat_filename,
                        const std::string& oat_location,
                        uint8_t* requested_base,
                        uint8_t* oat_file_begin,
@@ -1392,7 +1413,8 @@
 
   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
   // disabled.
-  OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(vdex_filename,
+  OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
+                                                                 vdex_filename,
                                                                  oat_filename,
                                                                  oat_location,
                                                                  requested_base,
@@ -1421,7 +1443,8 @@
   //
   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
-  OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_filename,
+  OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
+                                                                vdex_filename,
                                                                 oat_filename,
                                                                 oat_location,
                                                                 requested_base,
@@ -1434,7 +1457,8 @@
   return with_internal;
 }
 
-OatFile* OatFile::Open(int vdex_fd,
+OatFile* OatFile::Open(int zip_fd,
+                       int vdex_fd,
                        int oat_fd,
                        const std::string& oat_location,
                        uint8_t* requested_base,
@@ -1447,7 +1471,8 @@
 
   std::string vdex_location = GetVdexFilename(oat_location);
 
-  OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_fd,
+  OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
+                                                                vdex_fd,
                                                                 oat_fd,
                                                                 vdex_location,
                                                                 oat_location,
@@ -1461,12 +1486,14 @@
   return with_internal;
 }
 
-OatFile* OatFile::OpenWritable(File* file,
+OatFile* OatFile::OpenWritable(int zip_fd,
+                               File* file,
                                const std::string& location,
                                const char* abs_dex_location,
                                std::string* error_msg) {
   CheckLocation(location);
-  return ElfOatFile::OpenElfFile(file,
+  return ElfOatFile::OpenElfFile(zip_fd,
+                                 file,
                                  location,
                                  nullptr,
                                  nullptr,
@@ -1477,12 +1504,14 @@
                                  error_msg);
 }
 
-OatFile* OatFile::OpenReadable(File* file,
+OatFile* OatFile::OpenReadable(int zip_fd,
+                               File* file,
                                const std::string& location,
                                const char* abs_dex_location,
                                std::string* error_msg) {
   CheckLocation(location);
-  return ElfOatFile::OpenElfFile(file,
+  return ElfOatFile::OpenElfFile(zip_fd,
+                                 file,
                                  location,
                                  nullptr,
                                  nullptr,
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 6494b4c..8e18cee 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -74,7 +74,8 @@
 
   // Opens an oat file contained within the given elf file. This is always opened as
   // non-executable at the moment.
-  static OatFile* OpenWithElfFile(ElfFile* elf_file,
+  static OatFile* OpenWithElfFile(int zip_fd,
+                                  ElfFile* elf_file,
                                   VdexFile* vdex_file,
                                   const std::string& location,
                                   const char* abs_dex_location,
@@ -83,7 +84,8 @@
   // optionally be used to request where the file should be loaded.
   // See the ResolveRelativeEncodedDexLocation for a description of how the
   // abs_dex_location argument is used.
-  static OatFile* Open(const std::string& filename,
+  static OatFile* Open(int zip_fd,
+                       const std::string& filename,
                        const std::string& location,
                        uint8_t* requested_base,
                        uint8_t* oat_file_begin,
@@ -93,8 +95,10 @@
                        std::string* error_msg);
 
   // Similar to OatFile::Open(const std::string...), but accepts input vdex and
-  // odex files as file descriptors.
-  static OatFile* Open(int vdex_fd,
+  // odex files as file descriptors. We also take zip_fd in case the vdex does not
+  // contain the dex code, and we need to read it from the zip file.
+  static OatFile* Open(int zip_fd,
+                       int vdex_fd,
                        int oat_fd,
                        const std::string& oat_location,
                        uint8_t* requested_base,
@@ -109,11 +113,15 @@
   // where relocations may be required. Currently used from
   // ImageWriter which wants to open a writable version from an existing
   // file descriptor for patching.
-  static OatFile* OpenWritable(File* file, const std::string& location,
+  static OatFile* OpenWritable(int zip_fd,
+                               File* file,
+                               const std::string& location,
                                const char* abs_dex_location,
                                std::string* error_msg);
   // Open an oat file from an already opened File. Maps it PROT_READ, MAP_PRIVATE.
-  static OatFile* OpenReadable(File* file, const std::string& location,
+  static OatFile* OpenReadable(int zip_fd,
+                               File* file,
+                               const std::string& location,
                                const char* abs_dex_location,
                                std::string* error_msg);
 
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 718f917..9c8b651 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -118,7 +118,7 @@
   std::string error_msg;
   std::string odex_file_name;
   if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
-    odex_.Reset(odex_file_name, UseFdToReadFiles(), vdex_fd, oat_fd);
+    odex_.Reset(odex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
   } else {
     LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
   }
@@ -1148,7 +1148,8 @@
       std::string error_msg;
       if (use_fd_) {
         if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
-          file_.reset(OatFile::Open(vdex_fd_,
+          file_.reset(OatFile::Open(zip_fd_,
+                                    vdex_fd_,
                                     oat_fd_,
                                     filename_.c_str(),
                                     nullptr,
@@ -1159,7 +1160,8 @@
                                     &error_msg));
         }
       } else {
-        file_.reset(OatFile::Open(filename_.c_str(),
+        file_.reset(OatFile::Open(/* zip_fd */ -1,
+                                  filename_.c_str(),
                                   filename_.c_str(),
                                   nullptr,
                                   nullptr,
@@ -1235,11 +1237,15 @@
   status_attempted_ = false;
 }
 
-void OatFileAssistant::OatFileInfo::Reset(const std::string& filename, bool use_fd, int vdex_fd,
+void OatFileAssistant::OatFileInfo::Reset(const std::string& filename,
+                                          bool use_fd,
+                                          int zip_fd,
+                                          int vdex_fd,
                                           int oat_fd) {
   filename_provided_ = true;
   filename_ = filename;
   use_fd_ = use_fd;
+  zip_fd_ = zip_fd;
   vdex_fd_ = vdex_fd;
   oat_fd_ = oat_fd;
   Reset();
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 8d6ec00..a6d0961 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -378,7 +378,11 @@
 
     // Clear any cached information and switch to getting info about the oat
     // file with the given filename.
-    void Reset(const std::string& filename, bool use_fd, int vdex_fd = -1, int oat_fd = -1);
+    void Reset(const std::string& filename,
+               bool use_fd,
+               int zip_fd = -1,
+               int vdex_fd = -1,
+               int oat_fd = -1);
 
     // Release the loaded oat file for runtime use.
     // Returns null if the oat file hasn't been loaded or is out of date.
@@ -415,6 +419,7 @@
     bool filename_provided_ = false;
     std::string filename_;
 
+    int zip_fd_ = -1;
     int oat_fd_ = -1;
     int vdex_fd_ = -1;
     bool use_fd_ = false;
diff --git a/runtime/oat_file_test.cc b/runtime/oat_file_test.cc
index 89812f3..12dfe20 100644
--- a/runtime/oat_file_test.cc
+++ b/runtime/oat_file_test.cc
@@ -74,7 +74,8 @@
   std::string error_msg;
   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_location.c_str(),
                                                    oat_location.c_str(),
                                                    nullptr,
                                                    nullptr,
@@ -101,7 +102,8 @@
 
   // Ensure we can load that file. Just a precondition.
   {
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                     oat_location.c_str(),
                                                      oat_location.c_str(),
                                                      nullptr,
                                                      nullptr,
@@ -117,7 +119,8 @@
   Copy(GetTestDexFileName("MainUncompressed"), dex_location);
 
   // And try to load again.
-  std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+  std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
+                                                   oat_location.c_str(),
                                                    oat_location.c_str(),
                                                    nullptr,
                                                    nullptr,
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c394fef..bfed326 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1002,7 +1002,8 @@
       return false;
     }
     std::unique_ptr<const OatFile> oat_file(
-        OatFile::OpenWithElfFile(elf_file.release(),
+        OatFile::OpenWithElfFile(/* zip_fd */ -1,
+                                 elf_file.release(),
                                  vdex_file.release(),
                                  oat_location,
                                  nullptr,