Add ISA directory to image and odex pathnames.

Bug: 14882223
Bug: 14694978
Change-Id: Ic1b5ae836b8e91ea461dcd4f3da8e38dc3bec00f
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6b98da9..54532b4 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -552,7 +552,7 @@
 
   gc::Heap* heap = Runtime::Current()->GetHeap();
   std::string boot_image_option("--boot-image=");
-  boot_image_option += heap->GetImageSpace()->GetImageFilename();
+  boot_image_option += heap->GetImageSpace()->GetImageLocation();
 
   std::string dex_file_option("--dex-file=");
   dex_file_option += dex_filename;
@@ -910,6 +910,7 @@
 
 const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const char* dex_location,
                                                                 const uint32_t* const dex_location_checksum,
+                                                                InstructionSet isa,
                                                                 std::vector<std::string>* error_msgs) {
   const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location,
                                                                   dex_location_checksum);
@@ -925,8 +926,8 @@
   }
 
   // Look for an existing file next to dex. for example, for
-  // /foo/bar/baz.jar, look for /foo/bar/baz.odex.
-  std::string odex_filename(OatFile::DexFilenameToOdexFilename(dex_location));
+  // /foo/bar/baz.jar, look for /foo/bar/<isa>/baz.odex.
+  std::string odex_filename(DexFilenameToOdexFilename(dex_location, isa));
   bool open_failed;
   std::string error_msg;
   const DexFile* dex_file = VerifyAndOpenDexFileFromOatFile(odex_filename, dex_location,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 3dac6e5..8037b91 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -280,6 +280,7 @@
   // does not match the OatFile.
   const DexFile* FindDexFileInOatFileFromDexLocation(const char* location,
                                                      const uint32_t* const location_checksum,
+                                                     InstructionSet isa,
                                                      std::vector<std::string>* error_msgs)
       LOCKS_EXCLUDED(dex_lock_, Locks::mutator_lock_);
 
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index d7a1667..54ef68d 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -75,9 +75,14 @@
     file_.reset(new File(fd, GetFilename()));
   }
 
+  explicit ScratchFile(File* file) {
+    CHECK(file != NULL);
+    filename_ = file->GetPath();
+    file_.reset(file);
+  }
+
   ~ScratchFile() {
-    int unlink_result = unlink(filename_.c_str());
-    CHECK_EQ(0, unlink_result);
+    Unlink();
   }
 
   const std::string& GetFilename() const {
@@ -92,6 +97,14 @@
     return file_->Fd();
   }
 
+  void Unlink() {
+    if (!OS::FileExists(filename_.c_str())) {
+      return;
+    }
+    int unlink_result = unlink(filename_.c_str());
+    CHECK_EQ(0, unlink_result);
+  }
+
  private:
   std::string filename_;
   UniquePtr<File> file_;
