Merge "Remove ro.vold.level_from_user."
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/VoldNativeService.cpp b/VoldNativeService.cpp
index 864a6f0..332fc63 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -681,15 +681,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 0a55af4..8fd6261 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -111,7 +111,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 714122d..5dc0d9a 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -985,11 +985,6 @@
 }
 
 int VolumeManager::ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid) {
-    if (IsSdcardfsUsed()) {
-        // sdcardfs magically does this for us
-        return OK;
-    }
-
     int size = paths.size();
     for (int i = 0; i < size; i++) {
         int result = setupAppDir(paths[i], appUid, false /* fixupExistingOnly */,
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 28e343f..de381d3 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -88,7 +88,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);
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));