Add NTFS support in vold

This CR, when paired with a functional NTFS implementation and the
corresponding SEPolicy updates, will allow NTFS USB drives to be mounted
on Android.

Bug: 254407246

Test: Extensive testing with an ADT-4 and NTFS USB drives.

Merged-In: If4197c4c588866c611cd6ba3483707d3cb0e0cf8
Change-Id: If4197c4c588866c611cd6ba3483707d3cb0e0cf8
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index bf54c95..20015af 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -20,6 +20,7 @@
 #include "Utils.h"
 #include "VolumeManager.h"
 #include "fs/Exfat.h"
+#include "fs/Ntfs.h"
 #include "fs/Vfat.h"
 
 #include <android-base/logging.h>
@@ -110,6 +111,11 @@
             LOG(ERROR) << getId() << " failed filesystem check";
             return -EIO;
         }
+    } else if (mFsType == "ntfs" && ntfs::IsSupported()) {
+        if (ntfs::Check(mDevPath)) {
+            LOG(ERROR) << getId() << " failed filesystem check";
+            return -EIO;
+        }
     } else {
         LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
         return -EIO;
@@ -152,6 +158,12 @@
             PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
             return -EIO;
         }
+    } else if (mFsType == "ntfs") {
+        if (ntfs::Mount(mDevPath, mRawPath, false, false, false, AID_ROOT,
+                        (isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007)) {
+            PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
+            return -EIO;
+        }
     }
 
     if (getMountFlags() & MountFlags::kPrimary) {
@@ -308,12 +320,15 @@
 }
 
 status_t PublicVolume::doFormat(const std::string& fsType) {
-    bool useVfat = vfat::IsSupported();
-    bool useExfat = exfat::IsSupported();
+    bool isVfatSup = vfat::IsSupported();
+    bool isExfatSup = exfat::IsSupported();
+    bool isNtfsSup = ntfs::IsSupported();
     status_t res = OK;
 
-    // Resolve the target filesystem type
-    if (fsType == "auto" && useVfat && useExfat) {
+    enum { NONE, VFAT, EXFAT, NTFS } fsPick = NONE;
+
+    // Resolve auto requests
+    if (fsType == "auto" && isVfatSup && isExfatSup) {
         uint64_t size = 0;
 
         res = GetBlockDevSize(mDevPath, &size);
@@ -324,29 +339,38 @@
 
         // If both vfat & exfat are supported use exfat for SDXC (>~32GiB) cards
         if (size > 32896LL * 1024 * 1024) {
-            useVfat = false;
+            fsPick = EXFAT;
         } else {
-            useExfat = false;
+            fsPick = VFAT;
         }
-    } else if (fsType == "vfat") {
-        useExfat = false;
-    } else if (fsType == "exfat") {
-        useVfat = false;
+    } else if (fsType == "auto" && isExfatSup) {
+        fsPick = EXFAT;
+    } else if (fsType == "auto" && isVfatSup) {
+        fsPick = VFAT;
     }
 
-    if (!useVfat && !useExfat) {
-        LOG(ERROR) << "Unsupported filesystem " << fsType;
-        return -EINVAL;
+    // Resolve explicit requests
+    if (fsType == "vfat" && isVfatSup) {
+        fsPick = VFAT;
+    } else if (fsType == "exfat" && isExfatSup) {
+        fsPick = EXFAT;
+    } else if (fsType == "ntfs" && isNtfsSup) {
+        fsPick = NTFS;
     }
 
     if (WipeBlockDevice(mDevPath) != OK) {
         LOG(WARNING) << getId() << " failed to wipe";
     }
 
-    if (useVfat) {
+    if (fsPick == VFAT) {
         res = vfat::Format(mDevPath, 0);
-    } else if (useExfat) {
+    } else if (fsPick == EXFAT) {
         res = exfat::Format(mDevPath);
+    } else if (fsPick == NTFS) {
+        res = ntfs::Format(mDevPath, 0);
+    } else {
+        LOG(ERROR) << "Unsupported filesystem " << fsType;
+        return -EINVAL;
     }
 
     if (res != OK) {