Merge "Set a default ACL on /data/media/userId."
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index be51963..c62eb25 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -795,11 +795,6 @@
 
 static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid,
                             userid_t user_id, int flags) {
-    // TODO(b/141677108): Remove this & make it the default behavior
-    if (android::base::GetProperty("ro.vold.level_from_user", "1") == "1") {
-        flags |= android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER;
-    }
-
     if (0 != android::vold::ForkExecvp(
                  std::vector<std::string>{prepare_subdirs_path, action, volume_uuid,
                                           std::to_string(user_id), std::to_string(flags)})) {
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index cf7c5f7..24c7476 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -41,6 +41,8 @@
 #include "Keymaster.h"
 #include "Utils.h"
 #include "VoldUtil.h"
+#include "fs/Ext4.h"
+#include "fs/F2fs.h"
 
 namespace android {
 namespace vold {
@@ -202,8 +204,11 @@
 }
 
 bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
-                                      bool needs_encrypt) {
-    LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt;
+                                      bool needs_encrypt, bool should_format,
+                                      const std::string& fs_type) {
+    LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point
+               << " encrypt: " << needs_encrypt << " format: " << should_format << " with "
+               << fs_type;
     auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
     if (encrypted_state != "" && encrypted_state != "encrypted") {
         LOG(DEBUG) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
@@ -250,8 +255,24 @@
     if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, &nr_sec))
         return false;
 
-    // FIXME handle the corrupt case
-    if (needs_encrypt && !encrypt_inplace(crypto_blkdev, blk_device, nr_sec, false)) return false;
+    if (needs_encrypt) {
+        if (should_format) {
+            status_t error;
+
+            if (fs_type == "ext4") {
+                error = ext4::Format(crypto_blkdev, 0, mount_point);
+            } else if (fs_type == "f2fs") {
+                error = f2fs::Format(crypto_blkdev);
+            } else {
+                LOG(ERROR) << "Unknown filesystem type: " << fs_type;
+                return false;
+            }
+            LOG(DEBUG) << "Format (err=" << error << ") " << crypto_blkdev << " on " << mount_point;
+            if (error != 0) return false;
+        } else {
+            if (!encrypt_inplace(crypto_blkdev, blk_device, nr_sec, false)) return false;
+        }
+    }
 
     LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point;
     mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str());
diff --git a/MetadataCrypt.h b/MetadataCrypt.h
index 7341a08..e482765 100644
--- a/MetadataCrypt.h
+++ b/MetadataCrypt.h
@@ -26,7 +26,8 @@
 namespace vold {
 
 bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
-                                      const std::string& mount_point, bool needs_encrypt);
+                                      const std::string& mount_point, bool needs_encrypt,
+                                      bool should_format, const std::string& fs_type);
 
 bool defaultkey_volume_keygen(KeyGeneration* gen);
 
diff --git a/Utils.h b/Utils.h
index 8975adc..a727e63 100644
--- a/Utils.h
+++ b/Utils.h
@@ -34,7 +34,6 @@
 namespace android {
 namespace vold {
 
-static const char* kPropFuse = "persist.sys.fuse";
 static const char* kVoldAppDataIsolationEnabled = "persist.sys.vold_app_data_isolation_enabled";
 static const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled";
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 674a721..9f4f7b0 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -282,12 +282,6 @@
         return translate(res);
     }
 
-    if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
-        res = VolumeManager::Instance()->setPrimary(vol);
-        if (res != OK) {
-            return translate(res);
-        }
-    }
     return translate(OK);
 }
 
@@ -383,7 +377,17 @@
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_LOCK;
 
-    return translate(VolumeManager::Instance()->remountAppStorageDirs(uid, pid, packageNames));
+    return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+            false /* doUnmount */, packageNames));
+}
+
+binder::Status VoldNativeService::unmountAppStorageDirs(int uid, int pid,
+        const std::vector<std::string>& packageNames) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_LOCK;
+
+    return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+            true /* doUnmount */, packageNames));
 }
 
 binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t appUid) {
@@ -394,6 +398,14 @@
     return translate(VolumeManager::Instance()->setupAppDir(path, appUid));
 }
 
+binder::Status VoldNativeService::ensureAppDirsCreated(const std::vector<std::string>& paths,
+        int32_t appUid) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_LOCK;
+
+    return translate(VolumeManager::Instance()->ensureAppDirsCreated(paths, appUid));
+}
+
 binder::Status VoldNativeService::fixupAppDir(const std::string& path, int32_t appUid) {
     ENFORCE_SYSTEM_OR_ROOT;
     CHECK_ARGUMENT_PATH(path);
@@ -673,15 +685,18 @@
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_LOCK;
 
-    return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false));
+    return translateBool(
+            fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false, false, "null"));
 }
 
 binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice,
