From f02420c5e1bcc8b2c278f272aca633fe6d2b4e88 Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Mon, 4 Apr 2016 18:52:21 +0100 Subject: [PATCH] Maybe decrypt user when quiet mode is disabled When quiet mode is disabled for a user and that user is not currently decrypted, we show a confirm credentials screen to trigger decryption of that user. Only if that was successful, do we actually disable quiet mode. Bug: 27764124 Change-Id: Ib1f649194d89e225dad62c14f3ddba1fa3d79da2 --- core/java/android/os/IUserManager.aidl | 2 ++ core/java/android/os/UserManager.java | 18 ++++++++++ .../internal/app/UnlaunchableAppActivity.java | 5 ++- .../phone/ManagedProfileController.java | 13 +++++-- .../android/server/LockSettingsService.java | 6 ++++ .../android/server/pm/UserManagerService.java | 36 +++++++++++++++++++ 6 files changed, 75 insertions(+), 5 deletions(-) diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 67d395954e1e0..55b0d2a153173 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -20,6 +20,7 @@ package android.os; import android.os.Bundle; import android.os.PersistableBundle; import android.content.pm.UserInfo; +import android.content.IntentSender; import android.content.RestrictionEntry; import android.graphics.Bitmap; import android.os.ParcelFileDescriptor; @@ -70,6 +71,7 @@ interface IUserManager { boolean markGuestForDeletion(int userHandle); void setQuietModeEnabled(int userHandle, boolean enableQuietMode); 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(); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index d5b3b35187013..086a9776aa8ff 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -29,6 +29,7 @@ import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentSender; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; @@ -1690,6 +1691,23 @@ 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. + * + * @return true if the quiet mode was disabled immediately + * @hide + */ + public boolean trySetQuietModeDisabled(@UserIdInt int userHandle, 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 diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index 27588e98dcafe..d24cefeecf077 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -107,9 +107,8 @@ 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).setQuietModeEnabled(mUserId, false); - - if (mTarget != null) { + if (UserManager.get(this).trySetQuietModeDisabled(mUserId, mTarget) + && mTarget != null) { try { startIntentSenderForResult(mTarget, -1, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java index 41eed565506d5..951b09681c0bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java @@ -15,6 +15,7 @@ package com.android.systemui.statusbar.phone; import android.app.ActivityManager; +import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -57,10 +58,18 @@ public class ManagedProfileController { } } - public void setWorkModeEnabled(boolean enabled) { + public void setWorkModeEnabled(boolean enableWorkMode) { synchronized (mProfiles) { for (UserInfo ui : mProfiles) { - mUserManager.setQuietModeEnabled(ui.id, !enabled); + 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); + } } } } diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index f2b4e5218ac3d..54237a980779d 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -702,6 +702,12 @@ public class LockSettingsService extends ILockSettings.Stub { } }; + // Check if the user is currently in quiet mode and start it otherwise + if (mUserManager.isQuietModeEnabled(new UserHandle(userId)) + && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { + mUserManager.setQuietModeEnabled(userId, false); + } + try { ActivityManagerNative.getDefault().unlockUser(userId, token, secret, listener); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 60ea2544cadc4..9b918f3fb9935 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -17,6 +17,9 @@ package com.android.server.pm; +import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -27,10 +30,12 @@ import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.IStopUserCallback; +import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentSender; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; @@ -692,6 +697,37 @@ public class UserManagerService extends IUserManager.Stub { } } + @Override + public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) { + if (mContext.getSystemService(StorageManager.class).isUserKeyUnlocked(userHandle) + || !mLockPatternUtils.isSecure(userHandle) + || !mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) { + // if the user is already unlocked, no need to show a profile challenge + setQuietModeEnabled(userHandle, false); + 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); + final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, + userHandle); + if (unlockIntent == null) { + return false; + } + if (target != null) { + unlockIntent.putExtra(Intent.EXTRA_INTENT, target); + } + unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + mContext.startActivity(unlockIntent); + } finally { + Binder.restoreCallingIdentity(identity); + } + return false; + } + @Override public void setUserEnabled(int userId) { checkManageUsersPermission("enable user");