@@ -258,11 +271,7 @@
       filename += getenv("ANDROID_HOST_OUT");
       filename += "/framework/";
     } else {
-#ifdef __LP64__
-      filename += "/data/nativetest/art64/";
-#else
       filename += "/data/nativetest/art/";
-#endif
     }
     filename += "art-test-dex-";
     filename += name;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 446f898..2a717cb 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -103,8 +103,11 @@
                                    const InstructionSet image_isa,
                                    std::string* image_filename,
                                    bool *is_system) {
-  if (OS::FileExists(image_location)) {
-    *image_filename = image_location;
+  // image_location = /system/framework/boot.art
+  // system_image_location = /system/framework/<image_isa>/boot.art
+  std::string system_image_filename(GetSystemImageFilename(image_location, image_isa));
+  if (OS::FileExists(system_image_filename.c_str())) {
+    *image_filename = system_image_filename;
     *is_system = true;
     return true;
   }
@@ -113,6 +116,9 @@
 
   // Always set output location even if it does not exist,
   // so that the caller knows where to create the image.
+  //
+  // image_location = /system/framework/boot.art
+  // *image_filename = /data/dalvik-cache/<image_isa>/boot.art
   *image_filename = GetDalvikCacheFilenameOrDie(image_location, dalvik_cache.c_str());
   *is_system = false;
   return OS::FileExists(image_filename->c_str());
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 5353592..27f19a7 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -115,7 +115,9 @@
   if (outputName.c_str() == nullptr) {
     // FindOrCreateOatFileForDexLocation can tolerate a missing dex_location_checksum
     dex_file = linker->FindDexFileInOatFileFromDexLocation(sourceName.c_str(),
-                                                           dex_location_checksum_pointer, &error_msgs);
+                                                           dex_location_checksum_pointer,
+                                                           kRuntimeISA,
+                                                           &error_msgs);
   } else {
     // FindOrCreateOatFileForDexLocation requires the dex_location_checksum
     if (dex_location_checksum_pointer == NULL) {
@@ -387,7 +389,7 @@
   const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
 
   // Check if we have an odex file next to the dex file.
-  std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename));
+  std::string odex_filename(DexFilenameToOdexFilename(filename, kRuntimeISA));
   std::string error_msg;
   UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL, false,
                                                   &error_msg));
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 7976f6a..46a4d53 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -33,17 +33,6 @@
 
 namespace art {
 
-std::string OatFile::DexFilenameToOdexFilename(const std::string& location) {
-  CHECK_GE(location.size(), 4U) << location;  // must be at least .123
-  size_t dot_index = location.size() - 3 - 1;  // 3=dex or zip or apk
-  CHECK_EQ('.', location[dot_index]) << location;
-  std::string odex_location(location);
-  odex_location.resize(dot_index + 1);
-  CHECK_EQ('.', odex_location[odex_location.size()-1]) << location << " " << odex_location;
-  odex_location += "odex";
-  return odex_location;
-}
-
 void OatFile::CheckLocation(const std::string& location) {
   CHECK(!location.empty());
 }
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index e5dc53c..07d70ff 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -37,10 +37,6 @@
 
 class OatFile {
  public:
-  // Returns an .odex file name next adjacent to the dex location.
-  // For example, for "/foo/bar/baz.jar", return "/foo/bar/baz.odex".
-  static std::string DexFilenameToOdexFilename(const std::string& location);
-
   // Open an oat file. Returns NULL on failure.  Requested base can
   // optionally be used to request where the file should be loaded.
   static OatFile* Open(const std::string& filename,
diff --git a/runtime/utils.cc b/runtime/utils.cc
index f26b598..e4af8e4 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1206,6 +1206,37 @@
   return StringPrintf("%s/%s", cache_location, cache_file.c_str());
 }
 
+static void InsertIsaDirectory(std::string* filename, const InstructionSet isa) {
+  // in = /foo/bar/baz
+  // out = /foo/bar/<isa>/baz
+  size_t pos = filename->rfind('/');
+  CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
+  filename->insert(pos, "/", 1);
+  filename->insert(pos + 1, GetInstructionSetString(isa));
+}
+
+std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
+  // location = /system/framework/boot.art
+  // filename = /system/framework/<isa>/boot.art
+  std::string filename(location);
+  InsertIsaDirectory(&filename, isa);
+  return filename;
+}
+
+std::string DexFilenameToOdexFilename(const std::string& location, const InstructionSet isa) {
+  // location = /foo/bar/baz.jar
+  // odex_location = /foo/bar/<isa>/baz.odex
+  CHECK_GE(location.size(), 4U) << location;  // must be at least .123
+  std::string odex_location(location);
+  InsertIsaDirectory(&odex_location, isa);
+  size_t dot_index = odex_location.size() - 3 - 1;  // 3=dex or zip or apk
+  CHECK_EQ('.', odex_location[dot_index]) << location;
+  odex_location.resize(dot_index + 1);
+  CHECK_EQ('.', odex_location[odex_location.size()-1]) << location << " " << odex_location;
+  odex_location += "odex";
+  return odex_location;
+}
+
 bool IsZipMagic(uint32_t magic) {
   return (('P' == ((magic >> 0) & 0xff)) &&
           ('K' == ((magic >> 8) & 0xff)));
diff --git a/runtime/utils.h b/runtime/utils.h
index 14a532e..9de5d23 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -25,6 +25,7 @@
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "globals.h"
+#include "instruction_set.h"
 #include "primitive.h"
 
 namespace art {
@@ -402,6 +403,13 @@
 std::string GetDalvikCacheFilenameOrDie(const char* file_location,
                                         const char* cache_location);
 
+// Returns the system location for an image
+std::string GetSystemImageFilename(const char* location, const InstructionSet isa);
+
+// Returns an .odex file name next adjacent to the dex location.
+// For example, for "/foo/bar/baz.jar", return "/foo/bar/<isa>/baz.odex".
+std::string DexFilenameToOdexFilename(const std::string& location, const InstructionSet isa);
+
 // Check whether the given magic matches a known file type.
 bool IsZipMagic(uint32_t magic);
 bool IsDexMagic(uint32_t magic);
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 8a8834d..4a1e477 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -351,6 +351,16 @@
                GetDalvikCacheFilenameOrDie("/system/framework/boot.art", "/foo").c_str());
 }
 
+TEST_F(UtilsTest, GetSystemImageFilename) {
+  EXPECT_STREQ("/system/framework/arm/boot.art",
+               GetSystemImageFilename("/system/framework/boot.art", kArm).c_str());
+}
+
+TEST_F(UtilsTest, DexFilenameToOdexFilename) {
+  EXPECT_STREQ("/foo/bar/arm/baz.odex",
+               DexFilenameToOdexFilename("/foo/bar/baz.jar", kArm).c_str());
+}
+
 TEST_F(UtilsTest, ExecSuccess) {
   std::vector<std::string> command;
   if (kIsTargetBuild) {