diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index cb38d522f3bdd..0cdf7bf62f55a 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -166,9 +166,10 @@ final class DeletePackageHelper { if (PackageManagerServiceUtils.isSystemApp(uninstalledPs)) { UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); - if (userInfo == null || !userInfo.isAdmin()) { + if (userInfo == null || (!userInfo.isAdmin() && !mUserManagerInternal.getUserInfo( + mUserManagerInternal.getProfileParentId(userId)).isAdmin())) { Slog.w(TAG, "Not removing package " + packageName - + " as only admin user may downgrade system apps"); + + " as only admin user (or their profile) may downgrade system apps"); EventLog.writeEvent(0x534e4554, "170646036", -1, packageName); return PackageManager.DELETE_FAILED_USER_RESTRICTED; } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt index c9598bdc88231..e30f3d26119fc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt @@ -69,13 +69,34 @@ class DeletePackageHelperTest { } @Test - fun deleteSystemPackageFailsIfNotAdmin() { + fun deleteSystemPackageFailsIfNotAdminAndNotProfile() { val ps = mPms.mSettings.getPackageLPr("a.data.package") whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true) whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(UserInfo(1, "test", 0)) + whenever(mUserManagerInternal.getProfileParentId(1)).thenReturn(1) val dph = DeletePackageHelper(mPms) - val result = dph.deletePackageX("a.data.package", 1L, 1, 0, false) + val result = dph.deletePackageX("a.data.package", 1L, 1, + PackageManager.DELETE_SYSTEM_APP, false) + + assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED) + } + + @Test + fun deleteSystemPackageFailsIfProfileOfNonAdmin() { + val userId = 1 + val parentId = 5 + val ps = mPms.mSettings.getPackageLPr("a.data.package") + whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true) + whenever(mUserManagerInternal.getUserInfo(userId)).thenReturn( + UserInfo(userId, "test", UserInfo.FLAG_PROFILE)) + whenever(mUserManagerInternal.getProfileParentId(userId)).thenReturn(parentId) + whenever(mUserManagerInternal.getUserInfo(parentId)).thenReturn( + UserInfo(userId, "testparent", 0)) + + val dph = DeletePackageHelper(mPms) + val result = dph.deletePackageX("a.data.package", 1L, userId, + PackageManager.DELETE_SYSTEM_APP, false) assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED) } @@ -93,4 +114,23 @@ class DeletePackageHelperTest { assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED) } + + @Test + fun deleteSystemPackageSucceedsIfProfileOfAdmin() { + val userId = 1 + val parentId = 5 + val ps = mPms.mSettings.getPackageLPr("a.data.package") + whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true) + whenever(mUserManagerInternal.getUserInfo(userId)).thenReturn( + UserInfo(userId, "test", UserInfo.FLAG_PROFILE)) + whenever(mUserManagerInternal.getProfileParentId(userId)).thenReturn(parentId) + whenever(mUserManagerInternal.getUserInfo(parentId)).thenReturn( + UserInfo(userId, "testparent", UserInfo.FLAG_ADMIN)) + + val dph = DeletePackageHelper(mPms) + val result = dph.deletePackageX("a.data.package", 1L, userId, + PackageManager.DELETE_SYSTEM_APP, false) + + assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED) + } } \ No newline at end of file