Use sdcardfs for pass-through mounts.

The pass-through mount is used by MediaProvider to access external
storage. Previously, it was the raw filesystem (eg ext4/f2fs); the
problem with that is that the permissions on that filesystem don't allow
MediaProvider to access all the files it needs to - in particular
directories under Android/

To solve this problem, we can have the pass-through mount sit on top of
sdcardfs instead of the raw filesystem. This means we need to mount
sdcardfs even in case we're using FUSE, but we already needed to do this
anyway for other performance reasons.

Bug: 135341433
Test: atest AdoptableHostTest
Change-Id: I893d5e5076c5096d2d55212f643c9a857242e964
diff --git a/Utils.cpp b/Utils.cpp
index af93824..841aab6 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -995,16 +995,11 @@
     std::string pass_through_path(
             StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
 
-    // Force remove the existing mount before we attempt to prepare the
-    // directory. If we have a dangling mount, then PrepareDir may fail if the
-    // indirection to FUSE doesn't work.
-    android::status_t result = UnmountUserFuse(pass_through_path, fuse_path);
-    if (result != android::OK) {
-        return -1;
-    }
+    std::string sdcardfs_path(
+            StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
 
     // Create directories.
-    result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT);
+    auto result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT);
     if (result != android::OK) {
         PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
         return -1;
@@ -1063,14 +1058,26 @@
         PLOG(ERROR) << "Failed to mount " << fuse_path;
         return -errno;
     }
-    LOG(INFO) << "Bind mounting to " << absolute_lower_path;
-    return BindMount(absolute_lower_path, pass_through_path);
+
+    LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
+    return BindMount(sdcardfs_path, pass_through_path);
 }
 
-status_t UnmountUserFuse(const std::string& pass_through_path, const std::string& fuse_path) {
+status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
+                         const std::string& relative_upper_path) {
+    std::string fuse_path(StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str()));
+    std::string pass_through_path(
+            StringPrintf("/mnt/pass_through/%d/%s", user_id, relative_upper_path.c_str()));
+
     // Best effort unmount pass_through path
     sSleepOnUnmount = false;
-    ForceUnmount(pass_through_path);
+    LOG(INFO) << "Unmounting pass_through_path " << pass_through_path;
+    auto status = ForceUnmount(pass_through_path);
+    if (status != android::OK) {
+        LOG(ERROR) << "Failed to unmount " << pass_through_path;
+    }
+
+    LOG(INFO) << "Unmounting fuse path " << fuse_path;
     android::status_t result = ForceUnmount(fuse_path);
     sSleepOnUnmount = true;
     if (result != android::OK) {