Create /data/vendor_ce/0/facedata in vold_prepare_subdirs
am: b409ade4d7

Change-Id: I6b3a1624a1bfc0053c75f842a1c6f219071a3fb5
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 19c1f3c..ba9af11 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -61,6 +61,16 @@
 namespace {
 const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
 
+binder::Status error(const std::string& msg) {
+    PLOG(ERROR) << msg;
+    return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
+}
+
+binder::Status error(int error, const std::string& msg) {
+    LOG(ERROR) << msg;
+    return binder::Status::fromServiceSpecificError(error, String8(msg.c_str()));
+}
+
 bool setBowState(std::string const& block_device, std::string const& state) {
     if (block_device.substr(0, 5) != "/dev/") {
         LOG(ERROR) << "Expected block device, got " << block_device;
@@ -115,7 +125,7 @@
 }
 
 Status cp_startCheckpoint(int retry) {
-    if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
+    if (retry < -1) return error(EINVAL, "Retry count must be more than -1");
     std::string content = std::to_string(retry + 1);
     if (retry == -1) {
         sp<IBootControl> module = IBootControl::getService();
@@ -126,7 +136,7 @@
         }
     }
     if (!android::base::WriteStringToFile(content, kMetadataCPFile))
-        return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
+        return error("Failed to write checkpoint file");
     return Status::ok();
 }
 
@@ -143,10 +153,8 @@
     if (module) {
         CommandResult cr;
         module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
-        if (!cr.success) {
-            std::string msg = "Error marking booted successfully: " + std::string(cr.errMsg);
-            return Status::fromExceptionCode(EINVAL, String8(msg.c_str()));
-        }
+        if (!cr.success)
+            return error(EINVAL, "Error marking booted successfully: " + std::string(cr.errMsg));
         LOG(INFO) << "Marked slot as booted successfully.";
     }
     // Must take action for list of mounted checkpointed things here
@@ -157,7 +165,7 @@
 
     Fstab mounts;
     if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
-        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
+        return error(EINVAL, "Failed to get /proc/mounts");
     }
 
     // Walk mounted file systems
@@ -170,19 +178,20 @@
                 std::string options = mount_rec.fs_options + ",checkpoint=enable";
                 if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
                           MS_REMOUNT | fstab_rec->flags, options.c_str())) {
-                    return Status::fromExceptionCode(EINVAL, "Failed to remount");
+                    return error(EINVAL, "Failed to remount");
                 }
             }
         } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
             if (!setBowState(mount_rec.blk_device, "2"))
-                return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
+                return error(EINVAL, "Failed to set bow state");
         }
     }
     SetProperty("vold.checkpoint_committed", "1");
     LOG(INFO) << "Checkpoint has been committed.";
     isCheckpointing = false;
     if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
-        return Status::fromExceptionCode(errno, err_str.c_str());
+        return error(err_str.c_str());
+
     return Status::ok();
 }
 
@@ -321,7 +330,7 @@
 
     Fstab mounts;
     if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
-        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
+        return error(EINVAL, "Failed to get /proc/mounts");
     }
 
     for (const auto& mount_rec : mounts) {
@@ -581,10 +590,7 @@
 
         LOG(INFO) << action << " checkpoint on " << blockDevice;
         base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR | O_CLOEXEC));
-        if (device_fd < 0) {
-            PLOG(ERROR) << "Cannot open " << blockDevice;
-            return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
-        }
+        if (device_fd < 0) return error("Cannot open " + blockDevice);
 
         log_sector_v1_0 original_ls;
         read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
@@ -592,8 +598,7 @@
             validating = false;
             action = "Restoring";
         } else if (original_ls.magic != kMagic) {
-            LOG(ERROR) << "No magic";
-            return Status::fromExceptionCode(EINVAL, "No magic");
+            return error(EINVAL, "No magic");
         }
 
         LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
@@ -607,23 +612,18 @@
             used_sectors[0] = false;
 
             if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
-                LOG(ERROR) << "No magic!";
-                status = Status::fromExceptionCode(EINVAL, "No magic");
+                status = error(EINVAL, "No magic");
                 break;
             }
 
             if (ls.block_size != original_ls.block_size) {
-                LOG(ERROR) << "Block size mismatch!";
-                status = Status::fromExceptionCode(EINVAL, "Block size mismatch");
+                status = error(EINVAL, "Block size mismatch");
                 break;
             }
 
             if ((int)ls.sequence != sequence) {
-                LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
-                status = Status::fromExceptionCode(
-                    EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
-                             std::to_string(ls.sequence))
-                                .c_str());
+                status = error(EINVAL, "Expecting log sector " + std::to_string(sequence) +
+                                           " but got " + std::to_string(ls.sequence));
                 break;
             }
 