-                                               const std::string& mountPoint) {
+                                               const std::string& mountPoint, bool shouldFormat,
+                                               const std::string& fsType) {
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_LOCK;
 
-    return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true));
+    return translateBool(
+            fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, fsType));
 }
 
 binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial,
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 390e9fc..47991c2 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -66,7 +66,10 @@
     binder::Status remountUid(int32_t uid, int32_t remountMode);
     binder::Status remountAppStorageDirs(int uid, int pid,
                                const std::vector<std::string>& packageNames);
+    binder::Status unmountAppStorageDirs(int uid, int pid,
+                               const std::vector<std::string>& packageNames);
 
+    binder::Status ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid);
     binder::Status setupAppDir(const std::string& path, int32_t appUid);
     binder::Status fixupAppDir(const std::string& path, int32_t appUid);
 
@@ -110,7 +113,8 @@
     binder::Status initUser0();
     binder::Status isConvertibleToFbe(bool* _aidl_return);
     binder::Status mountFstab(const std::string& blkDevice, const std::string& mountPoint);
-    binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint);
+    binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint,
+                                bool shouldFormat, const std::string& fsType);
 
     binder::Status createUserKey(int32_t userId, int32_t userSerial, bool ephemeral);
     binder::Status destroyUserKey(int32_t userId);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index f0fc388..ac7356c 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -369,21 +369,6 @@
     return success ? 0 : -1;
 }
 
-int VolumeManager::linkPrimary(userid_t userId) {
-    if (!GetBoolProperty(android::vold::kPropFuse, false)) {
-        std::string source(mPrimary->getPath());
-        if (mPrimary->isEmulated()) {
-            source = StringPrintf("%s/%d", source.c_str(), userId);
-            fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
-        }
-
-        std::string target(StringPrintf("/mnt/user/%d/primary", userId));
-        LOG(DEBUG) << "Linking " << source << " to " << target;
-        Symlink(source, target);
-    }
-    return 0;
-}
-
 void VolumeManager::destroyEmulatedVolumesForUser(userid_t userId) {
     // Destroy and remove all unstacked EmulatedVolumes for the user
     auto i = mInternalEmulatedVolumes.begin();
@@ -464,18 +449,6 @@
         createEmulatedVolumesForUser(userId);
     }
 
-    if (!GetBoolProperty(android::vold::kPropFuse, false)) {
-        // Note that sometimes the system will spin up processes from Zygote
-        // before actually starting the user, so we're okay if Zygote
-        // already created this directory.
-        std::string path(StringPrintf("%s/%d", kPathUserMount, userId));
-        fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
-
-        if (mPrimary) {
-            linkPrimary(userId);
-        }
-    }
-
     mStartedUsers.insert(userId);
 
     createPendingDisksIfNeeded();
@@ -512,14 +485,6 @@
     return 0;
 }
 
-int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
-    mPrimary = vol;
-    for (userid_t userId : mStartedUsers) {
-        linkPrimary(userId);
-    }
-    return 0;
-}
-
 // This code is executed after a fork so it's very important that the set of
 // methods we call here is strictly limited.
 //
@@ -718,15 +683,42 @@
     return true;
 }
 
-int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
-    if (GetBoolProperty(android::vold::kPropFuse, false)) {
-        // TODO(135341433): Implement fuse specific logic.
-        return 0;
+// In each app's namespace, unmount obb and data dirs
+static bool umountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir,
+        int uid, const char* targets[], int size) {
+    // This code is executed after a fork so it's very important that the set of
+    // methods we call here is strictly limited.
+    if (setns(nsFd, CLONE_NEWNS) != 0) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to setns %s", strerror(errno));
+        return false;
     }
-    return scanProcProcesses(uid, static_cast<userid_t>(-1),
-            forkAndRemountChild, &mountMode) ? 0 : -1;
-}
 
+    // Unmount of Android/data/foo needs to be done before Android/data below.
+    bool result = true;
+    for (int i = 0; i < size; i++) {
+        if (TEMP_FAILURE_RETRY(umount2(targets[i], MNT_DETACH)) < 0 && errno != EINVAL &&
+                errno != ENOENT) {
+            async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s: %s",
+                                  targets[i], strerror(errno));
+            result = false;
+        }
+    }
+
+    // Mount tmpfs on Android/data and Android/obb
+    if (TEMP_FAILURE_RETRY(umount2(android_data_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+                errno != ENOENT) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+                        android_data_dir, strerror(errno));
+        result = false;
+    }
+    if (TEMP_FAILURE_RETRY(umount2(android_obb_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+                errno != ENOENT) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+                android_obb_dir, strerror(errno));
+        result = false;
+    }
+    return result;
+}
 
 // In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data
 // package dirs.
