Revert^2 "Avoid crash when ANDROID_DATA is not writeable."

This reverts commit c702e34372e7120d3b99a42d9a226c6c036b5d17.

Fix the new test when running as root. Instead of relying on
directory permissions (which are ignored for root), create
a dummy file "dalvik-cache" to prevent the creation of the
directory "dalvik-cache/<isa>".

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: m test-art-target-gtest
Bug: 112848347
Bug: 112827048
Change-Id: I0fad66c876c5dd062a38aacc15cdd21c374cc96f
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index eebb103..2a4803a 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1454,6 +1454,7 @@
         has_system_(false),
         has_cache_(false),
         is_global_cache_(true),
+        dalvik_cache_exists_(false),
         dalvik_cache_(),
         cache_filename_() {
   }
@@ -1462,33 +1463,30 @@
 
   void FindImageFiles() {
     std::string system_filename;
-    bool dalvik_cache_exists = false;
     bool found_image = FindImageFilenameImpl(image_location_.c_str(),
                                              image_isa_,
                                              &has_system_,
                                              &system_filename,
-                                             &dalvik_cache_exists,
+                                             &dalvik_cache_exists_,
                                              &dalvik_cache_,
                                              &is_global_cache_,
                                              &has_cache_,
                                              &cache_filename_);
-    DCHECK_EQ(dalvik_cache_exists, !dalvik_cache_.empty());
+    DCHECK(!dalvik_cache_exists_ || !dalvik_cache_.empty());
     DCHECK_EQ(found_image, has_system_ || has_cache_);
   }
 
   bool HasSystem() const { return has_system_; }
   bool HasCache() const { return has_cache_; }
 
-  bool DalvikCacheExists() const { return !dalvik_cache_.empty(); }
+  bool DalvikCacheExists() const { return dalvik_cache_exists_; }
   bool IsGlobalCache() const { return is_global_cache_; }
 
   const std::string& GetDalvikCache() const {
-    DCHECK(DalvikCacheExists());
     return dalvik_cache_;
   }
 
   const std::string& GetCacheFilename() const {
-    DCHECK(DalvikCacheExists());
     return cache_filename_;
   }
 
@@ -1617,6 +1615,7 @@
   bool has_system_;
   bool has_cache_;
   bool is_global_cache_;
+  bool dalvik_cache_exists_;
   std::string dalvik_cache_;
   std::string cache_filename_;
 };
@@ -1769,7 +1768,7 @@
 
   // Step 3: We do not have an existing image in /system,
   //         so generate an image into the dalvik cache.
-  if (!loader.HasSystem()) {
+  if (!loader.HasSystem() && loader.DalvikCacheExists()) {
     std::string local_error_msg;
     if (!dex2oat_enabled) {
       local_error_msg = "Image compilation disabled.";
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index f202a43..a1ffa06 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -150,6 +150,48 @@
   EXPECT_FALSE(Runtime::Current()->GetHeap()->GetBootImageSpaces().empty());
 }
 
+class NoAccessAndroidDataTest : public ImageSpaceLoadingTest<false, true, false, true> {
+ protected:
+  void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
+    const char* android_data = getenv("ANDROID_DATA");
+    CHECK(android_data != nullptr);
+    old_android_data_ = android_data;
+    bad_android_data_ = old_android_data_ + "/no-android-data";
+    int result = setenv("ANDROID_DATA", bad_android_data_.c_str(), /* replace */ 1);
+    CHECK_EQ(result, 0) << strerror(errno);
+    result = mkdir(bad_android_data_.c_str(), /* mode */ 0700);
+    CHECK_EQ(result, 0) << strerror(errno);
+    // Create a regular file "dalvik_cache". GetDalvikCache() shall get EEXIST
+    // when trying to create a directory with the same name and creating a
+    // subdirectory for a particular architecture shall fail.
+    bad_dalvik_cache_ = bad_android_data_ + "/dalvik-cache";
+    int fd = creat(bad_dalvik_cache_.c_str(), /* mode */ 0);
+    CHECK_NE(fd, -1) << strerror(errno);
+    result = close(fd);
+    CHECK_EQ(result, 0) << strerror(errno);
+    ImageSpaceLoadingTest<false, true, false, true>::SetUpRuntimeOptions(options);
+  }
+
+  void TearDown() OVERRIDE {
+    int result = unlink(bad_dalvik_cache_.c_str());
+    CHECK_EQ(result, 0) << strerror(errno);
+    result = rmdir(bad_android_data_.c_str());
+    CHECK_EQ(result, 0) << strerror(errno);
+    result = setenv("ANDROID_DATA", old_android_data_.c_str(), /* replace */ 1);
+    CHECK_EQ(result, 0) << strerror(errno);
+    ImageSpaceLoadingTest<false, true, false, true>::TearDown();
+  }
+
+ private:
+  std::string old_android_data_;
+  std::string bad_android_data_;
+  std::string bad_dalvik_cache_;
+};
+
+TEST_F(NoAccessAndroidDataTest, Test) {
+  EXPECT_TRUE(Runtime::Current()->GetHeap()->GetBootImageSpaces().empty());
+}
+
 }  // namespace space
 }  // namespace gc
 }  // namespace art