summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eran Messeri <eranm@google.com> 2020-04-13 22:41:45 +0100
committer Eran Messeri <eranm@google.com> 2020-04-28 09:23:31 +0100
commit145d69a43d6333d3675746e59a121078f76ebdfb (patch)
tree20e41e06e191d22c854b450e08216b190fe1d43c
parent2b40d3c462b59c18a3b62a813c26b6e483795491 (diff)
Fix work challenge lockscreen being dismissed
Fix the issue of the work challenge lockscreen being dismissed under the following circumstances: * The device has a managed (work) profile. * The work profile has a separate challenge than the primary one. * The phone is locked, and on the lock screen there's a notification associated with an activity in the work profile. In these circumstances, when the user double-taps the notification from the work profile, they have to enter the primary challenge first and then the work one. However, the issue is that the work challenge is shown for a fraction of a second, after the user enters the primary challenge, and then dismissed. The issue is caused by the lock screen still being shown when the ConfirmDeviceCredentialActivity is started. It is legal to start an activity when the device is locked, but it will be paused. The fix is to delay starting the ConfirmDeviceCredentialActivity until the lock screen is no longer shown. This is done by listening to the onKeyguardShowingChanged callback from KeyguardStateController.Callback: If, in startWorkChallengeIfNecessary, the keyguard is still showing, a callback listener is added to the KeyguardStateController. When the callback is invoked the ConfirmDeviceCredentialActivity is started. Bug: 141470517 Test: Manual, double-tap on a managed profile notification (see above) Change-Id: If85a5781cc2054165eb508cd9634980ce228addc
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java73
1 files changed, 67 insertions, 6 deletions
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 6193a8e9005b..428de9e9adbb 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<Intent> 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 = 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 false;
+ 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