Merge "Add mount callback"
diff --git a/Android.bp b/Android.bp
index 323bc3c..5d93bfa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -265,6 +265,7 @@
     srcs: [
         "binder/android/os/IVold.aidl",
         "binder/android/os/IVoldListener.aidl",
+        "binder/android/os/IVoldMountCallback.aidl",
         "binder/android/os/IVoldTaskListener.aidl",
     ],
     path: "binder",
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index e20d68e..1f7638f 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -325,9 +325,9 @@
     return translate(VolumeManager::Instance()->forgetPartition(partGuid, fsUuid));
 }
 
-binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
-                                        int32_t mountUserId,
-                                        android::base::unique_fd* _aidl_return) {
+binder::Status VoldNativeService::mount(
+        const std::string& volId, int32_t mountFlags, int32_t mountUserId,
+        const android::sp<android::os::IVoldMountCallback>& callback) {
     ENFORCE_SYSTEM_OR_ROOT;
     CHECK_ARGUMENT_ID(volId);
     ACQUIRE_LOCK;
@@ -340,18 +340,14 @@
     vol->setMountFlags(mountFlags);
     vol->setMountUserId(mountUserId);
 
+    vol->setMountCallback(callback);
     int res = vol->mount();
+    vol->setMountCallback(nullptr);
+
     if (res != OK) {
         return translate(res);
     }
 
-    _aidl_return->reset(dup(vol->getFuseFd().get()));
-    if (_aidl_return->get() == -1) {
-        // Let's not return invalid fd since binder will not allow null fds. Instead give it a
-        // default value.
-        _aidl_return->reset(open("/dev/null", O_RDONLY | O_CLOEXEC));
-    }
-
     if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
         res = VolumeManager::Instance()->setPrimary(vol);
         if (res != OK) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 744ff84..cc4dd1b 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -53,7 +53,7 @@
     binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid);
 
     binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId,
-                         android::base::unique_fd* _aidl_return);
+                         const android::sp<android::os::IVoldMountCallback>& callback);
     binder::Status unmount(const std::string& volId);
     binder::Status format(const std::string& volId, const std::string& fsType);
     binder::Status benchmark(const std::string& volId,
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 91c0172..8412f9a 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.os.IVoldListener;
+import android.os.IVoldMountCallback;
 import android.os.IVoldTaskListener;
 
 /** {@hide} */
@@ -40,7 +41,8 @@
     void partition(@utf8InCpp String diskId, int partitionType, int ratio);
     void forgetPartition(@utf8InCpp String partGuid, @utf8InCpp String fsUuid);
 
-    FileDescriptor mount(@utf8InCpp String volId, int mountFlags, int mountUserId);
+    void mount(@utf8InCpp String volId, int mountFlags, int mountUserId,
+         IVoldMountCallback callback);
     void unmount(@utf8InCpp String volId);
     void format(@utf8InCpp String volId, @utf8InCpp String fsType);
     void benchmark(@utf8InCpp String volId, IVoldTaskListener listener);
diff --git a/binder/android/os/IVoldMountCallback.aidl b/binder/android/os/IVoldMountCallback.aidl
new file mode 100644
index 0000000..6bf46d7
--- /dev/null
+++ b/binder/android/os/IVoldMountCallback.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** {@hide} */
+interface IVoldMountCallback {
+    boolean onVolumeChecking(FileDescriptor fuseFd, @utf8InCpp String path,
+        @utf8InCpp String internalPath);
+}
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;