@@ -786,8 +778,8 @@
             userId, dirName.c_str(), packageName.c_str());
 }
 
-// Fork the process and remount storage
-bool VolumeManager::forkAndRemountStorage(int uid, int pid,
+// Fork the process and remount / unmount app data and obb dirs
+bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool doUnmount,
                                           const std::vector<std::string>& packageNames) {
     userid_t userId = multiuser_get_user_id(uid);
     std::string mnt_path = StringPrintf("/proc/%d/ns/mnt", pid);
@@ -843,11 +835,20 @@
     // Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect
     // original vold process mount namespace.
     if (!(child = fork())) {
-        if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
-                sources_cstr, targets_cstr, size)) {
-            _exit(0);
+        if (doUnmount) {
+            if (umountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+                    targets_cstr, size)) {
+                _exit(0);
+            } else {
+                _exit(1);
+            }
         } else {
-            _exit(1);
+            if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+                    sources_cstr, targets_cstr, size)) {
+                _exit(0);
+            } else {
+                _exit(1);
+            }
         }
     }
 
@@ -872,11 +873,8 @@
     return true;
 }
 
-int VolumeManager::remountAppStorageDirs(int uid, int pid,
-        const std::vector<std::string>& packageNames) {
-    if (!GetBoolProperty(android::vold::kPropFuse, false)) {
-        return 0;
-    }
+int VolumeManager::handleAppStorageDirs(int uid, int pid,
+        bool doUnmount, const std::vector<std::string>& packageNames) {
     // Only run the remount if fuse is mounted for that user.
     userid_t userId = multiuser_get_user_id(uid);
     bool fuseMounted = false;
@@ -890,7 +888,7 @@
         }
     }
     if (fuseMounted) {
-        forkAndRemountStorage(uid, pid, packageNames);
+        forkAndRemountStorage(uid, pid, doUnmount, packageNames);
     }
     return 0;
 }
@@ -984,7 +982,20 @@
     return 0;
 }
 
