diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index 6193a8e9005b3..428de9e9adbb3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -30,6 +30,7 @@ import android.content.IntentSender; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; +import android.util.Log; import android.view.View; import android.view.ViewParent; @@ -47,6 +48,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.policy.KeyguardStateController; +import java.util.concurrent.atomic.AtomicReference; + import javax.inject.Inject; import javax.inject.Singleton; @@ -54,7 +57,8 @@ import javax.inject.Singleton; */ @Singleton public class StatusBarRemoteInputCallback implements Callback, Callbacks, - StatusBarStateController.StateListener { + StatusBarStateController.StateListener, KeyguardStateController.Callback { + private static final String TAG = StatusBarRemoteInputCallback.class.getSimpleName(); private final KeyguardStateController mKeyguardStateController; private final SysuiStatusBarStateController mStatusBarStateController; @@ -72,6 +76,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, private int mDisabled2; protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver(); private Handler mMainHandler = new Handler(); + private final AtomicReference mPendingConfirmCredentialIntent = new AtomicReference(); /** */ @@ -98,6 +103,9 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, mCommandQueue.addCallback(this); mActivityIntentHelper = new ActivityIntentHelper(mContext); mGroupManager = groupManager; + // Listen to onKeyguardShowingChanged in case a managed profile needs to be unlocked + // once the primary profile's keyguard is no longer shown. + mKeyguardStateController.addCallback(this); } @Override @@ -201,12 +209,39 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, // Clear pending remote view, as we do not want to trigger pending remote input view when // it's called by other code mPendingWorkRemoteInputView = null; - // Begin old BaseStatusBar.startWorkChallengeIfNecessary. - final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, - null, userId); + + final Intent newIntent = createConfirmDeviceCredentialIntent( + userId, intendSender, notificationKey); if (newIntent == null) { + Log.w(TAG, String.format("Cannot create intent to unlock user %d", userId)); return false; } + + mPendingConfirmCredentialIntent.set(newIntent); + + // If the Keyguard is currently showing, starting the ConfirmDeviceCredentialActivity + // would cause it to pause, not letting the user actually unlock the managed profile. + // Instead, wait until we receive a callback indicating it is no longer showing and + // then start the pending intent. + if (mKeyguardStateController.isShowing()) { + // Do nothing, since the callback will get the pending intent and start it. + Log.w(TAG, String.format("Keyguard is showing, waiting until it's not")); + } else { + startPendingConfirmDeviceCredentialIntent(); + } + + return true; + } + + private Intent createConfirmDeviceCredentialIntent( + int userId, IntentSender intendSender, String notificationKey) { + final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, + null, userId); + + if (newIntent == null) { + return null; + } + final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender); callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey); @@ -222,14 +257,40 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, newIntent.putExtra( Intent.EXTRA_INTENT, callBackPendingIntent.getIntentSender()); + + return newIntent; + } + + private void startPendingConfirmDeviceCredentialIntent() { + final Intent pendingIntent = mPendingConfirmCredentialIntent.getAndSet(null); + if (pendingIntent == null) { + return; + } + try { - ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent, + if (mKeyguardStateController.isShowing()) { + Log.w(TAG, "Keyguard is showing while starting confirm device credential intent."); + } + ActivityManager.getService().startConfirmDeviceCredentialIntent(pendingIntent, null /*options*/); } catch (RemoteException ex) { // ignore } - return true; - // End old BaseStatusBar.startWorkChallengeIfNecessary. + } + + @Override + public void onKeyguardShowingChanged() { + if (mKeyguardStateController.isShowing()) { + // In order to avoid jarring UX where/ the managed profile challenge is shown and + // immediately dismissed, do not attempt to start the confirm device credential + // activity if the keyguard is still showing. + if (mPendingConfirmCredentialIntent.get() != null) { + Log.w(TAG, "There's a pending unlock intent but keyguard is still showing, abort."); + } + return; + } + + startPendingConfirmDeviceCredentialIntent(); } @Override