vold: Support aborting FUSE connections.

This can be done through binder as well as vdc, using 'vdc volume
abort_fuse'.

Bug: 153411204
Test: adb shell vdc volume abort_fuse
Change-Id: I93e46dc1cd361729cc1162c63520cf73152ea409
diff --git a/Utils.cpp b/Utils.cpp
index 15a5e49..e3a419f 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1330,6 +1330,21 @@
     return true;
 }
 
+status_t AbortFuseConnections() {
+    namespace fs = std::filesystem;
+
+    for (const auto& itEntry : fs::directory_iterator("/sys/fs/fuse/connections")) {
+        std::string abortPath = itEntry.path().string() + "/abort";
+        LOG(DEBUG) << "Aborting fuse connection entry " << abortPath;
+        bool ret = writeStringToFile("1", abortPath);
+        if (!ret) {
+            LOG(WARNING) << "Failed to write to " << abortPath;
+        }
+    }
+
+    return OK;
+}
+
 status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
     if (access(path.c_str(), F_OK) != 0) {
         PLOG(WARNING) << "Dir does not exist: " << path;
diff --git a/Utils.h b/Utils.h
index eac3cf4..c4926e7 100644
--- a/Utils.h
+++ b/Utils.h
@@ -50,6 +50,8 @@
 status_t CreateDeviceNode(const std::string& path, dev_t dev);
 status_t DestroyDeviceNode(const std::string& path);
 
+status_t AbortFuseConnections();
+
 int SetQuotaInherit(const std::string& path);
 int SetQuotaProjectId(const std::string& path, long projectId);
 /*
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 1020526..a37ba5a 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -175,6 +175,13 @@
     return translate(VolumeManager::Instance()->shutdown());
 }
 
+binder::Status VoldNativeService::abortFuse() {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_LOCK;
+
+    return translate(VolumeManager::Instance()->abortFuse());
+}
+
 binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) {
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_LOCK;
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 060d704..c7d8849 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -36,6 +36,7 @@
     binder::Status monitor();
     binder::Status reset();
     binder::Status shutdown();
+    binder::Status abortFuse();
 
     binder::Status onUserAdded(int32_t userId, int32_t userSerial);
     binder::Status onUserRemoved(int32_t userId);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index f42f3e7..a543573 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -905,6 +905,10 @@
     return 0;
 }
 
+int VolumeManager::abortFuse() {
+    return android::vold::AbortFuseConnections();
+}
+
 int VolumeManager::reset() {
     // Tear down all existing disks/volumes and start from a blank slate so
     // newly connected framework hears all events.
@@ -940,6 +944,7 @@
     mDisks.clear();
     mPendingDisks.clear();
     android::vold::sSleepOnUnmount = true;
+
     return 0;
 }
 
diff --git a/VolumeManager.h b/VolumeManager.h
index a9087fd..3277f75 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -120,6 +120,8 @@
     int remountUid(uid_t uid, int32_t remountMode);
     int remountAppStorageDirs(int uid, int pid, const std::vector<std::string>& packageNames);
 
+    /* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */
+    int abortFuse();
     /* Reset all internal state, typically during framework boot */
     int reset();
     /* Prepare for device shutdown, safely unmounting all devices */
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 68e2ba9..6d14959 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -25,6 +25,7 @@
 interface IVold {
     void setListener(IVoldListener listener);
 
+    void abortFuse();
     void monitor();
     void reset();
     void shutdown();
diff --git a/vdc.cpp b/vdc.cpp
index a6a3fb0..c0b798d 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -99,6 +99,8 @@
         checkStatus(args, vold->fdeEnable(passwordType, "", encryptionFlags));
     } else if (args[0] == "cryptfs" && args[1] == "mountdefaultencrypted") {
         checkStatus(args, vold->mountDefaultEncrypted());
+    } else if (args[0] == "volume" && args[1] == "abort_fuse") {
+        checkStatus(args, vold->abortFuse());
     } else if (args[0] == "volume" && args[1] == "shutdown") {
         checkStatus(args, vold->shutdown());
     } else if (args[0] == "volume" && args[1] == "reset") {