-int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly) {
+int VolumeManager::ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid) {
+    int size = paths.size();
+    for (int i = 0; i < size; i++) {
+        int result = setupAppDir(paths[i], appUid, false /* fixupExistingOnly */,
+                true /* skipIfDirExists */);
+        if (result != OK) {
+            return result;
+        }
+    }
+    return OK;
+}
+
+int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly,
+        bool skipIfDirExists) {
     // Only offer to create directories for paths managed by vold
     if (!StartsWith(path, "/storage/")) {
         LOG(ERROR) << "Failed to find mounted volume for " << path;
@@ -1029,11 +1040,18 @@
 
     const std::string volumeRoot = volume->getRootPath();  // eg /data/media/0
 
-    if (fixupExistingOnly && (access(lowerPath.c_str(), F_OK) != 0)) {
+    const int access_result = access(lowerPath.c_str(), F_OK);
+    if (fixupExistingOnly && access_result != 0) {
         // Nothing to fixup
         return OK;
     }
 
+    if (skipIfDirExists && access_result == 0) {
+        // It's safe to assume it's ok as it will be used for zygote to bind mount dir only,
+        // which the dir doesn't need to have correct permission for now yet.
+        return OK;
+    }
+
     if (volume->getType() == VolumeBase::Type::kPublic) {
         // On public volumes, we don't need to setup permissions, as everything goes through
         // FUSE; just create the dirs and be done with it.
@@ -1120,9 +1138,14 @@
     auto vol = std::shared_ptr<android::vold::StubVolume>(
             new android::vold::StubVolume(stubId, sourcePath, mountPath, fsType, fsUuid, fsLabel));
 
-    int32_t passedFlags = android::vold::Disk::Flags::kStub;
+    int32_t passedFlags = 0;
     passedFlags |= (flags & android::vold::Disk::Flags::kUsb);
     passedFlags |= (flags & android::vold::Disk::Flags::kSd);
+    if (flags & android::vold::Disk::Flags::kStubVisible) {
+        passedFlags |= (flags & android::vold::Disk::Flags::kStubVisible);
+    } else {
+        passedFlags |= (flags & android::vold::Disk::Flags::kStubInvisible);
+    }
     // StubDisk doesn't have device node corresponds to it. So, a fake device
     // number is used.
     auto disk = std::shared_ptr<android::vold::Disk>(
diff --git a/VolumeManager.h b/VolumeManager.h
index 54a2443..3573b1a 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -114,10 +114,9 @@
     void createPendingDisksIfNeeded();
     int onSecureKeyguardStateChanged(bool isShowing);
 
-    int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
-
-    int remountUid(uid_t uid, int32_t remountMode);
-    int remountAppStorageDirs(int uid, int pid, const std::vector<std::string>& packageNames);
+    int remountUid(uid_t uid, int32_t remountMode) { return 0; }
+    int handleAppStorageDirs(int uid, int pid,
+            bool doUnmount, const std::vector<std::string>& packageNames);
 
     /* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */
     int abortFuse();
@@ -131,7 +130,8 @@
     int updateVirtualDisk();
     int setDebug(bool enable);
 
-    bool forkAndRemountStorage(int uid, int pid, const std::vector<std::string>& packageNames);
+    bool forkAndRemountStorage(int uid, int pid, bool doUnmount,
+        const std::vector<std::string>& packageNames);
 
     static VolumeManager* Instance();
 
@@ -165,12 +165,16 @@
      * files in the passed in path, but only if that path exists; if it doesn't
      * exist, this function doesn't create them.
      *
+     * If skipIfDirExists is set, we will not fix any existing dirs, we will
+     * only create app dirs if it doesn't exist.
+     *
      * Validates that given paths are absolute and that they contain no relative
      * "." or ".." paths or symlinks.  Last path segment is treated as filename
      * and ignored, unless the path ends with "/".  Also ensures that path
      * belongs to a volume managed by vold.
      */
-    int setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly = false);
+    int setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly = false,
+            bool skipIfDirExists = false);
 
     /**
      * Fixes up an existing application directory, as if it was created with
@@ -179,6 +183,9 @@
      */
     int fixupAppDir(const std::string& path, int32_t appUid);
 
+    // Called before zygote starts to ensure dir exists so zygote can bind mount them.
+    int ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid);
+
     int createObb(const std::string& path, const std::string& key, int32_t ownerGid,
                   std::string* outVolId);
     int destroyObb(const std::string& volId);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index bb284b8..19ce9ba 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -54,9 +54,11 @@
 
     void remountUid(int uid, int remountMode);
     void remountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
+    void unmountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
 
     void setupAppDir(@utf8InCpp String path, int appUid);
     void fixupAppDir(@utf8InCpp String path, int appUid);
+    void ensureAppDirsCreated(in @utf8InCpp String[] paths, int appUid);
 
     @utf8InCpp String createObb(@utf8InCpp String sourcePath, @utf8InCpp String sourceKey,
                                 int ownerGid);
@@ -87,7 +89,7 @@
     void initUser0();
     boolean isConvertibleToFbe();
     void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
-    void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
+    void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType);
 
     void createUserKey(int userId, int userSerial, boolean ephemeral);
     void destroyUserKey(int userId);
@@ -167,7 +169,6 @@
 
     const int STORAGE_FLAG_DE = 1;
     const int STORAGE_FLAG_CE = 2;
-    const int STORAGE_FLAG_LEVEL_FROM_USER = 4;
 
     const int REMOUNT_MODE_NONE = 0;
     const int REMOUNT_MODE_DEFAULT = 1;
diff --git a/model/Disk.h b/model/Disk.h
index 99c98fc..16476dc 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -53,9 +53,12 @@
         kUsb = 1 << 3,
         /* Flag that disk is EMMC internal */
         kEmmc = 1 << 4,
-        /* Flag that disk is Stub disk, i.e., disk that is managed from outside
-         * Android (e.g., ARC++). */
-        kStub = 1 << 5,
+        /* Flag that disk is an invisible Stub disk, i.e., disk that is managed from outside
+         * Android (e.g., ARC++) and invisible to apps. */
+        kStubInvisible = 1 << 5,
+        /* Flag that disk is a visible Stub disk, i.e., disk that is managed from outside
+         * Android (e.g., ARC++) and visible to apps. */
+        kStubVisible = 1 << 6,
     };
 
     const std::string& getId() const { return mId; }
@@ -120,7 +123,7 @@
 
     int getMaxMinors();
 
