Change dex naming for output directory

Write to Dex file names to match storage inside APK for -w option.
dir/classes.dex
dir/classes2.dex
...
dir/classesn.dex

This makes it easier to overwrite the Dex files in the APK.

Bug: 113059564
Test: test-art-host

Change-Id: Iadf1621402315887165813da4abf00d466f0f623
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index bd7a301..52d355b 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1794,14 +1794,20 @@
   // If options_.output_dex_directory_ is non null, we are outputting to a file.
   if (options_.output_dex_directory_ != nullptr) {
     std::string output_location(options_.output_dex_directory_);
-    size_t last_slash = dex_file_location.rfind('/');
+    const size_t last_slash = dex_file_location.rfind('/');
     std::string dex_file_directory = dex_file_location.substr(0, last_slash + 1);
     if (output_location == dex_file_directory) {
       output_location = dex_file_location + ".new";
-    } else if (last_slash != std::string::npos) {
-      output_location += dex_file_location.substr(last_slash);
     } else {
-      output_location += "/" + dex_file_location + ".new";
+      if (!output_location.empty() && output_location.back() != '/') {
+        output_location += "/";
+      }
+      const size_t separator = dex_file_location.rfind('!');
+      if (separator != std::string::npos) {
+        output_location += dex_file_location.substr(separator + 1);
+      } else {
+        output_location += "classes.dex";
+      }
     }
     new_file.reset(OS::CreateEmptyFile(output_location.c_str()));
     if (new_file == nullptr) {
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index a20930b..187c687 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -267,7 +267,7 @@
     ScratchFile dexlayout_output;
     const std::string& dexlayout_filename = dexlayout_output.GetFilename();
 
-    for (const std::string &dex_file : GetLibCoreDexFileNames()) {
+    for (const std::string& dex_file : GetLibCoreDexFileNames()) {
       std::vector<std::string> dexdump_exec_argv =
           { dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file };
       std::vector<std::string> dexlayout_args =
@@ -293,31 +293,33 @@
     const std::string& tmp_name = tmp_file.GetFilename();
     size_t tmp_last_slash = tmp_name.rfind('/');
     std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
+    std::string unzip_dir = tmp_dir + "unzip/";
 
-    for (const std::string &dex_file : GetLibCoreDexFileNames()) {
+    for (const std::string& dex_file : GetLibCoreDexFileNames()) {
       std::vector<std::string> dexlayout_args =
           { "-w", tmp_dir, "-o", tmp_name, dex_file };
       if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option*/ false)) {
         return false;
       }
-      size_t dex_file_last_slash = dex_file.rfind('/');
-      std::string dex_file_name = dex_file.substr(dex_file_last_slash + 1);
+      std::string dex_file_name = "classes.dex";
       std::vector<std::string> unzip_exec_argv =
-          { "/usr/bin/unzip", dex_file, "classes.dex", "-d", tmp_dir};
+          { "/usr/bin/unzip", dex_file, "classes.dex", "-d", unzip_dir};
       if (!::art::Exec(unzip_exec_argv, error_msg)) {
         return false;
       }
       std::vector<std::string> diff_exec_argv =
-          { "/usr/bin/diff", tmp_dir + "classes.dex" , tmp_dir + dex_file_name };
+          { "/usr/bin/diff", tmp_dir + "classes.dex" , unzip_dir + dex_file_name };
       if (!::art::Exec(diff_exec_argv, error_msg)) {
         return false;
       }
-      if (!UnlinkFile(tmp_dir + "classes.dex")) {
+      if (!UnlinkFile(unzip_dir + "classes.dex")) {
         return false;
       }
       if (!UnlinkFile(tmp_dir + dex_file_name)) {
         return false;
       }
+      // Remove the unzip temp directory so that unlinking android_data doesn't fail.
+      EXPECT_EQ(rmdir(unzip_dir.c_str()), 0);
     }
     return true;
   }