Merge "Use /mnt/storage for bind mounting package sandboxes."
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 594fcde..5e012c7 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -98,6 +98,7 @@
     // For security reasons, assume that a secure keyguard is
     // showing until we hear otherwise
     mSecureKeyguardShowing = true;
+    mMntStorageCreated = false;
 }
 
 VolumeManager::~VolumeManager() {
@@ -346,9 +347,35 @@
     return success ? 0 : -1;
 }
 
+static int prepareMntStorageDir() {
+    std::string mntTarget("/mnt/storage");
+    if (fs_prepare_dir(mntTarget.c_str(), 0755, AID_ROOT, AID_ROOT) != 0) {
+        PLOG(ERROR) << "fs_prepare_dir failed on " << mntTarget;
+        return -errno;
+    }
+    if (TEMP_FAILURE_RETRY(mount("/mnt/runtime/write", mntTarget.c_str(),
+            nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+        PLOG(ERROR) << "Failed to mount /mnt/runtime/write at " << mntTarget;
+        return -errno;
+    }
+    if (TEMP_FAILURE_RETRY(mount(nullptr, mntTarget.c_str(),
+            nullptr, MS_REC | MS_SLAVE, nullptr)) == -1) {
+        PLOG(ERROR) << "Failed to set MS_SLAVE at " << mntTarget;
+        return -errno;
+    }
+    return 0;
+}
+
 int VolumeManager::linkPrimary(userid_t userId, const std::vector<std::string>& packageNames) {
     if (GetBoolProperty(kIsolatedStorage, false)) {
-        std::string source(StringPrintf("/mnt/runtime/write/%s", mPrimary->getLabel().c_str()));
+        // This should ideally go into start() but it's possible that system properties are not
+        // loaded at that point.
+        if (!mMntStorageCreated) {
+            prepareMntStorageDir();
+            mMntStorageCreated = true;
+        }
+
+        std::string source(StringPrintf("/mnt/storage/%s", mPrimary->getLabel().c_str()));
         bool isPrimaryEmulated =
                 (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated);
         if (isPrimaryEmulated) {
@@ -441,44 +468,47 @@
         std::string sandboxId = mSandboxIds[appId];
         uid_t uid = multiuser_get_uid(userId, appId);
 
-        // Create [1] /mnt/runtime/write/emulated/0/Android/sandbox/<sandboxId>
-        // Create [2] /mnt/user/0/package/<packageName>/emulated/0
-        // Mount [1] at [2]
+        // Create /mnt/storage/emulated/0/Android/sandbox/<sandboxId>
         std::string pkgSandboxSourceDir = prepareSandboxSource(uid, sandboxId, sandboxRoot);
         if (pkgSandboxSourceDir.empty()) {
             return -errno;
         }
-        std::string pkgSandboxTargetDir = prepareSandboxTarget(packageName, uid,
-                mPrimary->getLabel(), mntTargetRoot, isPrimaryEmulated);
-        if (pkgSandboxTargetDir.empty()) {
-            return -errno;
-        }
-        if (TEMP_FAILURE_RETRY(mount(pkgSandboxSourceDir.c_str(), pkgSandboxTargetDir.c_str(),
-                nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
-            PLOG(ERROR) << "Failed to mount " << pkgSandboxSourceDir << " at "
-                        << pkgSandboxTargetDir;
-            return -errno;
-        }
 
-        // Create [1] /mnt/runtime/write/emulated/0/Android/data/<packageName>
-        // Create [2] /mnt/user/0/package/<packageName>/emulated/0/Android/data/<packageName>
+        // Create [1] /mnt/storage/emulated/0/Android/data/<packageName>
+        // Create [2] /mnt/storage/emulated/0/Android/sandbox/<sandboxId>/Android/data/<packageName>
         // Mount [1] at [2]
         std::string pkgDataSourceDir = preparePkgDataSource(packageName, uid, dataRoot);
         if (pkgDataSourceDir.empty()) {
             return -errno;
         }
         std::string pkgDataTargetDir = preparePkgDataTarget(packageName, uid,
-                pkgSandboxTargetDir);
+                pkgSandboxSourceDir);
         if (pkgDataTargetDir.empty()) {
             return -errno;
         }
         if (TEMP_FAILURE_RETRY(mount(pkgDataSourceDir.c_str(), pkgDataTargetDir.c_str(),
-                nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+                nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
             PLOG(ERROR) << "Failed to mount " << pkgDataSourceDir << " at "
                         << pkgDataTargetDir;
             return -errno;
         }
 
+        // Already created [1] /mnt/storage/emulated/0/Android/sandbox/<sandboxId>
+        // Create [2] /mnt/user/0/package/<packageName>/emulated/0
+        // Mount [1] at [2]
+        std::string pkgSandboxTargetDir = prepareSandboxTarget(packageName, uid,
+                mPrimary->getLabel(), mntTargetRoot, isPrimaryEmulated);
+        if (pkgSandboxTargetDir.empty()) {
+            return -errno;
+        }
+
+        if (TEMP_FAILURE_RETRY(mount(pkgSandboxSourceDir.c_str(), pkgSandboxTargetDir.c_str(),
+                nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+            PLOG(ERROR) << "Failed to mount " << pkgSandboxSourceDir << " at "
+                        << pkgSandboxTargetDir;
+            return -errno;
+        }
+
         // Create [1] /mnt/user/0/package/<packageName>/self/primary
         // Already created [2] /mnt/user/0/package/<packageName>/emulated/0
         // Mount [2] at [1]
@@ -489,7 +519,7 @@
             return -errno;
         }
         if (TEMP_FAILURE_RETRY(mount(pkgSandboxTargetDir.c_str(), pkgPrimaryTargetDir.c_str(),
-                nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+                nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
             PLOG(ERROR) << "Failed to mount " << pkgSandboxTargetDir << " at "
                         << pkgPrimaryTargetDir;
             return -errno;
@@ -802,6 +832,13 @@
     mUserPackages.clear();
     mAppIds.clear();
     mSandboxIds.clear();
+
+    // For unmounting dirs under /mnt/user/<user-id>/package/<package-name>
+    unmount_tree("/mnt/user/");
+    // For unmounting dirs under /mnt/storage including the bind mount at /mnt/storage, that's
+    // why no trailing '/'
+    unmount_tree("/mnt/storage");
+    mMntStorageCreated = false;
     return 0;
 }
 
@@ -850,7 +887,8 @@
         auto test = std::string(mentry->mnt_dir);
         if ((android::base::StartsWith(test, "/mnt/") &&
              !android::base::StartsWith(test, "/mnt/vendor") &&
-             !android::base::StartsWith(test, "/mnt/product")) ||
+             !android::base::StartsWith(test, "/mnt/product") &&
+             !android::base::StartsWith(test, "/mnt/storage")) ||
             android::base::StartsWith(test, "/storage/")) {
             toUnmount.push_front(test);
         }
diff --git a/VolumeManager.h b/VolumeManager.h
index dd7bf71..52203c5 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -179,6 +179,7 @@
 
     int mNextObbId;
     bool mSecureKeyguardShowing;
+    bool mMntStorageCreated;
 };
 
 #endif