@@ -644,8 +644,7 @@
                 }
 
                 if (le->checksum && checksum != le->checksum) {
-                    LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
-                    status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
+                    status = error(EINVAL, "Checksums don't match");
                     break;
                 }
 
@@ -655,8 +654,7 @@
                     restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
                     restore_count++;
                     if (restore_limit && restore_count >= restore_limit) {
-                        LOG(WARNING) << "Hit the test limit";
-                        status = Status::fromExceptionCode(EAGAIN, "Hit the test limit");
+                        status = error(EAGAIN, "Hit the test limit");
                         break;
                     }
                 }
@@ -694,20 +692,18 @@
 
     // If the file doesn't exist, we aren't managing a checkpoint retry counter
     if (result != 0) return Status::ok();
-    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
-        PLOG(ERROR) << "Failed to read checkpoint file";
-        return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
-    }
+    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent))
+        return error("Failed to read checkpoint file");
     std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
 
     if (!android::base::ParseInt(retryContent, &retry))
-        return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
+        return error(EINVAL, "Could not parse retry count");
     if (retry > 0) {
         retry--;
 
         newContent = std::to_string(retry);
         if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
-            return Status::fromExceptionCode(errno, "Could not write checkpoint file");
+            return error("Could not write checkpoint file");
     }
     return Status::ok();
 }
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index b7d3928..c3c9fef 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -411,11 +411,18 @@
     return true;
 }
 
+// "Lock" all encrypted directories whose key has been removed.  This is needed
+// because merely removing the keyring key doesn't affect inodes in the kernel's
+// inode cache whose per-file key was already set up.  So to remove the per-file
+// keys and make the files "appear encrypted", these inodes must be evicted.
+//
+// To do this, sync() to clean all dirty inodes, then drop all reclaimable slab
+// objects systemwide.  This is overkill, but it's the best available method
+// currently.  Don't use drop_caches mode "3" because that also evicts pagecache
+// for in-use files; all files relevant here are already closed and sync'ed.
 static void drop_caches() {
-    // Clean any dirty pages (otherwise they won't be dropped).
     sync();
-    // Drop inode and page caches.
-    if (!writeStringToFile("3", "/proc/sys/vm/drop_caches")) {
+    if (!writeStringToFile("2", "/proc/sys/vm/drop_caches")) {
         PLOG(ERROR) << "Failed to drop caches during key eviction";
     }
 }
diff --git a/Utils.cpp b/Utils.cpp
index df50658..1616d80 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -43,6 +43,7 @@
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <list>
 #include <mutex>
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 400a616..dc3a26c 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -2253,6 +2253,7 @@
          * /data, set a property saying we're doing inplace encryption,
          * and restart the framework.
          */
+        wait_and_unmount(DATA_MNT_POINT, true);
         if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
             goto error_shutting_down;
         }
diff --git a/main.cpp b/main.cpp
index 27a701b..7555276 100644
--- a/main.cpp
+++ b/main.cpp
@@ -152,6 +152,7 @@
         {"blkid_untrusted_context", required_argument, 0, 'B'},
         {"fsck_context", required_argument, 0, 'f'},
         {"fsck_untrusted_context", required_argument, 0, 'F'},
+        {nullptr, 0, nullptr, 0},
     };
 
     int c;
diff --git a/vdc.cpp b/vdc.cpp
index 76eca3e..6136413 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -32,6 +32,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <binder/IServiceManager.h>
 #include <binder/Status.h>
@@ -55,9 +56,10 @@
     return res;
 }
 
