diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 1f54ea53facc3..63ff7b22f364e 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -16,6 +16,9 @@
package android.os.storage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* Mount service local interface.
*
@@ -81,18 +84,26 @@ public abstract class StorageManagerInternal {
public abstract int getExternalStorageMountMode(int uid, String packageName);
/**
- * Mount external storage for the given package.
+ * Create storage sandbox for the given package.
*
*
This will involve calling into vold to setup appropriate bind mounts.
*
- * @param packageName The package for which external storage will be mounted.
+ * @param packageName The package for which the sandbox needs to be created.
* @param appId The appId for the given package.
* @param sharedUserId The sharedUserId for given package if it specified
* {@code android:sharedUserId} in the manifest, otherwise {@code null}
- * @param userId The userId in which the storage needs to be mounted.
+ * @param userId The userId in which the sandbox needs to be created.
*/
- public abstract void mountExternalStorageForApp(String packageName, int appId,
- String sharedUserId, int userId);
+ public abstract void prepareSandboxForApp(@NonNull String packageName, int appId,
+ @Nullable String sharedUserId, int userId);
+
+ /**
+ * Delete storage sandbox for the given package.
+ *
+ * @param packageName The package for which the sandbox needs to be destroyed.
+ * @param userId The userId in which the sandbox needs to be destroyed.
+ */
+ public abstract void destroySandboxForApp(@NonNull String packageName, int userId);
/**
* @return Labels of storage volumes that are visible to the given userId.
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 21f54dd33d3e8..7c67596d92b47 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3754,7 +3754,7 @@ class StorageManagerService extends IStorageManager.Stub
}
@Override
- public void mountExternalStorageForApp(String packageName, int appId, String sharedUserId,
+ public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
int userId) {
final String sandboxId;
synchronized (mPackagesLock) {
@@ -3771,7 +3771,41 @@ class StorageManagerService extends IStorageManager.Stub
}
try {
- mVold.mountExternalStorageForApp(packageName, appId, sandboxId, userId);
+ mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ }
+ }
+
+ @Override
+ public void destroySandboxForApp(String packageName, int userId) {
+ if (!ENABLE_ISOLATED_STORAGE) {
+ return;
+ }
+ final int appId;
+ final String sandboxId;
+ synchronized (mPackagesLock) {
+ final ArraySet userPackages = getAvailablePackagesForUserPL(userId);
+ userPackages.remove(packageName);
+ appId = mAppIds.get(packageName);
+ sandboxId = mSandboxIds.get(appId);
+
+ // If the package is not uninstalled in any other users, remove appId and sandboxId
+ // corresponding to it from the internal state.
+ boolean installedInAnyUser = false;
+ for (int i = mPackages.size() - 1; i >= 0; --i) {
+ if (mPackages.valueAt(i).contains(packageName)) {
+ installedInAnyUser = true;
+ break;
+ }
+ }
+ if (!installedInAnyUser) {
+ mAppIds.remove(packageName);
+ mSandboxIds.remove(appId);
+ }
+ }
+ try {
+ mVold.destroySandboxForApp(packageName, appId, sandboxId, userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 329b1da82608b..13f084e674944 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -940,6 +940,7 @@ public class PackageManagerService extends IPackageManager.Stub
private UserManagerInternal mUserManagerInternal;
private ActivityManagerInternal mActivityManagerInternal;
private ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ private StorageManagerInternal mStorageManagerInternal;
private DeviceIdleController.LocalService mDeviceIdleController;
@@ -4598,6 +4599,13 @@ public class PackageManagerService extends IPackageManager.Stub
return mDeviceIdleController;
}
+ private StorageManagerInternal getStorageManagerInternal() {
+ if (mStorageManagerInternal == null) {
+ mStorageManagerInternal = LocalServices.getService(StorageManagerInternal.class);
+ }
+ return mStorageManagerInternal;
+ }
+
/**
* Update given flags when being used to request {@link PackageInfo}.
*/
@@ -9505,6 +9513,30 @@ public class PackageManagerService extends IPackageManager.Stub
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
}
+ // If this package doesn't have a sharedUserId or there are no other packages
+ // present with same sharedUserId, then delete the sandbox data too.
+ try {
+ final SharedUserSetting sharedUserSetting = mSettings.getSharedUserLPw(
+ pkg.mSharedUserId, 0 /* pkgFlags */,
+ 0 /* pkgPrivateFlags */, false /* create */);
+ boolean deleteSandboxData = true;
+ if (sharedUserSetting != null && sharedUserSetting.packages != null) {
+ for (int i = sharedUserSetting.packages.size() - 1; i >= 0; --i) {
+ final PackageSetting packageSetting = sharedUserSetting.packages.valueAt(i);
+ if (!packageSetting.name.equals(pkg.packageName)
+ && packageSetting.readUserState(realUserId).isAvailable(
+ MATCH_UNINSTALLED_PACKAGES)) {
+ deleteSandboxData = false;
+ break;
+ }
+ }
+ }
+ if (deleteSandboxData) {
+ getStorageManagerInternal().destroySandboxForApp(pkg.packageName, realUserId);
+ }
+ } catch (PackageManagerException e) {
+ // Should not happen
+ }
mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
}
}
@@ -19820,9 +19852,7 @@ public class PackageManagerService extends IPackageManager.Stub
mDexManager.systemReady();
mPackageDexOptimizer.systemReady();
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
- storageManagerInternal.addExternalStoragePolicy(
+ getStorageManagerInternal().addExternalStoragePolicy(
new StorageManagerInternal.ExternalStorageMountPolicy() {
@Override
public int getMountMode(int uid, String packageName) {
@@ -21215,10 +21245,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
prepareAppDataContentsLeafLIF(pkg, userId, flags);
- final StorageManagerInternal storageManagerInternal
- = LocalServices.getService(StorageManagerInternal.class);
- if (storageManagerInternal != null) {
- storageManagerInternal.mountExternalStorageForApp(
+ if (getStorageManagerInternal() != null) {
+ getStorageManagerInternal().prepareSandboxForApp(
pkg.packageName, appId, pkg.mSharedUserId, userId);
}
}