Loading core/java/android/content/pm/flags.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -302,3 +302,10 @@ flag { bug: "332664521" is_fixed_read_only: true } flag { name: "delete_packages_silently_backport" namespace: "package_manager_service" description: "Feature flag to enable the holder of SYSTEM_APP_PROTECTION_SERVICE role to silently delete packages. To be deprecated by delete_packages_silently." bug: "361776825" } services/core/java/com/android/server/pm/PackageInstallerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; import android.content.IntentSender; Loading Loading @@ -201,6 +202,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements Manifest.permission.USE_FULL_SCREEN_INTENT ); private static final String ROLE_SYSTEM_APP_PROTECTION_SERVICE = "android.app.role.SYSTEM_APP_PROTECTION_SERVICE"; final PackageArchiver mPackageArchiver; private final Context mContext; Loading Loading @@ -1454,6 +1458,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements .createEvent(DevicePolicyEnums.UNINSTALL_PACKAGE) .setAdmin(callerPackageName) .write(); } else if (isSystemAppProtectionRoleHolder(snapshot, userId, callingUid)) { // Allow the SYSTEM_APP_PROTECTION_SERVICE role holder to silently uninstall, with a // clean calling identity to get DELETE_PACKAGES permission Binder.withCleanCallingIdentity(() -> mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags) ); } else { ApplicationInfo appInfo = snapshot.getApplicationInfo(callerPackageName, 0, userId); if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { Loading @@ -1475,6 +1485,29 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } private Boolean isSystemAppProtectionRoleHolder( @NonNull Computer snapshot, int userId, int callingUid) { if (!Flags.deletePackagesSilentlyBackport()) { return false; } String holderPackageName = Binder.withCleanCallingIdentity(() -> { RoleManager roleManager = mPm.mContext.getSystemService(RoleManager.class); if (roleManager == null) { return null; } List<String> holders = roleManager.getRoleHoldersAsUser( ROLE_SYSTEM_APP_PROTECTION_SERVICE, UserHandle.of(userId)); if (holders.isEmpty()) { return null; } return holders.get(0); }); if (holderPackageName == null) { return false; } return snapshot.getPackageUid(holderPackageName, /* flags= */ 0, userId) == callingUid; } @Override public void uninstallExistingPackage(VersionedPackage versionedPackage, String callerPackageName, IntentSender statusReceiver, int userId) { Loading Loading
core/java/android/content/pm/flags.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -302,3 +302,10 @@ flag { bug: "332664521" is_fixed_read_only: true } flag { name: "delete_packages_silently_backport" namespace: "package_manager_service" description: "Feature flag to enable the holder of SYSTEM_APP_PROTECTION_SERVICE role to silently delete packages. To be deprecated by delete_packages_silently." bug: "361776825" }
services/core/java/com/android/server/pm/PackageInstallerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; import android.content.IntentSender; Loading Loading @@ -201,6 +202,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements Manifest.permission.USE_FULL_SCREEN_INTENT ); private static final String ROLE_SYSTEM_APP_PROTECTION_SERVICE = "android.app.role.SYSTEM_APP_PROTECTION_SERVICE"; final PackageArchiver mPackageArchiver; private final Context mContext; Loading Loading @@ -1454,6 +1458,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements .createEvent(DevicePolicyEnums.UNINSTALL_PACKAGE) .setAdmin(callerPackageName) .write(); } else if (isSystemAppProtectionRoleHolder(snapshot, userId, callingUid)) { // Allow the SYSTEM_APP_PROTECTION_SERVICE role holder to silently uninstall, with a // clean calling identity to get DELETE_PACKAGES permission Binder.withCleanCallingIdentity(() -> mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags) ); } else { ApplicationInfo appInfo = snapshot.getApplicationInfo(callerPackageName, 0, userId); if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { Loading @@ -1475,6 +1485,29 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } private Boolean isSystemAppProtectionRoleHolder( @NonNull Computer snapshot, int userId, int callingUid) { if (!Flags.deletePackagesSilentlyBackport()) { return false; } String holderPackageName = Binder.withCleanCallingIdentity(() -> { RoleManager roleManager = mPm.mContext.getSystemService(RoleManager.class); if (roleManager == null) { return null; } List<String> holders = roleManager.getRoleHoldersAsUser( ROLE_SYSTEM_APP_PROTECTION_SERVICE, UserHandle.of(userId)); if (holders.isEmpty()) { return null; } return holders.get(0); }); if (holderPackageName == null) { return false; } return snapshot.getPackageUid(holderPackageName, /* flags= */ 0, userId) == callingUid; } @Override public void uninstallExistingPackage(VersionedPackage versionedPackage, String callerPackageName, IntentSender statusReceiver, int userId) { Loading