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

Commit ade4372e authored by Hai Zhang's avatar Hai Zhang
Browse files

Add flags parameter for managing role holders.

This change allows passing a flag parameter when managing role
holders, including a DONT_KILL_APP flag that can be used by the
request role dialog.

Bug: 123429697
Test: manual
Change-Id: If4d81e9049f9b9e784e9b82f21a3b1766b766282
parent f2cbd312
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ public class Role {
     * Grant this role to an application.
     *
     * @param packageName the package name of the application to be granted this role to
     * @param mayKillApp whether this application may be killed due to changes
     * @param dontKillApp whether this application should not be killed despite changes
     * @param overrideDisabledSystemPackageAndUserSetAndFixedPermissions whether to ignore the
     *                                                                   permissions of a disabled
     *                                                                   system package (if this
@@ -428,7 +428,7 @@ public class Role {
     * @param setPermissionsSystemFixed whether the permissions will be granted as system-fixed
     * @param context the {@code Context} to retrieve system services
     */
    public void grant(@NonNull String packageName, boolean mayKillApp,
    public void grant(@NonNull String packageName, boolean dontKillApp,
            boolean overrideDisabledSystemPackageAndUserSetAndFixedPermissions,
            boolean setPermissionsSystemFixed, @NonNull Context context) {
        boolean permissionOrAppOpChanged = Permissions.grant(packageName, mPermissions,
@@ -451,8 +451,8 @@ public class Role {
            mBehavior.grant(this, packageName, context);
        }

        if (mayKillApp && !Permissions.isRuntimePermissionsSupported(packageName, context)
                && permissionOrAppOpChanged) {
        if (!dontKillApp && permissionOrAppOpChanged && !Permissions.isRuntimePermissionsSupported(
                packageName, context)) {
            killApp(packageName, context);
        }
    }
@@ -461,11 +461,11 @@ public class Role {
     * Revoke this role from an application.
     *
     * @param packageName the package name of the application to be granted this role to
     * @param mayKillApp whether this application may be killed due to changes
     * @param dontKillApp whether this application should not be killed despite changes
     * @param overrideSystemFixedPermissions whether system-fixed permissions can be revoked
     * @param context the {@code Context} to retrieve system services
     */
    public void revoke(@NonNull String packageName, boolean mayKillApp,
    public void revoke(@NonNull String packageName, boolean dontKillApp,
            boolean overrideSystemFixedPermissions, @NonNull Context context) {
        RoleManager roleManager = context.getSystemService(RoleManager.class);
        List<String> otherRoleNames = roleManager.getHeldRolesFromController(packageName);
@@ -500,7 +500,7 @@ public class Role {
            mBehavior.revoke(this, packageName, context);
        }

        if (mayKillApp && permissionOrAppOpChanged) {
        if (!dontKillApp && permissionOrAppOpChanged) {
            killApp(packageName, context);
        }
    }
+55 −25
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @Override
    public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
    public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, int flags,
            @NonNull RoleManagerCallback callback) {
        if (callback == null) {
            Log.e(LOG_TAG, "callback cannot be null");
@@ -109,11 +109,15 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> addRoleHolder(roleName, packageName, callback));
        if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> addRoleHolder(roleName, packageName, flags, callback));
    }

    @Override
    public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
    public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, int flags,
            @NonNull RoleManagerCallback callback) {
        if (callback == null) {
            Log.e(LOG_TAG, "callback cannot be null");
@@ -129,11 +133,15 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> removeRoleHolder(roleName, packageName, callback));
        if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> removeRoleHolder(roleName, packageName, flags, callback));
    }

    @Override
    public void onClearRoleHolders(@NonNull String roleName,
    public void onClearRoleHolders(@NonNull String roleName, int flags,
            @NonNull RoleManagerCallback callback) {
        if (callback == null) {
            Log.e(LOG_TAG, "callback cannot be null");
@@ -144,7 +152,11 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> clearRoleHolders(roleName, callback));
        if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
            callback.onFailure();
            return;
        }
        mWorkerHandler.post(() -> clearRoleHolders(roleName, flags, callback));
    }

    @Override
@@ -252,12 +264,11 @@ public class RoleControllerServiceImpl extends RoleControllerService {
                String packageName = currentPackageNames.get(currentPackageNamesIndex);

                if (role.isPackageQualified(packageName, this)) {
                    // TODO: STOPSHIP: Pass in appropriate arguments.
                    role.grant(packageName, true, false, false, this);
                    addRoleHolderInternal(role, packageName, false, false, true);
                } else {
                    Log.i(LOG_TAG, "Removing package that no longer qualifies for the role,"
                            + " package: " + packageName + ", role: " + roleName);
                    removeRoleHolderInternal(role, packageName);
                    removeRoleHolderInternal(role, packageName, false);
                }
            }

@@ -309,7 +320,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {

                    Log.i(LOG_TAG, "Removing extraneous package for an exclusive role, package: "
                            + packageName + ", role: " + roleName);
                    removeRoleHolderInternal(role, packageName);
                    removeRoleHolderInternal(role, packageName, false);
                }
            }
        }
@@ -320,7 +331,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @WorkerThread
    private void addRoleHolder(@NonNull String roleName, @NonNull String packageName,
    private void addRoleHolder(@NonNull String roleName, @NonNull String packageName, int flags,
            @NonNull RoleManagerCallback callback) {
        Role role = Roles.get(this).get(roleName);
        if (role == null) {
@@ -355,7 +366,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
                    continue;
                }

                boolean removed = removeRoleHolderInternal(role, currentPackageName);
                boolean removed = removeRoleHolderInternal(role, currentPackageName, false);
                if (!removed) {
                    // TODO: Clean up?
                    callback.onFailure();
@@ -364,7 +375,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            }
        }

        added = addRoleHolderInternal(role, packageName, true, added);
        boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
        added = addRoleHolderInternal(role, packageName, dontKillApp, true, added);
        if (!added) {
            callback.onFailure();
            return;
@@ -376,7 +388,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @WorkerThread
    private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName,
    private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName, int flags,
            @NonNull RoleManagerCallback callback) {
        Role role = Roles.get(this).get(roleName);
        if (role == null) {
@@ -390,7 +402,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            return;
        }

        boolean removed = removeRoleHolderInternal(role, packageName);
        boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
        boolean removed = removeRoleHolderInternal(role, packageName, dontKillApp);
        if (!removed) {
            callback.onFailure();
            return;
@@ -407,7 +420,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @WorkerThread
    private void clearRoleHolders(@NonNull String roleName, @NonNull RoleManagerCallback callback) {
    private void clearRoleHolders(@NonNull String roleName, int flags,
            @NonNull RoleManagerCallback callback) {
        Role role = Roles.get(this).get(roleName);
        if (role == null) {
            Log.e(LOG_TAG, "Unknown role: " + roleName);
@@ -420,7 +434,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            return;
        }

        boolean cleared = clearRoleHoldersInternal(role);
        boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
        boolean cleared = clearRoleHoldersInternal(role, dontKillApp);
        if (!cleared) {
            callback.onFailure();
        }
@@ -438,16 +453,17 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    @WorkerThread
    private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
            boolean overrideDisabledSystemPackageAndUserSetAndFixedPermissions) {
        return addRoleHolderInternal(role, packageName,
        return addRoleHolderInternal(role, packageName, false,
                overrideDisabledSystemPackageAndUserSetAndFixedPermissions, false);
    }

    @WorkerThread
    private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
            boolean overrideDisabledSystemPackageAndUserSetAndFixedPermissions, boolean added) {
            boolean dontKillApp, boolean overrideDisabledSystemPackageAndUserSetAndFixedPermissions,
            boolean added) {
        // TODO: STOPSHIP: Pass in appropriate arguments.
        role.grant(packageName, true, overrideDisabledSystemPackageAndUserSetAndFixedPermissions,
                false, this);
        role.grant(packageName, dontKillApp,
                overrideDisabledSystemPackageAndUserSetAndFixedPermissions, false, this);

        String roleName = role.getName();
        if (!added) {
@@ -461,7 +477,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @WorkerThread
    private boolean removeRoleHolderInternal(@NonNull Role role, @NonNull String packageName) {
    private boolean removeRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
            boolean dontKillApp) {
        ApplicationInfo applicationInfo = PackageUtils.getApplicationInfo(packageName, this);
        if (applicationInfo == null) {
            Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName);
@@ -469,7 +486,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {

        if (applicationInfo != null) {
            // TODO: STOPSHIP: Pass in appropriate arguments.
            role.revoke(packageName, true, false, this);
            role.revoke(packageName, dontKillApp, false, this);
        }

        String roleName = role.getName();
@@ -482,7 +499,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
    }

    @WorkerThread
    private boolean clearRoleHoldersInternal(@NonNull Role role) {
    private boolean clearRoleHoldersInternal(@NonNull Role role, boolean dontKillApp) {
        String roleName = role.getName();
        List<String> packageNames = mRoleManager.getRoleHolders(roleName);
        boolean cleared = true;
@@ -490,7 +507,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
        int packageNamesSize = packageNames.size();
        for (int i = 0; i < packageNamesSize; i++) {
            String packageName = packageNames.get(i);
            boolean removed = removeRoleHolderInternal(role, packageName);
            boolean removed = removeRoleHolderInternal(role, packageName, dontKillApp);
            if (!removed) {
                cleared = false;
            }
@@ -529,4 +546,17 @@ public class RoleControllerServiceImpl extends RoleControllerService {
        // should at least show a notification?
        return addRoleHolderInternal(role, fallbackPackageName, true);
    }

    private static boolean checkFlags(int flags, int allowedFlags) {
        if ((flags & allowedFlags) != flags) {
            Log.e(LOG_TAG, "flags is invalid, flags: 0x" + Integer.toHexString(flags)
                    + ", allowed flags: 0x" + Integer.toHexString(allowedFlags));
            return false;
        }
        return true;
    }

    private static boolean hasFlag(int flags, int flag) {
        return (flags & flag) == flag;
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ public class DefaultAppFragment extends SettingsFragment
            Log.i(LOG_TAG, "Trying to set default app while another request is on-going");
            return;
        }
        liveData.setRoleHolderAsUser(mRoleName, packageName, true, mUser, requireContext());
        liveData.setRoleHolderAsUser(mRoleName, packageName, true, 0, mUser, requireContext());
    }

    private void setNoneDefaultApp() {
@@ -239,6 +239,6 @@ public class DefaultAppFragment extends SettingsFragment
            Log.i(LOG_TAG, "Trying to set default app while another request is on-going");
            return;
        }
        liveData.clearRoleHoldersAsUser(mRoleName, mUser, requireContext());
        liveData.clearRoleHoldersAsUser(mRoleName, 0, mUser, requireContext());
    }
}
+9 −6
Original line number Diff line number Diff line
@@ -52,11 +52,12 @@ public class ManageRoleHolderStateLiveData extends LiveData<Integer> {
     * @param roleName the name of the role
     * @param packageName the package name of the application
     * @param add whether to add or remove the application as a role holder
     * @param flags optional behavior flags
     * @param user the user to manage the role holder for
     * @param context the {@code Context} to retrieve system services
     */
    public void setRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
            boolean add, @NonNull UserHandle user, @NonNull Context context) {
            boolean add, int flags, @NonNull UserHandle user, @NonNull Context context) {
        if (getValue() != STATE_IDLE) {
            Log.e(LOG_TAG, "Already (tried) managing role holders, requested role: " + roleName
                    + ", requested package: " + packageName);
@@ -90,9 +91,10 @@ public class ManageRoleHolderStateLiveData extends LiveData<Integer> {
            }
        };
        if (add) {
            roleManager.addRoleHolderAsUser(roleName, packageName, user, executor, callback);
            roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback);
        } else {
            roleManager.removeRoleHolderAsUser(roleName, packageName, user, executor, callback);
            roleManager.removeRoleHolderAsUser(roleName, packageName, flags, user, executor,
                    callback);
        }
    }

@@ -101,11 +103,12 @@ public class ManageRoleHolderStateLiveData extends LiveData<Integer> {
     * state is not {@link #STATE_IDLE}.
     *
     * @param roleName the name of the role
     * @param flags optional behavior flags
     * @param user the user to manage the role holder for
     * @param context the {@code Context} to retrieve system services
     */
    public void clearRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user,
            @NonNull Context context) {
    public void clearRoleHoldersAsUser(@NonNull String roleName, int flags,
            @NonNull UserHandle user, @NonNull Context context) {
        if (getValue() != STATE_IDLE) {
            Log.e(LOG_TAG, "Already (tried) managing role holders, requested role: " + roleName);
            return;
@@ -133,7 +136,7 @@ public class ManageRoleHolderStateLiveData extends LiveData<Integer> {
                setValue(STATE_FAILURE);
            }
        };
        roleManager.clearRoleHoldersAsUser(roleName, user, executor, callback);
        roleManager.clearRoleHoldersAsUser(roleName, flags, user, executor, callback);
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ public class RequestRoleFragment extends DialogFragment {

    private void addRoleHolder() {
        mViewModel.getLiveData().setRoleHolderAsUser(mRoleName, mPackageName, true,
                Process.myUserHandle(), requireContext());
                RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, Process.myUserHandle(),
                requireContext());
    }

    private void setResultOkAndFinish() {
Loading