Merge "Create a new mount mode for installer packages."
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 0b2f1bf..0137869 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -73,6 +73,7 @@
 using android::base::StringAppendF;
 using android::base::StringPrintf;
 using android::base::unique_fd;
+using android::vold::VoldNativeService;
 
 static const char* kPathUserMount = "/mnt/user";
 static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
@@ -496,40 +497,11 @@
                 _exit(1);
             }
 
-            struct stat storageSb;
-            if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
-                PLOG(ERROR) << "Failed to stat /storage";
+            int mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+            if (mountMode == -1) {
                 _exit(1);
             }
 
-            // Some packages have access to full external storage, identify processes belonging
-            // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
-            if (storageSb.st_dev == fullWriteSb.st_dev && storageSb.st_ino == fullWriteSb.st_ino) {
-                _exit(0);
-            } else {
-                // Some packages don't have access to external storage and processes belonging to
-                // those packages don't have anything mounted at /storage. So, identify those
-                // processes by comparing inode no.s of /mnt/user/%d/package/%s
-                // and /storage
-                std::string pkgStorageSource;
-                for (auto& package : packagesForUid) {
-                    std::string sandbox =
-                        StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
-                    struct stat s;
-                    if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &s)) == -1) {
-                        PLOG(ERROR) << "Failed to stat " << sandbox;
-                        _exit(1);
-                    }
-                    if (storageSb.st_dev == s.st_dev && storageSb.st_ino == s.st_ino) {
-                        pkgStorageSource = sandbox;
-                        break;
-                    }
-                }
-                if (pkgStorageSource.empty()) {
-                    _exit(0);
-                }
-            }
-
             for (auto& volumeLabel : visibleVolLabels) {
                 std::string mntSource = StringPrintf("/mnt/runtime/write/%s", volumeLabel.c_str());
                 std::string mntTarget = StringPrintf("/storage/%s", volumeLabel.c_str());
@@ -540,7 +512,23 @@
                 for (auto& package : packagesForUid) {
                     mountPkgSpecificDir(mntSource, mntTarget, package, "data");
                     mountPkgSpecificDir(mntSource, mntTarget, package, "media");
-                    mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+                    if (mountMode != VoldNativeService::REMOUNT_MODE_INSTALLER) {
+                        mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+                    }
+                }
+                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;
+                        continue;
+                    }
+                    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.c_str();
+                        continue;
+                    }
                 }
             }
             _exit(0);
@@ -555,6 +543,44 @@
     return 0;
 }
 
+int VolumeManager::getMountModeForRunningProc(const std::vector<std::string>& packagesForUid,
+                                              userid_t userId, struct stat& mntWriteStat) {
+    struct stat storageSb;
+    if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
+        PLOG(ERROR) << "Failed to stat /storage";
+        return -1;
+    }
+
+    // Some packages have access to full external storage, identify processes belonging
+    // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
+    if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+        return VoldNativeService::REMOUNT_MODE_FULL;
+    }
+
+    std::string obbMountFile =
+        StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId, packagesForUid[0].c_str());
+    if (access(obbMountFile.c_str(), F_OK) == 0) {
+        return VoldNativeService::REMOUNT_MODE_INSTALLER;
+    }
+
+    // Some packages don't have access to external storage and processes belonging to
+    // those packages don't have anything mounted at /storage. So, identify those
+    // processes by comparing inode no.s of /mnt/user/%d/package/%s
+    // and /storage
+    for (auto& package : packagesForUid) {
+        std::string sandbox = StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
+        struct stat sandboxStat;
+        if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &sandboxStat)) == -1) {
+            PLOG(ERROR) << "Failed to stat " << sandbox;
+            return -1;
+        }
+        if (storageSb.st_dev == sandboxStat.st_dev && storageSb.st_ino == sandboxStat.st_ino) {
+            return VoldNativeService::REMOUNT_MODE_WRITE;
+        }
+    }
+    return VoldNativeService::REMOUNT_MODE_NONE;
+}
+
 int VolumeManager::prepareSandboxes(userid_t userId, const std::vector<std::string>& packageNames,
                                     const std::vector<std::string>& visibleVolLabels) {
     if (visibleVolLabels.empty()) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 9e990d0..b1aa954 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -171,6 +171,8 @@
                             const std::string& packageName, const char* dirName);
     int destroySandboxForAppOnVol(const std::string& packageName, const std::string& sandboxId,
                                   userid_t userId, const std::string& volLabel);
+    int getMountModeForRunningProc(const std::vector<std::string>& packagesForUid, userid_t userId,
+                                   struct stat& mntWriteStat);
 
     void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
     void handleDiskChanged(dev_t device);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 2f7430f..fdccf00 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -151,7 +151,8 @@
     const int REMOUNT_MODE_DEFAULT = 1;
     const int REMOUNT_MODE_READ = 2;
     const int REMOUNT_MODE_WRITE = 3;
-    const int REMOUNT_MODE_FULL = 4;
+    const int REMOUNT_MODE_INSTALLER = 4;
+    const int REMOUNT_MODE_FULL = 5;
 
     const int VOLUME_STATE_UNMOUNTED = 0;
     const int VOLUME_STATE_CHECKING = 1;