From 78c9eb8947538f63d2e06684663d400991dfff8f Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Tue, 12 Apr 2016 15:51:35 -0700 Subject: [PATCH] Added api to delete cache files for a given user Added an api to delete application cache files for a specific user. This allows settings to clear cache files for work profile apps as well. Bug: b/25338468 Change-Id: I52d4944a7a03b6d63ad44dd6bb868aec62815eab --- .../app/ApplicationPackageManager.java | 10 +++++++++ .../android/content/pm/IPackageManager.aidl | 9 ++++++++ .../android/content/pm/PackageManager.java | 21 +++++++++++++++++++ .../server/pm/PackageManagerService.java | 13 ++++++++++-- .../android/test/mock/MockPackageManager.java | 9 ++++++++ .../bridge/android/BridgePackageManager.java | 5 +++++ 6 files changed, 65 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index ed590e6270e44..bf56f25132574 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1920,6 +1920,16 @@ public class ApplicationPackageManager extends PackageManager { } } + @Override + public void deleteApplicationCacheFilesAsUser(String packageName, int userId, + IPackageDataObserver observer) { + try { + mPM.deleteApplicationCacheFilesAsUser(packageName, userId, observer); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @Override public void freeStorageAndNotify(String volumeUuid, long idealStorageSize, IPackageDataObserver observer) { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 6fce36be43ab0..0526815abc5a3 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -387,6 +387,15 @@ interface IPackageManager { */ void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer); + /** + * Delete all the cache files in an applications cache directory + * @param packageName The package name of the application whose cache + * files need to be deleted + * @param userId the user to delete application cache for + * @param observer a callback used to notify when the deletion is finished. + */ + void deleteApplicationCacheFilesAsUser(in String packageName, int userId, IPackageDataObserver observer); + /** * Clear the user data directory of an application. * @param packageName The package name of the application whose cache diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 39bc783b53acd..ade22482bbc94 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4971,6 +4971,27 @@ public abstract class PackageManager { public abstract void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer); + /** + * Attempts to delete the cache files associated with an application for a given user. Since + * this may take a little while, the result will be posted back to the given observer. A + * deletion will fail if the calling context lacks the + * {@link android.Manifest.permission#DELETE_CACHE_FILES} permission, if the named package + * cannot be found, or if the named package is a "system package". If {@code userId} does not + * belong to the calling user, the caller must have + * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission. + * + * @param packageName The name of the package to delete + * @param userId the user for which the cache files needs to be deleted + * @param observer An observer callback to get notified when the cache file deletion is + * complete. + * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} + * will be called when that happens. observer may be null to indicate that no + * callback is desired. + * @hide + */ + public abstract void deleteApplicationCacheFilesAsUser(String packageName, int userId, + IPackageDataObserver observer); + /** * Free storage by deleting LRU sorted list of cache files across * all applications. If the currently available free storage diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 3b07fe185b4f5..5c682d38212e1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -16032,16 +16032,25 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public void deleteApplicationCacheFiles(final String packageName, final IPackageDataObserver observer) { + final int userId = UserHandle.getCallingUserId(); + deleteApplicationCacheFilesAsUser(packageName, userId, observer); + } + + @Override + public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId, + final IPackageDataObserver observer) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_CACHE_FILES, null); - // Queue up an async operation since the package deletion may take a little while. - final int userId = UserHandle.getCallingUserId(); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + /* requireFullPermission= */ true, /* checkShell= */ false, + "delete application cache files"); final PackageParser.Package pkg; synchronized (mPackages) { pkg = mPackages.get(packageName); } + // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() { public void run() { try (PackageFreezer freezer = freezePackage(packageName, diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 91e891f10f2f6..2e5ed3fd3520d 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -691,6 +691,15 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + /** + * @hide - to match hiding in superclass + */ + @Override + public void deleteApplicationCacheFilesAsUser(String packageName, int userId, + IPackageDataObserver observer) { + throw new UnsupportedOperationException(); + } + /** {@hide} */ @Override public void freeStorageAndNotify(String volumeUuid, long idealStorageSize, diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index 42c0ae0d8d8f4..0a64b63bfc64a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -644,6 +644,11 @@ public class BridgePackageManager extends PackageManager { public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) { } + @Override + public void deleteApplicationCacheFilesAsUser(String packageName, int userId, + IPackageDataObserver observer) { + } + @Override public void freeStorageAndNotify(String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {