Merge "Set a default ACL on /data/media/userId."
diff --git a/Android.bp b/Android.bp
index fa8f249..f2a1a37 100644
--- a/Android.bp
+++ b/Android.bp
@@ -96,6 +96,9 @@
     whole_static_libs: [
         "libincremental_aidl-cpp",
     ],
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
 }
 
 cc_library_headers {
diff --git a/Benchmark.cpp b/Benchmark.cpp
index 0770da7..e81cd61 100644
--- a/Benchmark.cpp
+++ b/Benchmark.cpp
@@ -181,7 +181,10 @@
 void Benchmark(const std::string& path,
                const android::sp<android::os::IVoldTaskListener>& listener) {
     std::lock_guard<std::mutex> lock(kBenchmarkLock);
-    android::wakelock::WakeLock wl{kWakeLock};
+    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+    if (!wl.has_value()) {
+        return;
+    }
 
     PerformanceBoost boost;
     android::os::PersistableBundle extras;
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index c62eb25..a56d196 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -463,7 +463,6 @@
         return false;
     LOG(INFO) << "Wrote per boot key reference to:" << per_boot_ref_filename;
 
-    if (!android::vold::FsyncDirectory(device_key_dir)) return false;
     return true;
 }
 
@@ -653,18 +652,12 @@
         if (!android::vold::readSecdiscardable(secdiscardable_path, &secdiscardable_hash))
             return false;
     } else {
-        if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) {
-            PLOG(ERROR) << "Creating directories for: " << secdiscardable_path;
-            return false;
-        }
+        if (!android::vold::MkdirsSync(secdiscardable_path, 0700)) return false;
         if (!android::vold::createSecdiscardable(secdiscardable_path, &secdiscardable_hash))
             return false;
     }
     auto key_path = volkey_path(misc_path, volume_uuid);
-    if (fs_mkdirs(key_path.c_str(), 0700) != 0) {
-        PLOG(ERROR) << "Creating directories for: " << key_path;
-        return false;
-    }
+    if (!android::vold::MkdirsSync(key_path, 0700)) return false;
     android::vold::KeyAuthentication auth("", secdiscardable_hash);
 
     EncryptionOptions options;
@@ -705,7 +698,6 @@
     if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
     if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, store_auth, ce_key))
         return false;
-    if (!android::vold::FsyncDirectory(directory_path)) return false;
     return true;
 }
 
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 4c3041b..8005cf4 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -154,7 +154,10 @@
 }
 
 void Trim(const android::sp<android::os::IVoldTaskListener>& listener) {
-    android::wakelock::WakeLock wl{kWakeLock};
+    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+    if (!wl.has_value()) {
+        return;
+    }
 
     // Collect both fstab and vold volumes
     std::list<std::string> paths;
@@ -414,7 +417,10 @@
 
     LOG(DEBUG) << "idle maintenance started";
 
-    android::wakelock::WakeLock wl{kWakeLock};
+    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+    if (!wl.has_value()) {
+        return android::UNEXPECTED_NULL;
+    }
 
     std::list<std::string> paths;
     addFromFstab(&paths, PathTypes::kBlkDevice);
@@ -448,7 +454,10 @@
 }
 
 int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
-    android::wakelock::WakeLock wl{kWakeLock};
+    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+    if (!wl.has_value()) {
+        return android::UNEXPECTED_NULL;
+    }
 
     std::unique_lock<std::mutex> lk(cv_m);
     if (idle_maint_stat != IdleMaintStats::kStopped) {
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 89844aa..457bb66 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -606,10 +606,6 @@
     return true;
 }
 
-bool pathExists(const std::string& path) {
-    return access(path.c_str(), F_OK) == 0;
-}
-
 bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key) {
     if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), 0700)) == -1) {
         PLOG(ERROR) << "key mkdir " << dir;
@@ -665,6 +661,7 @@
         PLOG(ERROR) << "Unable to move new key to location: " << key_path;
         return false;
     }
