From 585e5c46d58b9abfa43aa5c5f2bef9f14e9aa48a Mon Sep 17 00:00:00 2001 From: Evan Severson Date: Tue, 13 Oct 2020 13:15:41 -0700 Subject: [PATCH] Do not allow uninstalling while an app is pinned If an app is pinned we want to avoid ways to unpin without entering a set passcode. If the package of the base activity in the pinned activity stack is uninstalled then the device exits pinning mode so we want to restrict uninstalling this package. Bug: 135604684 Test: Pin test app, test app tries to uninstall itself Pin test app, `adb uninstall` Pin test app, test app launches second test app, assert that second test app can be uninstalled but base test app can't Change-Id: I32ee438e9dd9e245bed6e6a9f4efd0abbb70de1f --- core/java/android/content/pm/PackageManager.java | 11 +++++++++++ .../android/server/pm/PackageManagerService.java | 13 +++++++++++++ .../server/wm/ActivityTaskManagerInternal.java | 6 ++++++ .../server/wm/ActivityTaskManagerService.java | 8 ++++++++ .../com/android/server/wm/LockTaskController.java | 15 +++++++++++++++ 5 files changed, 53 insertions(+) diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e54a53efec59c..efa23fe12a4c9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1708,6 +1708,15 @@ public abstract class PackageManager { * {@hide} */ public static final int DELETE_FAILED_USED_SHARED_LIBRARY = -6; + /** + * Deletion failed return code: this is passed to the + * {@link IPackageDeleteObserver} if the system failed to delete the package + * because there is an app pinned. + * + * @hide + */ + public static final int DELETE_FAILED_APP_PINNED = -7; + /** * Return code that is passed to the {@link IPackageMoveObserver} when the * package has been successfully moved by the system. @@ -7701,6 +7710,7 @@ public abstract class PackageManager { case DELETE_FAILED_OWNER_BLOCKED: return "DELETE_FAILED_OWNER_BLOCKED"; case DELETE_FAILED_ABORTED: return "DELETE_FAILED_ABORTED"; case DELETE_FAILED_USED_SHARED_LIBRARY: return "DELETE_FAILED_USED_SHARED_LIBRARY"; + case DELETE_FAILED_APP_PINNED: return "DELETE_FAILED_APP_PINNED"; default: return Integer.toString(status); } } @@ -7715,6 +7725,7 @@ public abstract class PackageManager { case DELETE_FAILED_OWNER_BLOCKED: return PackageInstaller.STATUS_FAILURE_BLOCKED; case DELETE_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED; case DELETE_FAILED_USED_SHARED_LIBRARY: return PackageInstaller.STATUS_FAILURE_CONFLICT; + case DELETE_FAILED_APP_PINNED: return PackageInstaller.STATUS_FAILURE_BLOCKED; default: return PackageInstaller.STATUS_FAILURE; } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c39152be518a7..eaa19c5ddebd2 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -18678,6 +18678,19 @@ public class PackageManagerService extends IPackageManager.Stub final String packageName = versionedPackage.getPackageName(); final long versionCode = versionedPackage.getLongVersionCode(); final String internalPackageName; + + try { + if (mInjector.getLocalService(ActivityTaskManagerInternal.class) + .isBaseOfLockedTask(packageName)) { + observer.onPackageDeleted( + packageName, PackageManager.DELETE_FAILED_APP_PINNED, null); + EventLog.writeEvent(0x534e4554, "127605586", -1, ""); + return; + } + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + synchronized (mLock) { // Normalize package name to handle renamed packages and static libs internalPackageName = resolveInternalPackageNameLPr(packageName, versionCode); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index c7d716d8290a9..eb86d37225bcc 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -565,4 +565,10 @@ public abstract class ActivityTaskManagerInternal { /** Set all associated companion app that belongs to an userId. */ public abstract void setCompanionAppPackages(int userId, Set companionAppPackages); + + /** + * @param packageName The package to check + * @return Whether the package is the base of any locked task + */ + public abstract boolean isBaseOfLockedTask(String packageName); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 51f7d015e5482..04b11e3b5131a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -7413,5 +7413,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mCompanionAppUidsMap.put(userId, result); } } + + + @Override + public boolean isBaseOfLockedTask(String packageName) { + synchronized (mGlobalLock) { + return getLockTaskController().isBaseOfLockedTask(packageName); + } + } } } diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java index c49690157c085..9e705ca155d41 100644 --- a/services/core/java/com/android/server/wm/LockTaskController.java +++ b/services/core/java/com/android/server/wm/LockTaskController.java @@ -870,6 +870,21 @@ public class LockTaskController { return new Pair<>(flags1, flags2); } + /** + * @param packageName The package to check + * @return Whether the package is the base of any locked task + */ + boolean isBaseOfLockedTask(String packageName) { + for (int i = 0; i < mLockTaskModeTasks.size(); i++) { + final Intent bi = mLockTaskModeTasks.get(i).getBaseIntent(); + if (bi != null && packageName.equals(bi.getComponent() + .getPackageName())) { + return true; + } + } + return false; + } + /** * Gets the cached value of LockTask feature flags for a specific user. */