-    bool isStub() { return mFlags & kStub; }
+    bool isStub() { return (mFlags & kStubInvisible) || (mFlags & kStubVisible); }
 
     DISALLOW_COPY_AND_ASSIGN(Disk);
 };
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index db93bc2..4a77846 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -301,8 +301,6 @@
 
     dev_t before = GetDevice(mSdcardFsFull);
 
-    bool isFuse = base::GetBoolProperty(kPropFuse, false);
-
     // Mount sdcardfs regardless of FUSE, since we need it to bind-mount on top of the
     // FUSE volume for various reasons.
     if (mUseSdcardFs && getMountUserId() == 0) {
@@ -350,7 +348,7 @@
         sdcardFsPid = 0;
     }
 
-    if (isFuse && isVisible) {
+    if (isVisible) {
         // Make sure we unmount sdcardfs if we bail out with an error below
         auto sdcardfs_unmounter = [&]() {
             LOG(INFO) << "sdcardfs_unmounter scope_guard running";
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index d40e3e3..12e31ff 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -227,39 +227,36 @@
         TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
     }
 
-    bool isFuse = base::GetBoolProperty(kPropFuse, false);
-    if (isFuse) {
-        // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
-        // on sdcardfs being up.
-        LOG(INFO) << "Mounting public fuse volume";
-        android::base::unique_fd fd;
-        int user_id = getMountUserId();
-        int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
+    // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
+    // on sdcardfs being up.
+    LOG(INFO) << "Mounting public fuse volume";
+    android::base::unique_fd fd;
+    int user_id = getMountUserId();
+    int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
 
-        if (result != 0) {
-            LOG(ERROR) << "Failed to mount public fuse volume";
-            doUnmount();
-            return -result;
-        }
-
-        mFuseMounted = true;
-        auto callback = getMountCallback();
-        if (callback) {
-            bool is_ready = false;
-            callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
-            if (!is_ready) {
-                LOG(ERROR) << "Failed to complete public volume mount";
-                doUnmount();
-                return -EIO;
-            }
-        }
-
-        ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
-
-        // See comment in model/EmulatedVolume.cpp
-        ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
+    if (result != 0) {
+        LOG(ERROR) << "Failed to mount public fuse volume";
+        doUnmount();
+        return -result;
     }
 
+    mFuseMounted = true;
+    auto callback = getMountCallback();
+    if (callback) {
+        bool is_ready = false;
+        callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
+        if (!is_ready) {
+            LOG(ERROR) << "Failed to complete public volume mount";
+            doUnmount();
+            return -EIO;
+        }
+    }
+
+    ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
+
+    // See comment in model/EmulatedVolume.cpp
+    ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
+
     return OK;
 }
 
diff --git a/vdc.cpp b/vdc.cpp
index 1aaeb5a..47d98de 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -31,9 +31,10 @@
 #include "android/os/IVold.h"
 
 #include <android-base/logging.h>
+#include <android-base/parsebool.h>
 #include <android-base/parseint.h>
-#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <binder/IServiceManager.h>
 #include <binder/Status.h>
 
@@ -107,8 +108,12 @@
         checkStatus(args, vold->reset());
     } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 4) {
         checkStatus(args, vold->mountFstab(args[2], args[3]));
-    } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 4) {
-        checkStatus(args, vold->encryptFstab(args[2], args[3]));
+    } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 6) {
+        auto shouldFormat = android::base::ParseBool(args[4]);
+        if (shouldFormat == android::base::ParseBoolResult::kError) exit(EINVAL);
+        checkStatus(args, vold->encryptFstab(args[2], args[3],
+                                             shouldFormat == android::base::ParseBoolResult::kTrue,
+                                             args[5]));
     } else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) {
         bool supported = false;
         checkStatus(args, vold->supportsCheckpoint(&supported));
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 0283614..e2afb81 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -166,13 +166,9 @@
 static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int flags) {
     struct selabel_handle* sehandle = selinux_android_file_context_handle();
 
-    const uid_t user_for_level =
-            (flags & android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER) ? user_id : -1;
-
     if (flags & android::os::IVold::STORAGE_FLAG_DE) {
         auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
-        if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_de_path,
-                                  user_for_level)) {
+        if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_de_path, user_id)) {
             return false;
         }
 
@@ -187,7 +183,7 @@
 
             auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
             if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, profiles_de_path,
-                                      user_for_level)) {
+                                      user_id)) {
                 return false;
             }
 
@@ -203,8 +199,7 @@
     }
     if (flags & android::os::IVold::STORAGE_FLAG_CE) {
         auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
-        if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_ce_path,
-                                  user_for_level)) {
+        if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_ce_path, user_id)) {
             return false;
         }