-static void checkStatus(android::binder::Status status) {
+static void checkStatus(std::vector<std::string>& cmd, android::binder::Status status) {
     if (status.isOk()) return;
-    LOG(ERROR) << "Failed: " << status.toString8().string();
+    std::string command = ::android::base::Join(cmd, " ");
+    LOG(ERROR) << "Command: " << command << " Failed: " << status.toString8().string();
     exit(ENOTTY);
 }
 
@@ -88,63 +90,63 @@
     auto vold = android::interface_cast<android::os::IVold>(binder);
 
     if (args[0] == "cryptfs" && args[1] == "enablefilecrypto") {
-        checkStatus(vold->fbeEnable());
+        checkStatus(args, vold->fbeEnable());
     } else if (args[0] == "cryptfs" && args[1] == "init_user0") {
-        checkStatus(vold->initUser0());
+        checkStatus(args, vold->initUser0());
     } else if (args[0] == "cryptfs" && args[1] == "enablecrypto") {
         int passwordType = android::os::IVold::PASSWORD_TYPE_DEFAULT;
         int encryptionFlags = android::os::IVold::ENCRYPTION_FLAG_NO_UI;
-        checkStatus(vold->fdeEnable(passwordType, "", encryptionFlags));
+        checkStatus(args, vold->fdeEnable(passwordType, "", encryptionFlags));
     } else if (args[0] == "cryptfs" && args[1] == "mountdefaultencrypted") {
-        checkStatus(vold->mountDefaultEncrypted());
+        checkStatus(args, vold->mountDefaultEncrypted());
     } else if (args[0] == "volume" && args[1] == "shutdown") {
-        checkStatus(vold->shutdown());
+        checkStatus(args, vold->shutdown());
     } else if (args[0] == "cryptfs" && args[1] == "checkEncryption" && args.size() == 3) {
-        checkStatus(vold->checkEncryption(args[2]));
+        checkStatus(args, vold->checkEncryption(args[2]));
     } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 3) {
-        checkStatus(vold->mountFstab(args[2]));
+        checkStatus(args, vold->mountFstab(args[2]));
     } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 3) {
-        checkStatus(vold->encryptFstab(args[2]));
+        checkStatus(args, vold->encryptFstab(args[2]));
     } else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) {
         bool supported = false;
-        checkStatus(vold->supportsCheckpoint(&supported));
+        checkStatus(args, vold->supportsCheckpoint(&supported));
         return supported ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "supportsBlockCheckpoint" && args.size() == 2) {
         bool supported = false;
-        checkStatus(vold->supportsBlockCheckpoint(&supported));
+        checkStatus(args, vold->supportsBlockCheckpoint(&supported));
         return supported ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "supportsFileCheckpoint" && args.size() == 2) {
         bool supported = false;
-        checkStatus(vold->supportsFileCheckpoint(&supported));
+        checkStatus(args, vold->supportsFileCheckpoint(&supported));
         return supported ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "startCheckpoint" && args.size() == 3) {
         int retry;
         if (!android::base::ParseInt(args[2], &retry)) exit(EINVAL);
-        checkStatus(vold->startCheckpoint(retry));
+        checkStatus(args, vold->startCheckpoint(retry));
     } else if (args[0] == "checkpoint" && args[1] == "needsCheckpoint" && args.size() == 2) {
         bool enabled = false;
-        checkStatus(vold->needsCheckpoint(&enabled));
+        checkStatus(args, vold->needsCheckpoint(&enabled));
         return enabled ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "needsRollback" && args.size() == 2) {
         bool enabled = false;
-        checkStatus(vold->needsRollback(&enabled));
+        checkStatus(args, vold->needsRollback(&enabled));
         return enabled ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "commitChanges" && args.size() == 2) {
-        checkStatus(vold->commitChanges());
+        checkStatus(args, vold->commitChanges());
     } else if (args[0] == "checkpoint" && args[1] == "prepareCheckpoint" && args.size() == 2) {
-        checkStatus(vold->prepareCheckpoint());
+        checkStatus(args, vold->prepareCheckpoint());
     } else if (args[0] == "checkpoint" && args[1] == "restoreCheckpoint" && args.size() == 3) {
-        checkStatus(vold->restoreCheckpoint(args[2]));
+        checkStatus(args, vold->restoreCheckpoint(args[2]));
     } else if (args[0] == "checkpoint" && args[1] == "restoreCheckpointPart" && args.size() == 4) {
         int count;
         if (!android::base::ParseInt(args[3], &count)) exit(EINVAL);
-        checkStatus(vold->restoreCheckpointPart(args[2], count));
+        checkStatus(args, vold->restoreCheckpointPart(args[2], count));
     } else if (args[0] == "checkpoint" && args[1] == "markBootAttempt" && args.size() == 2) {
-        checkStatus(vold->markBootAttempt());
+        checkStatus(args, vold->markBootAttempt());
     } else if (args[0] == "checkpoint" && args[1] == "abortChanges" && args.size() == 4) {
         int retry;
         if (!android::base::ParseInt(args[2], &retry)) exit(EINVAL);
-        checkStatus(vold->abortChanges(args[2], retry != 0));
+        checkStatus(args, vold->abortChanges(args[2], retry != 0));
     } else {
         LOG(ERROR) << "Raw commands are no longer supported";
         exit(EINVAL);