Merge "vold: const-ify some of the API"
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index c2d4e0b..31890d6 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -556,24 +556,7 @@
     ENFORCE_UID(AID_SYSTEM);
     ACQUIRE_LOCK;
 
-    std::string tmp;
-    switch (remountMode) {
-        case REMOUNT_MODE_NONE:
-            tmp = "none";
-            break;
-        case REMOUNT_MODE_DEFAULT:
-            tmp = "default";
-            break;
-        case REMOUNT_MODE_READ:
-            tmp = "read";
-            break;
-        case REMOUNT_MODE_WRITE:
-            tmp = "write";
-            break;
-        default:
-            return error("Unknown mode " + std::to_string(remountMode));
-    }
-    return translate(VolumeManager::Instance()->remountUid(uid, tmp));
+    return translate(VolumeManager::Instance()->remountUid(uid, remountMode));
 }
 
 binder::Status VoldNativeService::mkdirs(const std::string& path) {
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a667e57..d113cf9 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -403,7 +403,7 @@
 
 int VolumeManager::mountPkgSpecificDirsForRunningProcs(
     userid_t userId, const std::vector<std::string>& packageNames,
-    const std::vector<std::string>& visibleVolLabels) {
+    const std::vector<std::string>& visibleVolLabels, int remountMode) {
     // TODO: New processes could be started while traversing over the existing
     // processes which would end up not having the necessary bind mounts. This
     // issue needs to be fixed, may be by doing multiple passes here?
@@ -498,9 +498,32 @@
                 _exit(1);
             }
 
-            int mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
-            if (mountMode == -1) {
-                _exit(1);
+            int mountMode;
+            if (remountMode == -1) {
+                mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+                if (mountMode == -1) {
+                    _exit(1);
+                }
+            } else {
+                mountMode = remountMode;
+                std::string obbMountFile = StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId,
+                                                        packagesForUid[0].c_str());
+                if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
+                    if (access(obbMountFile.c_str(), F_OK) != 0) {
+                        const unique_fd fd(
+                            TEMP_FAILURE_RETRY(open(obbMountFile.c_str(), O_RDWR | O_CREAT, 0660)));
+                    }
+                } else {
+                    if (access(obbMountFile.c_str(), F_OK) == 0) {
+                        remove(obbMountFile.c_str());
+                    }
+                }
+            }
+            if (mountMode == VoldNativeService::REMOUNT_MODE_FULL ||
+                mountMode == VoldNativeService::REMOUNT_MODE_NONE) {
+                // These mount modes are not going to change dynamically, so don't bother
+                // unmounting/remounting dirs.
+                _exit(0);
             }
 
             for (auto& volumeLabel : visibleVolLabels) {
@@ -510,6 +533,13 @@
                     StringAppendF(&mntSource, "/%d", userId);
                     StringAppendF(&mntTarget, "/%d", userId);
                 }
+                std::string obbSourceDir = StringPrintf("%s/Android/obb", mntSource.c_str());
+                std::string obbTargetDir = StringPrintf("%s/Android/obb", mntTarget.c_str());
+                if (umount2(obbTargetDir.c_str(), MNT_DETACH) == -1 && errno != EINVAL &&
+                    errno != ENOENT) {
+                    PLOG(ERROR) << "Failed to unmount " << obbTargetDir;
+                    continue;
+                }
                 for (auto& package : packagesForUid) {
                     mountPkgSpecificDir(mntSource, mntTarget, package, "data");
                     mountPkgSpecificDir(mntSource, mntTarget, package, "media");
@@ -518,16 +548,14 @@
                     }
                 }
                 if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