+    if (!FsyncParentDirectory(key_path)) return false;
     LOG(DEBUG) << "Created key: " << key_path;
     return true;
 }
diff --git a/KeyStorage.h b/KeyStorage.h
index a69dbf7..5fded41 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -43,9 +43,6 @@
 
 extern const KeyAuthentication kEmptyAuthentication;
 
-// Checks if path "path" exists.
-bool pathExists(const std::string& path);
-
 bool createSecdiscardable(const std::string& path, std::string* hash);
 bool readSecdiscardable(const std::string& path, std::string* hash);
 
@@ -58,7 +55,8 @@
 // Create a directory at the named path, and store "key" in it as storeKey
 // This version creates the key in "tmp_path" then atomically renames "tmp_path"
 // to "key_path" thereby ensuring that the key is either stored entirely or
-// not at all.
+// not at all.  All the needed files and directories are also fsync'ed to ensure
+// that the key is actually persisted to disk.
 bool storeKeyAtomically(const std::string& key_path, const std::string& tmp_path,
                         const KeyAuthentication& auth, const KeyBuffer& key);
 
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 24c7476..dc50679 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -111,10 +111,7 @@
     std::string sKey;
     auto dir = metadata_key_dir + "/key";
     LOG(DEBUG) << "metadata_key_dir/key: " << dir;
-    if (fs_mkdirs(dir.c_str(), 0700)) {
-        PLOG(ERROR) << "Creating directories: " << dir;
-        return false;
-    }
+    if (!MkdirsSync(dir, 0700)) return false;
     auto temp = metadata_key_dir + "/tmp";
     return retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key);
 }
diff --git a/MoveStorage.cpp b/MoveStorage.cpp
index 3f636a2..54e28a9 100644
--- a/MoveStorage.cpp
+++ b/MoveStorage.cpp
@@ -256,7 +256,10 @@
 
 void MoveStorage(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
                  const android::sp<android::os::IVoldTaskListener>& listener) {
-    android::wakelock::WakeLock wl{kWakeLock};
+    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+    if (!wl.has_value()) {
+        return;
+    }
 
     android::os::PersistableBundle extras;
     status_t res = moveStorageInternal(from, to, listener);
diff --git a/Utils.cpp b/Utils.cpp
index 98797b2..cef0f39 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1349,6 +1349,10 @@
     return -1;
 }
 
+bool pathExists(const std::string& path) {
+    return access(path.c_str(), F_OK) == 0;
+}
+
 bool FsyncDirectory(const std::string& dirname) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_CLOEXEC)));
     if (fd == -1) {
@@ -1367,6 +1371,40 @@
     return true;
 }
 
+bool FsyncParentDirectory(const std::string& path) {
+    return FsyncDirectory(android::base::Dirname(path));
+}
+
+// Creates all parent directories of |path| that don't already exist.  Assigns
+// the specified |mode| to any new directories, and also fsync()s their parent
+// directories so that the new directories get written to disk right away.
+bool MkdirsSync(const std::string& path, mode_t mode) {
+    if (path[0] != '/') {
+        LOG(ERROR) << "MkdirsSync() needs an absolute path, but got " << path;
+        return false;
+    }
+    std::vector<std::string> components = android::base::Split(android::base::Dirname(path), "/");
+
+    std::string current_dir = "/";
+    for (const std::string& component : components) {
+        if (component.empty()) continue;
+
+        std::string parent_dir = current_dir;
+        if (current_dir != "/") current_dir += "/";
+        current_dir += component;
+
+        if (!pathExists(current_dir)) {
+            if (mkdir(current_dir.c_str(), mode) != 0) {
+                PLOG(ERROR) << "Failed to create " << current_dir;
+                return false;
+            }
+            if (!FsyncDirectory(parent_dir)) return false;
+            LOG(DEBUG) << "Created directory " << current_dir;
+        }
+    }
+    return true;
+}
+
 bool writeStringToFile(const std::string& payload, const std::string& filename) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(
         open(filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0666)));
diff --git a/Utils.h b/Utils.h
index a727e63..4771593 100644
--- a/Utils.h
+++ b/Utils.h
@@ -179,8 +179,14 @@
 
 status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout);
 
+bool pathExists(const std::string& path);
+
 bool FsyncDirectory(const std::string& dirname);
 
+bool FsyncParentDirectory(const std::string& path);
+
+bool MkdirsSync(const std::string& path, mode_t mode);
+
 bool writeStringToFile(const std::string& payload, const std::string& filename);
 
 void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio);
diff --git a/cryptfs.cpp b/cryptfs.cpp
index faed65b..6203003 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -2083,7 +2083,16 @@
     int num_vols;
     bool rebootEncryption = false;
     bool onlyCreateHeader = false;
-    std::unique_ptr<android::wakelock::WakeLock> wakeLock = nullptr;
+
+    /* Get a wakelock as this may take a while, and we don't want the
+     * device to sleep on us.  We'll grab a partial wakelock, and if the UI
+     * wants to keep the screen on, it can grab a full wakelock.
+     */
+    snprintf(lockid, sizeof(lockid), "enablecrypto%d", (int)getpid());
+    auto wl = android::wakelock::WakeLock::tryGet(lockid);
+    if (!wl.has_value()) {
+        return android::UNEXPECTED_NULL;
+    }
 
     if (get_crypt_ftr_and_key(&crypt_ftr) == 0) {
         if (crypt_ftr.flags & CRYPT_FORCE_ENCRYPTION) {
@@ -2132,13 +2141,6 @@
         }
     }
 
-    /* Get a wakelock as this may take a while, and we don't want the
-     * device to sleep on us.  We'll grab a partial wakelock, and if the UI
-     * wants to keep the screen on, it can grab a full wakelock.
-     */
-    snprintf(lockid, sizeof(lockid), "enablecrypto%d", (int)getpid());
-    wakeLock = std::make_unique<android::wakelock::WakeLock>(lockid);
-
     /* The init files are setup to stop the class main and late start when
      * vold sets trigger_shutdown_framework.
      */
@@ -2291,7 +2293,7 @@
             /* default encryption - continue first boot sequence */
             property_set("ro.crypto.state", "encrypted");
             property_set("ro.crypto.type", "block");
-            wakeLock.reset(nullptr);
+            wl.reset();
             if (rebootEncryption && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
                 // Bring up cryptkeeper that will check the password and set it
                 property_set("vold.decrypt", "trigger_shutdown_framework");
diff --git a/tests/Utils_test.cpp b/tests/Utils_test.cpp
index d18dc67..35b40cd 100644
--- a/tests/Utils_test.cpp
+++ b/tests/Utils_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/file.h>
 #include <gtest/gtest.h>
 
 #include "../Utils.h"
@@ -43,5 +44,23 @@
     ASSERT_EQ("QUUX", tmp);
 }
 
+TEST_F(UtilsTest, MkdirsSyncTest) {
+    TemporaryDir temp_dir;
+    std::string temp_dir_path;
+
+    ASSERT_TRUE(android::base::Realpath(temp_dir.path, &temp_dir_path));
+
+    ASSERT_FALSE(pathExists(temp_dir_path + "/a"));
+    ASSERT_TRUE(MkdirsSync(temp_dir_path + "/a/b/c", 0700));
+    ASSERT_TRUE(pathExists(temp_dir_path + "/a"));
+    ASSERT_TRUE(pathExists(temp_dir_path + "/a/b"));
+    // The final component of the path should not be created; only the previous
+    // components should be.
+    ASSERT_FALSE(pathExists(temp_dir_path + "/a/b/c"));
+
+    // Currently, MkdirsSync() only supports absolute paths.
+    ASSERT_FALSE(MkdirsSync("foo", 0700));
+}
+
 }  // namespace vold
 }  // namespace android