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

Commit b7e6fd49 authored by Tony Mak's avatar Tony Mak
Browse files

Merge setQuietModeEnabled and trySetQuietModeDisabled into one API

This is the first step to introduce a public API to toggle work mode.

All the callers actually have the similar bit of logic like this:
if (workModeOn) {
    trySetQuietModeDisabled(..)
} else {
    setQuietModeEnabled(...)
}
So, let's merge them into one API.

Test: Quick Settings -> Toggle work mode
Test: Settings -> Work profile settings -> Toggle work mode
Test: Turn off work mode -> Settings -> Turn on work mode in the suggestion
Test: Turn on work mode through tapping on work app

TODO: Allow foreground default Launcher to call the API
TODO: Allow privileged apps to call the API
TODO: Remove @hide
TODO: Write a CTS to toggle the work mode once it is public API

BUG: 70212757

Change-Id: Ibcdd43458c236eca929c5f934fea61be2e2be863
parent 5c9d8019
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -79,9 +79,7 @@ interface IUserManager {
    void setDefaultGuestRestrictions(in Bundle restrictions);
    Bundle getDefaultGuestRestrictions();
    boolean markGuestForDeletion(int userHandle);
    void setQuietModeEnabled(int userHandle, boolean enableQuietMode, in IntentSender target);
    boolean isQuietModeEnabled(int userHandle);
    boolean trySetQuietModeDisabled(int userHandle, in IntentSender target);
    void setSeedAccountData(int userHandle, in String accountName,
            in String accountType, in PersistableBundle accountOptions, boolean persist);
    String getSeedAccountName();
@@ -99,4 +97,5 @@ interface IUserManager {
    boolean isUserRunning(int userId);
    boolean isUserNameSet(int userHandle);
    boolean hasRestrictedProfiles();
    boolean trySetQuietModeEnabled(boolean enableQuietMode, int userHandle, in IntentSender target);
}
+23 −25
Original line number Diff line number Diff line
@@ -2111,15 +2111,34 @@ public class UserManager {
    }

    /**
     * Set quiet mode of a managed profile.
     * @see {@link #trySetQuietModeEnabled(boolean, UserHandle, IntentSender)}
     *
     * @hide
     */
    public boolean trySetQuietModeEnabled(boolean enableQuietMode, @NonNull UserHandle userHandle) {
        return trySetQuietModeEnabled(enableQuietMode, userHandle, null);
    }

    /**
     * Set quiet mode of a managed profile. If quiet mode is on, work apps don't run, generate
     * notifications, or consume data or the battery. You also can’t access work apps or widgets.
     * <p>
     * If user credential is needed, confirm credential screen would be shown to user.
     *
     * @param enableQuietMode Whether work mode should be enabled or disabled.
     * @param userHandle The user handle of the profile.
     * @param enableQuietMode Whether quiet mode should be enabled or disabled.
     * @param target The target to start once work mode is enabled.
     * @return {@code false} confirm credential screen is shown in order turn off quiet mode,
     *         {@code true} otherwise.
     * @throws IllegalArgumentException if enableWorkMode is {@code false} while target is not null.
     * @throws IllegalArgumentException if userHandle is not a managed profile.
     * @hide
     */
    public void setQuietModeEnabled(@UserIdInt int userHandle, boolean enableQuietMode) {
    public boolean trySetQuietModeEnabled(
            boolean enableQuietMode, @NonNull UserHandle userHandle, IntentSender target) {
        try {
            mService.setQuietModeEnabled(userHandle, enableQuietMode, null);
            return mService.trySetQuietModeEnabled(
                    enableQuietMode, userHandle.getIdentifier(), target);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
@@ -2140,27 +2159,6 @@ public class UserManager {
        }
    }

    /**
     * Tries disabling quiet mode for a given user. If the user is still locked, we unlock the user
     * first by showing the confirm credentials screen and disable quiet mode upon successful
     * unlocking. If the user is already unlocked, we call through to {@link #setQuietModeEnabled}
     * directly.
     *
     * @param userHandle The user that is going to disable quiet mode.
     * @param target The target to launch when the user is unlocked.
     * @return {@code true} if quiet mode is disabled without showing confirm credentials screen,
     *         {@code false} otherwise.
     * @hide
     */
    public boolean trySetQuietModeDisabled(
            @UserIdInt int userHandle, @Nullable IntentSender target) {
        try {
            return mService.trySetQuietModeDisabled(userHandle, target);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * If the target user is a managed profile of the calling user or the caller
     * is itself a managed profile, then this returns a badged copy of the given
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class UnlaunchableAppActivity extends Activity
    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
            UserManager.get(this).trySetQuietModeDisabled(mUserId, mTarget);
            UserManager.get(this).trySetQuietModeEnabled(false, UserHandle.of(mUserId), mTarget);
        }
    }

+4 −8
Original line number Diff line number Diff line
@@ -61,15 +61,11 @@ public class ManagedProfileControllerImpl implements ManagedProfileController {
    public void setWorkModeEnabled(boolean enableWorkMode) {
        synchronized (mProfiles) {
            for (UserInfo ui : mProfiles) {
                if (enableWorkMode) {
                    if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
                if (!mUserManager.trySetQuietModeEnabled(!enableWorkMode, UserHandle.of(ui.id))) {
                    StatusBarManager statusBarManager = (StatusBarManager) mContext
                            .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
                    statusBarManager.collapsePanels();
                }
                } else {
                    mUserManager.setQuietModeEnabled(ui.id, true);
                }
            }
        }
    }
+96 −80
Original line number Diff line number Diff line
@@ -386,7 +386,7 @@ public class UserManagerService extends IUserManager.Stub {
    /**
     * Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
     *
     * @see {@link #trySetQuietModeDisabled(int, IntentSender)}
     * @see {@link #trySetQuietModeEnabled(boolean, int, IntentSender)}
     */
    private class DisableQuietModeUserUnlockedCallback extends IProgressListener.Stub {
        private final IntentSender mTarget;
@@ -784,27 +784,58 @@ public class UserManagerService extends IUserManager.Stub {
    }

    @Override
    public void setQuietModeEnabled(int userHandle, boolean enableQuietMode, IntentSender target) {
        checkManageUsersPermission("silence profile");
        boolean changed = false;
        UserInfo profile, parent;
        synchronized (mPackagesLock) {
    public boolean trySetQuietModeEnabled(
            boolean enableQuietMode, int userHandle, @Nullable IntentSender target) {
        if (enableQuietMode && target != null) {
            throw new IllegalArgumentException(
                    "target should only be specified when we are disabling quiet mode.");
        }

        checkManageUsersPermission("trySetQuietModeEnabled");

        final long identity = Binder.clearCallingIdentity();
        try {
            if (enableQuietMode) {
                setQuietModeEnabled(userHandle, true /* enableQuietMode */, target);
                return true;
            } else {
                boolean needToShowConfirmCredential =
                        mLockPatternUtils.isSecure(userHandle)
                                && !StorageManager.isUserKeyUnlocked(userHandle);
                if (needToShowConfirmCredential) {
                    showConfirmCredentialToDisableQuietMode(userHandle, target);
                    return false;
                } else {
                    setQuietModeEnabled(userHandle, false /* enableQuietMode */, target);
                    return true;
                }
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    private void setQuietModeEnabled(
            int userHandle, boolean enableQuietMode, IntentSender target) {
        final UserInfo profile, parent;
        final UserData profileUserData;
        synchronized (mUsersLock) {
            profile = getUserInfoLU(userHandle);
            parent = getProfileParentLU(userHandle);

            }
            if (profile == null || !profile.isManagedProfile()) {
                throw new IllegalArgumentException("User " + userHandle + " is not a profile");
            }
            if (profile.isQuietModeEnabled() != enableQuietMode) {
            if (profile.isQuietModeEnabled() == enableQuietMode) {
                Slog.i(LOG_TAG, "Quiet mode is already " + enableQuietMode);
                return;
            }
            profile.flags ^= UserInfo.FLAG_QUIET_MODE;
                writeUserLP(getUserDataLU(profile.id));
                changed = true;
            profileUserData = getUserDataLU(profile.id);
        }
        synchronized (mPackagesLock) {
            writeUserLP(profileUserData);
        }
        if (changed) {
            long identity = Binder.clearCallingIdentity();
        try {
            if (enableQuietMode) {
                ActivityManager.getService().stopUser(userHandle, /* force */true, null);
@@ -818,15 +849,12 @@ public class UserManagerService extends IUserManager.Stub {
                        userHandle, callback);
            }
        } catch (RemoteException e) {
                Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e);
            } finally {
                Binder.restoreCallingIdentity(identity);
            // Should not happen, same process.
            e.rethrowAsRuntimeException();
        }

        broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(),
                enableQuietMode);
    }
    }

    @Override
    public boolean isQuietModeEnabled(int userHandle) {
@@ -842,19 +870,11 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    @Override
    public boolean trySetQuietModeDisabled(
    /**
     * Show confirm credential screen to unlock user in order to turn off quiet mode.
     */
    private void showConfirmCredentialToDisableQuietMode(
            @UserIdInt int userHandle, @Nullable IntentSender target) {
        checkManageUsersPermission("silence profile");
        if (StorageManager.isUserKeyUnlocked(userHandle)
                || !mLockPatternUtils.isSecure(userHandle)) {
            // if the user is already unlocked, no need to show a profile challenge
            setQuietModeEnabled(userHandle, false, target);
            return true;
        }

        long identity = Binder.clearCallingIdentity();
        try {
        // otherwise, we show a profile challenge to trigger decryption of the user
        final KeyguardManager km = (KeyguardManager) mContext.getSystemService(
                Context.KEYGUARD_SERVICE);
@@ -864,7 +884,7 @@ public class UserManagerService extends IUserManager.Stub {
        final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
                userHandle);
        if (unlockIntent == null) {
                return false;
            return;
        }
        final Intent callBackIntent = new Intent(
                ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK);
@@ -886,10 +906,6 @@ public class UserManagerService extends IUserManager.Stub {
        unlockIntent.putExtra(Intent.EXTRA_INTENT, pendingIntent.getIntentSender());
        unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        mContext.startActivity(unlockIntent);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
        return false;
    }

    @Override