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); } }