diff options
| author | 2017-12-05 19:40:28 +0000 | |
|---|---|---|
| committer | 2017-12-15 16:27:48 +0000 | |
| commit | b7e6fd49a5500c6182484335b03343bfdbd6b70b (patch) | |
| tree | 289d7bcd136f8066dc4b53c3809083ba6c70a4eb | |
| parent | 5c9d80199e48322ab9939bc78d3ffeb224817a4c (diff) | |
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
5 files changed, 125 insertions, 116 deletions
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 9c90c3802caf..80c7c89b499f 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -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); } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index fb60bbb483b1..2412009e9d98 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -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(); } @@ -2141,27 +2160,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 * icon to be able to distinguish it from the original icon. For badging an diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index 8016a6559bcc..2eadaf3a06b0 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -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); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java index 316bd5bcaca2..7f4deb0372f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java @@ -61,14 +61,10 @@ public class ManagedProfileControllerImpl implements ManagedProfileController { public void setWorkModeEnabled(boolean enableWorkMode) { synchronized (mProfiles) { for (UserInfo ui : mProfiles) { - if (enableWorkMode) { - if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) { - StatusBarManager statusBarManager = (StatusBarManager) mContext - .getSystemService(android.app.Service.STATUS_BAR_SERVICE); - statusBarManager.collapsePanels(); - } - } else { - mUserManager.setQuietModeEnabled(ui.id, true); + if (!mUserManager.trySetQuietModeEnabled(!enableWorkMode, UserHandle.of(ui.id))) { + StatusBarManager statusBarManager = (StatusBarManager) mContext + .getSystemService(android.app.Service.STATUS_BAR_SERVICE); + statusBarManager.collapsePanels(); } } } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 03cd4f1d3269..2e4732469cea 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -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,48 +784,76 @@ 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) { - synchronized (mUsersLock) { - profile = getUserInfoLU(userHandle); - parent = getProfileParentLU(userHandle); + 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) { - profile.flags ^= UserInfo.FLAG_QUIET_MODE; - writeUserLP(getUserDataLU(profile.id)); - changed = true; + if (profile.isQuietModeEnabled() == enableQuietMode) { + Slog.i(LOG_TAG, "Quiet mode is already " + enableQuietMode); + return; } + profile.flags ^= UserInfo.FLAG_QUIET_MODE; + profileUserData = getUserDataLU(profile.id); } - if (changed) { - long identity = Binder.clearCallingIdentity(); - try { - if (enableQuietMode) { - ActivityManager.getService().stopUser(userHandle, /* force */true, null); - LocalServices.getService(ActivityManagerInternal.class) - .killForegroundAppsForUser(userHandle); - } else { - IProgressListener callback = target != null - ? new DisableQuietModeUserUnlockedCallback(target) - : null; - ActivityManager.getService().startUserInBackgroundWithListener( - userHandle, callback); - } - } catch (RemoteException e) { - Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e); - } finally { - Binder.restoreCallingIdentity(identity); + synchronized (mPackagesLock) { + writeUserLP(profileUserData); + } + try { + if (enableQuietMode) { + ActivityManager.getService().stopUser(userHandle, /* force */true, null); + LocalServices.getService(ActivityManagerInternal.class) + .killForegroundAppsForUser(userHandle); + } else { + IProgressListener callback = target != null + ? new DisableQuietModeUserUnlockedCallback(target) + : null; + ActivityManager.getService().startUserInBackgroundWithListener( + userHandle, callback); } - - broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(), - enableQuietMode); + } catch (RemoteException e) { + // Should not happen, same process. + e.rethrowAsRuntimeException(); } + broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(), + enableQuietMode); } @Override @@ -842,54 +870,42 @@ 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); - // We should use userHandle not credentialOwnerUserId here, as even if it is unified - // lock, confirm screenlock page will know and show personal challenge, and unlock - // work profile when personal challenge is correct - final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, - userHandle); - if (unlockIntent == null) { - return false; - } - final Intent callBackIntent = new Intent( - ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK); - if (target != null) { - callBackIntent.putExtra(Intent.EXTRA_INTENT, target); - } - callBackIntent.putExtra(Intent.EXTRA_USER_ID, userHandle); - callBackIntent.setPackage(mContext.getPackageName()); - callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, - 0, - callBackIntent, - PendingIntent.FLAG_CANCEL_CURRENT | - PendingIntent.FLAG_ONE_SHOT | - PendingIntent.FLAG_IMMUTABLE); - // After unlocking the challenge, it will disable quiet mode and run the original - // intentSender - 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); + // otherwise, we show a profile challenge to trigger decryption of the user + final KeyguardManager km = (KeyguardManager) mContext.getSystemService( + Context.KEYGUARD_SERVICE); + // We should use userHandle not credentialOwnerUserId here, as even if it is unified + // lock, confirm screenlock page will know and show personal challenge, and unlock + // work profile when personal challenge is correct + final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, + userHandle); + if (unlockIntent == null) { + return; } - return false; + final Intent callBackIntent = new Intent( + ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK); + if (target != null) { + callBackIntent.putExtra(Intent.EXTRA_INTENT, target); + } + callBackIntent.putExtra(Intent.EXTRA_USER_ID, userHandle); + callBackIntent.setPackage(mContext.getPackageName()); + callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, + 0, + callBackIntent, + PendingIntent.FLAG_CANCEL_CURRENT | + PendingIntent.FLAG_ONE_SHOT | + PendingIntent.FLAG_IMMUTABLE); + // After unlocking the challenge, it will disable quiet mode and run the original + // intentSender + unlockIntent.putExtra(Intent.EXTRA_INTENT, pendingIntent.getIntentSender()); + unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + mContext.startActivity(unlockIntent); } @Override |