Add mount callback

Mounting a FUSE path needs two steps:
1. Mounting the filesystem
2. Starting the FUSE session in the FUSE daemon

The second part requires retriving an fd from (1) and the mount paths
and passing it to the FUSE daemon.

Previously, we'd return from the Vold mount call and mark the volume
as mounted while we scramble to do (2). This means there's a time
period where the Volume is marked as MOUNTED but not actually ready
and any IO access on the paths will hang forever. This could also be
misleading when interpreting bug reports.

Now, we block the Vold mount call until the FUSE session is started

Test: atest AdoptableHostTest
Bug: 144275217

Change-Id: I45238a31df71286f67ef1c65c711d0085d72e97f
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index e0d0109..8224e61 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -97,8 +97,17 @@
             PLOG(ERROR) << "Failed to mount emulated fuse volume";
             return -result;
         }
-        setFuseFd(std::move(fd));
-        return 0;
+
+        auto callback = getMountCallback();
+        if (callback) {
+            bool is_ready = false;
+            callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
+            if (!is_ready) {
+                return -EIO;
+            }
+        }
+
+        return OK;
     } else if (getMountUserId() != 0) {
         // For sdcardfs, only mount for user 0, since user 0 will always be running
         // and the paths don't change for different users. Trying to double mount
@@ -177,7 +186,6 @@
 
         rmdir(fuse_path.c_str());
         rmdir(pass_through_path.c_str());
-        setFuseFd(android::base::unique_fd());
         return OK;
     } else if (getMountUserId() != 0) {
         // For sdcardfs, only unmount for user 0, since user 0 will always be running
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 403e85c..d1b63a3 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -180,7 +180,16 @@
             LOG(ERROR) << "Failed to mount public fuse volume";
             return -result;
         }
-        setFuseFd(std::move(fd));
+
+        auto callback = getMountCallback();
+        if (callback) {
+            bool is_ready = false;
+            callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
+            if (!is_ready) {
+                return -EIO;
+            }
+        }
+
         return OK;
     }
 
@@ -269,9 +278,6 @@
         rmdir(pass_through_path.c_str());
         rmdir(mRawPath.c_str());
         mRawPath.clear();
-
-        setFuseFd(android::base::unique_fd());
-
         return OK;
     }
 
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index ae45f7e..636c065 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -143,16 +143,16 @@
     return OK;
 }
 
-status_t VolumeBase::setFuseFd(android::base::unique_fd fuseFd) {
-    if ((mState != State::kChecking) && (mState != State::kEjecting)) {
-        LOG(WARNING) << getId() << " fuse fd change requires state checking or ejecting";
-        return -EBUSY;
-    }
-
-    mFuseFd = std::move(fuseFd);
+status_t VolumeBase::setMountCallback(
+        const android::sp<android::os::IVoldMountCallback>& callback) {
+    mMountCallback = callback;
     return OK;
 }
 
+sp<android::os::IVoldMountCallback> VolumeBase::getMountCallback() const {
+    return mMountCallback;
+}
+
 android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
     if (mSilent) {
         return nullptr;
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index 82b0ae0..1d88d1b 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -19,6 +19,7 @@
 
 #include "Utils.h"
 #include "android/os/IVoldListener.h"
+#include "android/os/IVoldMountCallback.h"
 
 #include <cutils/multiuser.h>
 #include <utils/Errors.h>
@@ -87,13 +88,13 @@
     State getState() const { return mState; }
     const std::string& getPath() const { return mPath; }
     const std::string& getInternalPath() const { return mInternalPath; }
-    const android::base::unique_fd& getFuseFd() const { return mFuseFd; }
     const std::list<std::shared_ptr<VolumeBase>>& getVolumes() const { return mVolumes; }
 
     status_t setDiskId(const std::string& diskId);
     status_t setPartGuid(const std::string& partGuid);
     status_t setMountFlags(int mountFlags);
     status_t setMountUserId(userid_t mountUserId);
+    status_t setMountCallback(const android::sp<android::os::IVoldMountCallback>& callback);
     status_t setSilent(bool silent);
 
     void addVolume(const std::shared_ptr<VolumeBase>& volume);
@@ -123,10 +124,9 @@
     status_t setId(const std::string& id);
     status_t setPath(const std::string& path);
     status_t setInternalPath(const std::string& internalPath);
-    // Takes ownership of the fd passed in.
-    status_t setFuseFd(android::base::unique_fd fuseFd);
 
     android::sp<android::os::IVoldListener> getListener() const;
+    android::sp<android::os::IVoldMountCallback> getMountCallback() const;
 
   private:
     /* ID that uniquely references volume while alive */
@@ -151,8 +151,7 @@
     std::string mInternalPath;
     /* Flag indicating that volume should emit no events */
     bool mSilent;
-    /* The filedescriptor for the fuse device, if the volume uses fuse, or -1 otherwise */
-    android::base::unique_fd mFuseFd;
+    android::sp<android::os::IVoldMountCallback> mMountCallback;
 
     /* Volumes stacked on top of this volume */
     std::list<std::shared_ptr<VolumeBase>> mVolumes;