Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59e33304 authored by Nino Jagar's avatar Nino Jagar
Browse files

Allow app protection role to uninstall packages

Bug: 361776825
Test: End-to-end
Flag: android.content.pm.delete_packages_silently_backport

Change-Id: I288a95ec9084e5acfac333de88d2741122a39386
parent 600835de
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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"
}
+33 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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) {
@@ -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) {