diff options
9 files changed, 52 insertions, 16 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 1440803f1524..70ee752dd8ed 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -52,6 +52,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; import com.android.systemui.R; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -121,6 +122,7 @@ public class NotificationRemoteInputManager implements Dumpable { protected final Context mContext; private final UserManager mUserManager; private final KeyguardManager mKeyguardManager; + private final StatusBarStateController mStatusBarStateController; protected RemoteInputController mRemoteInputController; protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback @@ -259,6 +261,7 @@ public class NotificationRemoteInputManager implements Dumpable { SmartReplyController smartReplyController, NotificationEntryManager notificationEntryManager, Lazy<ShadeController> shadeController, + StatusBarStateController statusBarStateController, @Named(MAIN_HANDLER_NAME) Handler mainHandler) { mContext = context; mLockscreenUserManager = lockscreenUserManager; @@ -271,6 +274,7 @@ public class NotificationRemoteInputManager implements Dumpable { mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); addLifetimeExtenders(); mKeyguardManager = context.getSystemService(KeyguardManager.class); + mStatusBarStateController = statusBarStateController; notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { @Override @@ -380,7 +384,10 @@ public class NotificationRemoteInputManager implements Dumpable { if (!mLockscreenUserManager.shouldAllowLockscreenRemoteInput()) { final int userId = pendingIntent.getCreatorUserHandle().getIdentifier(); - if (mLockscreenUserManager.isLockscreenPublicMode(userId)) { + if (mLockscreenUserManager.isLockscreenPublicMode(userId) + || mStatusBarStateController.getState() == StatusBarState.KEYGUARD) { + // Even if we don't have security we should go through this flow, otherwise we won't + // go to the shade mCallback.onLockedRemoteInput(row, view); return true; } @@ -391,6 +398,11 @@ public class NotificationRemoteInputManager implements Dumpable { } } + if (!riv.isAttachedToWindow()) { + // the remoteInput isn't attached to the window anymore :/ Let's focus on the expanded + // one instead if it's available + riv = null; + } if (riv == null) { riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild()); if (riv == null) { @@ -405,6 +417,10 @@ public class NotificationRemoteInputManager implements Dumpable { return true; } + if (!riv.isAttachedToWindow()) { + // if we still didn't find a view that is attached, let's abort. + return false; + } int width = view.getWidth(); if (view instanceof TextView) { // Center the reveal on the text which might be off-center from the TextView diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java index 6111178bbac9..b11329ad0135 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java @@ -24,6 +24,7 @@ public interface KeyguardDismissHandler { /** * Executes an action that requres the screen to be unlocked, showing the keyguard if * necessary. Does not close the notification shade (in case it was open). + * @param requiresShadeOpen does the shade need to be forced open when hiding the keyguard? */ - void executeWhenUnlocked(OnDismissAction action); + void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java index e541e14b3d91..834d2a5ae4a0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java @@ -37,7 +37,7 @@ public class KeyguardDismissUtil implements KeyguardDismissHandler { public KeyguardDismissUtil() { } - /** Sets the actual {@link DismissHandler} implementation. */ + /** Sets the actual {@link KeyguardDismissHandler} implementation. */ public void setDismissHandler(KeyguardDismissHandler dismissHandler) { mDismissHandler = dismissHandler; } @@ -46,15 +46,17 @@ public class KeyguardDismissUtil implements KeyguardDismissHandler { * Executes an action that requires the screen to be unlocked. * * <p>Must be called after {@link #setDismissHandler}. + * + * @param requiresShadeOpen does the shade need to be forced open when hiding the keyguard? */ @Override - public void executeWhenUnlocked(OnDismissAction action) { + public void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen) { KeyguardDismissHandler dismissHandler = mDismissHandler; if (dismissHandler == null) { Log.wtf(TAG, "KeyguardDismissHandler not set."); action.onDismiss(); return; } - dismissHandler.executeWhenUnlocked(action); + dismissHandler.executeWhenUnlocked(action, requiresShadeOpen); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 55f61fa8a6a0..ad13b28440bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2618,8 +2618,8 @@ public class StatusBar extends SystemUI implements DemoMode, } } - private void executeWhenUnlocked(OnDismissAction action) { - if (mStatusBarKeyguardViewManager.isShowing()) { + private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen) { + if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) { mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); } dismissKeyguardThenExecute(action, null /* cancelAction */, false /* afterKeyguardGone */); 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 6691f7a759f3..13d4b8edb8d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.policy.KeyguardMonitor; +import com.android.systemui.statusbar.policy.RemoteInputView; import javax.inject.Inject; import javax.inject.Singleton; @@ -93,9 +94,11 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, @Override public void onStateChanged(int state) { - if (state == StatusBarState.SHADE && mStatusBarStateController.leaveOpenOnKeyguardHide()) { + boolean hasPendingRemoteInput = mPendingRemoteInputView != null; + if (state == StatusBarState.SHADE + && (mStatusBarStateController.leaveOpenOnKeyguardHide() || hasPendingRemoteInput)) { if (!mStatusBarStateController.isKeyguardRequested()) { - if (mPendingRemoteInputView != null) { + if (hasPendingRemoteInput) { mMainHandler.post(mPendingRemoteInputView::callOnClick); } mPendingRemoteInputView = null; @@ -105,7 +108,9 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, @Override public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); + if (!row.isPinned()) { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); + } mShadeController.showBouncer(true /* scrimmed */); mPendingRemoteInputView = clicked; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 640f0f0cc3f6..282d28c3b20c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -303,7 +303,7 @@ public class SmartReplyView extends ViewGroup { }; OnClickListener onClickListener = view -> - smartReplyView.mKeyguardDismissUtil.executeWhenUnlocked(action); + smartReplyView.mKeyguardDismissUtil.executeWhenUnlocked(action, !entry.isRowPinned()); if (useDelayedOnClickListener) { onClickListener = new DelayedOnClickListener(onClickListener, smartReplyView.mConstants.getOnClickInitDelay()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java index b81e04821463..da25eed4a24e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -1,3 +1,4 @@ + package com.android.systemui.statusbar; import static junit.framework.Assert.assertEquals; @@ -22,12 +23,14 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputActiveExtender; import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender; import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyHistoryExtender; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ShadeController; import com.google.android.collect.Sets; @@ -54,6 +57,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { @Mock private SmartReplyController mSmartReplyController; @Mock private NotificationListenerService.RankingMap mRanking; @Mock private ExpandableNotificationRow mRow; + @Mock private StatusBarStateController mStateController; // Dependency mocks: @Mock private NotificationEntryManager mEntryManager; @@ -73,6 +77,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext, mLockscreenUserManager, mSmartReplyController, mEntryManager, () -> mock(ShadeController.class), + mStateController, Handler.createAsync(Looper.myLooper())); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); @@ -196,15 +201,15 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager { - TestableNotificationRemoteInputManager(Context context, NotificationLockscreenUserManager lockscreenUserManager, SmartReplyController smartReplyController, NotificationEntryManager notificationEntryManager, Lazy<ShadeController> shadeController, + StatusBarStateController statusBarStateController, Handler mainHandler) { super(context, lockscreenUserManager, smartReplyController, notificationEntryManager, - shadeController, mainHandler); + shadeController, statusBarStateController, mainHandler); } public void setUpWithPresenterForTest(Callback callback, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java index 81e373a8be27..185723ffa09b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java @@ -38,6 +38,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.ShadeController; @@ -70,6 +71,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { @Mock private StatusBarNotification mSbn; @Mock private NotificationEntryManager mNotificationEntryManager; @Mock private IStatusBarService mIStatusBarService; + @Mock private StatusBarStateController mStatusBarStateController; @Before public void setUp() { @@ -85,6 +87,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { mRemoteInputManager = new NotificationRemoteInputManager(mContext, mock(NotificationLockscreenUserManager.class), mSmartReplyController, mNotificationEntryManager, () -> mock(ShadeController.class), + mStatusBarStateController, Handler.createAsync(Looper.myLooper())); mRemoteInputManager.setUpWithCallback(mCallback, mDelegate); mNotification = new Notification.Builder(mContext, "") diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java index 8c5fac47885f..0cb575483466 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java @@ -109,7 +109,9 @@ public class SmartReplyViewTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mReceiver = new BlockingQueueIntentReceiver(); mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION)); - mDependency.get(KeyguardDismissUtil.class).setDismissHandler(action -> action.onDismiss()); + mDependency.get(KeyguardDismissUtil.class).setDismissHandler((action, unused) -> { + action.onDismiss(); + }); mDependency.injectMockDependency(ShadeController.class); mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter); mDependency.injectTestDependency(SmartReplyConstants.class, mConstants); @@ -162,7 +164,7 @@ public class SmartReplyViewTest extends SysuiTestCase { @Test public void testSendSmartReply_keyguardCancelled() throws InterruptedException { - mDependency.get(KeyguardDismissUtil.class).setDismissHandler(action -> {}); + mDependency.get(KeyguardDismissUtil.class).setDismissHandler((action, unused) -> {}); setSmartReplies(TEST_CHOICES); mView.getChildAt(2).performClick(); @@ -173,7 +175,9 @@ public class SmartReplyViewTest extends SysuiTestCase { @Test public void testSendSmartReply_waitsForKeyguard() throws InterruptedException { AtomicReference<OnDismissAction> actionRef = new AtomicReference<>(); - mDependency.get(KeyguardDismissUtil.class).setDismissHandler(actionRef::set); + mDependency.get(KeyguardDismissUtil.class).setDismissHandler((action, unused) -> { + actionRef.set(action); + }); setSmartReplies(TEST_CHOICES); mView.getChildAt(2).performClick(); |