-                    StringAppendF(&mntSource, "/Android/obb");
-                    StringAppendF(&mntTarget, "/Android/obb");
-                    if (TEMP_FAILURE_RETRY(mount(mntSource.c_str(), mntTarget.c_str(), nullptr,
-                                                 MS_BIND | MS_REC, nullptr)) == -1) {
-                        PLOG(ERROR) << "Failed to mount " << mntSource << " to " << mntTarget;
+                    if (TEMP_FAILURE_RETRY(mount(obbSourceDir.c_str(), obbTargetDir.c_str(),
+                                                 nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+                        PLOG(ERROR) << "Failed to mount " << obbSourceDir << " to " << obbTargetDir;
                         continue;
                     }
-                    if (TEMP_FAILURE_RETRY(mount(nullptr, mntTarget.c_str(), nullptr,
+                    if (TEMP_FAILURE_RETRY(mount(nullptr, obbTargetDir.c_str(), nullptr,
                                                  MS_REC | MS_SLAVE, nullptr)) == -1) {
-                        PLOG(ERROR) << "Failed to set MS_SLAVE at " << mntTarget.c_str();
+                        PLOG(ERROR) << "Failed to set MS_SLAVE at " << obbTargetDir.c_str();
                         continue;
                     }
                 }
@@ -694,7 +722,7 @@
             }
         }
     }
-    mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels);
+    mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, -1);
     return 0;
 }
 
@@ -1066,12 +1094,56 @@
     return 0;
 }
 
-int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
-    // If the isolated storage is enabled, return -1 since in the isolated storage world, there
-    // are no longer any runtime storage permissions, so this shouldn't be called anymore.
-    if (GetBoolProperty(kIsolatedStorage, false)) {
+int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+    if (!GetBoolProperty(kIsolatedStorage, false)) {
+        return remountUidLegacy(uid, mountMode);
+    }
+
+    appid_t appId = multiuser_get_app_id(uid);
+    userid_t userId = multiuser_get_user_id(uid);
+    std::vector<std::string> visibleVolLabels;
+    for (auto& volId : mVisibleVolumeIds) {
+        auto vol = findVolume(volId);
+        userid_t mountUserId = vol->getMountUserId();
+        if (mountUserId == userId || vol->isEmulated()) {
+            visibleVolLabels.push_back(vol->getLabel());
+        }
+    }
+
+    // Finding one package with appId is enough
+    std::vector<std::string> packageNames;
+    for (auto it = mAppIds.begin(); it != mAppIds.end(); ++it) {
+        if (it->second == appId) {
+            packageNames.push_back(it->first);
+            break;
+        }
+    }
+    if (packageNames.empty()) {
+        PLOG(ERROR) << "Failed to find packageName for " << uid;
         return -1;
     }
+    return mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, mountMode);
+}
+
+int VolumeManager::remountUidLegacy(uid_t uid, int32_t mountMode) {
+    std::string mode;
+    switch (mountMode) {
+        case VoldNativeService::REMOUNT_MODE_NONE:
+            mode = "none";
+            break;
+        case VoldNativeService::REMOUNT_MODE_DEFAULT:
+            mode = "default";
+            break;
+        case VoldNativeService::REMOUNT_MODE_READ:
+            mode = "read";
+            break;
+        case VoldNativeService::REMOUNT_MODE_WRITE:
+            mode = "write";
+            break;
+        default:
+            PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
+            return -1;
+    }
     LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
 
     DIR* dir;
diff --git a/VolumeManager.h b/VolumeManager.h
index e25ba9b..3a7bae4 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -107,7 +107,8 @@
 
     int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
 
-    int remountUid(uid_t uid, const std::string& mode);
+    int remountUid(uid_t uid, int32_t remountMode);
+    int remountUidLegacy(uid_t uid, int32_t remountMode);
 
     /* Reset all internal state, typically during framework boot */
     int reset();
@@ -153,7 +154,8 @@
                          const std::vector<std::string>& visibleVolLabels);
     int mountPkgSpecificDirsForRunningProcs(userid_t userId,
                                             const std::vector<std::string>& packageNames,
-                                            const std::vector<std::string>& visibleVolLabels);
+                                            const std::vector<std::string>& visibleVolLabels,
+                                            int remountMode);
     int destroySandboxesForVol(android::vold::VolumeBase* vol, userid_t userId);
     std::string prepareSandboxSource(uid_t uid, const std::string& sandboxId,
                                      const std::string& sandboxRootDir);