From e2ddaa2ee7aaa775510f431e5c9ead65576d06d3 Mon Sep 17 00:00:00 2001 From: Beverly Date: Thu, 6 May 2021 15:35:54 -0400 Subject: GPay activity can use passive biometric auth - User can face authenticate immediately after tapping the gpay icon on the LS - User can use rear fp sensor to authenticate while the GPay activity from LS is showing - Update udfps bouncer logic so that longpress on a notification works with udfps - Never listen for UDFPS on the keyguard if the device already has trust Test: atest SystemUITests Test: atest KeyguardUpdateMonitorTest Test: manual (unlock with and withou biometric on notification, shade, bouncer, gpay surfaces) Fixes: 187020022 Fixes: 183112863 Bug: 183024921 Bug: 185433347 Change-Id: I47aa58505535267c56b88c021791066c36a6c717 --- .../android/keyguard/KeyguardFaceListenModel.kt | 1 + .../android/keyguard/KeyguardUpdateMonitor.java | 49 +++++++++++++++++----- .../biometrics/UdfpsKeyguardViewController.java | 4 +- .../android/systemui/media/MediaControlPanel.java | 4 +- .../systemui/qs/tiles/ScreenRecordTile.java | 2 +- .../systemui/screenrecord/RecordingService.java | 2 +- .../sensorprivacy/SensorUseStartedActivity.kt | 2 +- .../statusbar/phone/BiometricUnlockController.java | 17 ++++---- .../statusbar/phone/KeyguardDismissHandler.java | 4 +- .../statusbar/phone/KeyguardDismissUtil.java | 5 ++- .../systemui/statusbar/phone/StatusBar.java | 6 ++- .../phone/StatusBarKeyguardViewManager.java | 41 +++++++++++------- .../statusbar/policy/SmartReplyStateInflater.kt | 2 +- .../android/systemui/wallet/ui/WalletActivity.java | 42 ++++++++++++------- .../systemui/wallet/ui/WalletScreenController.java | 5 +++ .../com/android/systemui/wallet/ui/WalletView.java | 6 +++ .../keyguard/KeyguardUpdateMonitorTest.java | 45 ++++++++++++++++---- .../systemui/media/MediaControlPanelTest.kt | 3 +- .../phone/BiometricsUnlockControllerTest.java | 17 +++++--- .../statusbar/policy/SmartReplyViewTest.java | 7 ++-- 20 files changed, 188 insertions(+), 76 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt index ab15630a6975..ff20805c5ea4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt @@ -12,6 +12,7 @@ data class KeyguardFaceListenModel( val isListeningForFace: Boolean, val isBouncer: Boolean, val isAuthInterruptActive: Boolean, + val isOccludingAppRequestingFaceAuth: Boolean, val isKeyguardAwake: Boolean, val isListeningForFaceAssistant: Boolean, val isSwitchingUser: Boolean, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 321c6b75d671..64bc77f3f03f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -276,6 +276,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean mHasLockscreenWallpaper; private boolean mAssistantVisible; private boolean mKeyguardOccluded; + private boolean mOccludingAppRequestingFp; + private boolean mOccludingAppRequestingFace; private boolean mSecureCameraLaunched; @VisibleForTesting protected boolean mTelephonyCapable; @@ -587,6 +589,29 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateBiometricListeningState(); } + + /** + * Request to listen for face authentication when an app is occluding keyguard. + * @param request if true and mKeyguardOccluded, request face auth listening, else default + * to normal behavior. + * See {@link KeyguardUpdateMonitor#shouldListenForFace()} + */ + public void requestFaceAuthOnOccludingApp(boolean request) { + mOccludingAppRequestingFace = request; + updateFaceListeningState(); + } + + /** + * Request to listen for fingerprint when an app is occluding keyguard. + * @param request if true and mKeyguardOccluded, request fingerprint listening, else default + * to normal behavior. + * See {@link KeyguardUpdateMonitor#shouldListenForFingerprint(boolean)} + */ + public void requestFingerprintAuthOnOccludingApp(boolean request) { + mOccludingAppRequestingFp = request; + updateFingerprintListeningState(); + } + /** * Invoked when the secure camera is launched. */ @@ -2093,14 +2118,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting protected boolean shouldListenForFingerprint(boolean isUdfps) { + final boolean userDoesNotHaveTrust = !getUserHasTrust(getCurrentUser()); final boolean shouldListenKeyguardState = - mKeyguardIsVisible - || !mDeviceInteractive - || (mBouncer && !mKeyguardGoingAway) - || mGoingToSleep - || shouldListenForFingerprintAssistant() - || (mKeyguardOccluded && mIsDreaming) - || (isUdfps && mKeyguardOccluded); + mKeyguardIsVisible + || !mDeviceInteractive + || (mBouncer && !mKeyguardGoingAway) + || mGoingToSleep + || shouldListenForFingerprintAssistant() + || (mKeyguardOccluded && mIsDreaming) + || (mKeyguardOccluded && userDoesNotHaveTrust + && (mOccludingAppRequestingFp || isUdfps)); // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. @@ -2116,8 +2143,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean shouldListenUdfpsState = !isUdfps || (!getUserCanSkipBouncer(getCurrentUser()) - && !isEncryptedOrLockdown(getCurrentUser()) - && mStrongAuthTracker.hasUserAuthenticatedSinceBoot()); + && !isEncryptedOrLockdown(getCurrentUser()) + && mStrongAuthTracker.hasUserAuthenticatedSinceBoot() + && userDoesNotHaveTrust); return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState && shouldListenUdfpsState; @@ -2166,7 +2194,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. final boolean shouldListen = - (mBouncer || mAuthInterruptActive || awakeKeyguard + (mBouncer || mAuthInterruptActive || mOccludingAppRequestingFace || awakeKeyguard || shouldListenForFaceAssistant()) && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer && !mKeyguardGoingAway && mBiometricEnabledForUser.get(user) && !mLockIconPressed @@ -2181,6 +2209,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab shouldListen, mBouncer, mAuthInterruptActive, + mOccludingAppRequestingFace, awakeKeyguard, shouldListenForFaceAssistant(), mSwitchingUser, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 819e829c53b0..a0ac2dc7289e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -169,7 +169,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController mKeyguardViewManager.cancelPostAuthActions()); + mView.animateAwayUdfpsBouncer(null); } return true; } @@ -231,8 +231,8 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController Boolean -) = executeWhenUnlocked(onDismissAction, requiresShadeOpen) +) = executeWhenUnlocked(onDismissAction, requiresShadeOpen, false) // convenience function that swaps parameter order so that lambda can be placed at the end private fun ActivityStarter.startPendingIntentDismissingKeyguard( diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java index 66bd48b9d188..4cba432a66be 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java @@ -99,6 +99,7 @@ public class WalletActivity extends LifecycleActivity { getActionBar().setHomeAsUpIndicator(getHomeIndicatorDrawable()); getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close); WalletView walletView = requireViewById(R.id.wallet_view); + mWalletScreenController = new WalletScreenController( this, walletView, @@ -116,20 +117,31 @@ public class WalletActivity extends LifecycleActivity { && mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return; } - mActivityStarter.startActivity( - mQuickAccessWalletClient.createWalletIntent(), true); - finish(); + + if (mKeyguardStateController.isUnlocked()) { + mActivityStarter.startActivity( + mQuickAccessWalletClient.createWalletIntent(), true); + finish(); + } else { + mKeyguardDismissUtil.executeWhenUnlocked(() -> { + mActivityStarter.startActivity( + mQuickAccessWalletClient.createWalletIntent(), true); + finish(); + return false; + }, false, true); + } }); + // Click the action button to re-render the screen when the device is unlocked. - if (!mKeyguardStateController.isUnlocked()) { - walletView.getActionButton().setOnClickListener( - v -> { - if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { - return; - } - mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false); - }); - } + walletView.setDeviceLockedActionOnClickListener( + v -> { + if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + return; + } + + mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false, + false); + }); } @Override @@ -142,13 +154,15 @@ public class WalletActivity extends LifecycleActivity { protected void onResume() { super.onResume(); mWalletScreenController.queryWalletCards(); - mKeyguardViewManager.requestUdfps(true, Color.BLACK); + mKeyguardViewManager.requestFp(true, Color.BLACK); + mKeyguardViewManager.requestFace(true); } @Override protected void onPause() { super.onPause(); - mKeyguardViewManager.requestUdfps(false, -1); + mKeyguardViewManager.requestFp(false, -1); + mKeyguardViewManager.requestFace(false); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java index b57d93762381..d9a7a8b29f10 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java @@ -177,6 +177,11 @@ public class WalletScreenController implements queryWalletCards(); } + @Override + public void onUnlockedChanged() { + queryWalletCards(); + } + @Override public void onCardSelected(@NonNull WalletCardViewInfo card) { if (mIsDismissed) { diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java index e42ce6ac50f3..bf146b6cd02f 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java @@ -63,6 +63,7 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard private final ViewGroup mEmptyStateView; private CharSequence mCenterCardText; private boolean mIsDeviceLocked = false; + private OnClickListener mDeviceLockedActionOnClickListener; public WalletView(Context context) { this(context, null); @@ -178,6 +179,10 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard mEmptyStateView.setVisibility(GONE); } + void setDeviceLockedActionOnClickListener(OnClickListener onClickListener) { + mDeviceLockedActionOnClickListener = onClickListener; + } + void hide() { setVisibility(GONE); } @@ -238,6 +243,7 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard if (isDeviceLocked) { mActionButton.setVisibility(VISIBLE); mActionButton.setText(R.string.wallet_action_button_label_unlock); + mActionButton.setOnClickListener(mDeviceLockedActionOnClickListener); } else if (actionButtonText != null) { mActionButton.setText(actionButtonText); mActionButton.setVisibility(VISIBLE); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 77582bd2e7af..f779305b75ab 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -842,10 +842,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testStartUdfpsServiceBeginsOnKeyguard() { // GIVEN - // - bouncer isn't showing // - status bar state is on the keyguard // - user has authenticated since boot - setKeyguardBouncerVisibility(false /* isVisible */); mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); @@ -853,12 +851,45 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true); } + @Test + public void testOccludingAppFingerprintListeningState() { + // GIVEN keyguard isn't visible (app occluding) + mKeyguardUpdateMonitor.dispatchStartedWakingUp(); + mKeyguardUpdateMonitor.setKeyguardOccluded(true); + mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false); + when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); + + // THEN we shouldn't listen for fingerprints + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(false); + + // THEN we should listen for udfps (hiding of mechanism to actually auth is + // controlled by UdfpsKeyguardViewController) + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true); + } + + @Test + public void testOccludingAppRequestsFingerprint() { + // GIVEN keyguard isn't visible (app occluding) + mKeyguardUpdateMonitor.dispatchStartedWakingUp(); + mKeyguardUpdateMonitor.setKeyguardOccluded(true); + mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false); + + // WHEN an occluding app requests fp + mKeyguardUpdateMonitor.requestFingerprintAuthOnOccludingApp(true); + + // THEN we should listen for fingerprints + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(true); + + // WHEN an occluding app stops requesting fp + mKeyguardUpdateMonitor.requestFingerprintAuthOnOccludingApp(false); + + // THEN we shouldn't listen for fingeprints + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(false); + } + @Test public void testStartUdfpsServiceNoAuthenticationSinceLastBoot() { - // GIVEN - // - bouncer isn't showing - // - status bar state is on the keyguard - setKeyguardBouncerVisibility(false /* isVisible */); + // GIVEN status bar state is on the keyguard mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); // WHEN user hasn't authenticated since last boot @@ -871,7 +902,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testShouldNotListenForUdfps_whenTrustEnabled() { // GIVEN a "we should listen for udfps" state - setKeyguardBouncerVisibility(false /* isVisible */); mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); @@ -886,7 +916,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testShouldNotListenForUdfps_whenFaceAuthenticated() { // GIVEN a "we should listen for udfps" state - setKeyguardBouncerVisibility(false /* isVisible */); mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index e62fa912e610..e1f1dc15badb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -325,7 +325,8 @@ public class MediaControlPanelTest : SysuiTestCase() { assertThat(dismiss.isEnabled).isEqualTo(true) dismiss.callOnClick() val captor = ArgumentCaptor.forClass(ActivityStarter.OnDismissAction::class.java) - verify(keyguardDismissUtil).executeWhenUnlocked(captor.capture(), anyBoolean()) + verify(keyguardDismissUtil).executeWhenUnlocked(captor.capture(), anyBoolean(), + eq(false)) captor.value.onDismiss() verify(mediaDataManager).dismissMediaData(eq(mediaKey), anyLong()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index a63d509b0b53..b54f9234188f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -42,6 +42,8 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -90,6 +92,12 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { private DozeParameters mDozeParameters; @Mock private MetricsLogger mMetricsLogger; + @Mock + private NotificationMediaManager mNotificationMediaManager; + @Mock + private WakefulnessLifecycle mWakefulnessLifecycle; + @Mock + private ScreenLifecycle mScreenLifecycle; private BiometricUnlockController mBiometricUnlockController; @Before @@ -109,7 +117,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mKeyguardViewMediator, mScrimController, mShadeController, mNotificationShadeWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters, - mMetricsLogger, mDumpManager); + mMetricsLogger, mDumpManager, mPowerManager, + mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener); } @@ -121,8 +130,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */); verify(mStatusBarKeyguardViewManager).showBouncer(eq(false)); - verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(), - anyFloat()); verify(mStatusBarKeyguardViewManager, never()).notifyKeyguardAuthenticated(anyBoolean()); assertThat(mBiometricUnlockController.getMode()) .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER); @@ -161,7 +168,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test - public void onBiometricAuthenticated_whenFingerprint_dismissKeyguard() { + public void onBiometricAuthenticated_whenFingerprint_notifyKeyguardAuthenticated() { when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); // the value of isStrongBiometric doesn't matter here since we only care about the returned // value of isUnlockingWithBiometricAllowed() @@ -169,8 +176,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */); verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean()); - verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(), - anyFloat()); verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); assertThat(mBiometricUnlockController.getMode()) .isEqualTo(BiometricUnlockController.MODE_UNLOCK_COLLAPSING); 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 e5b7e3f71ac1..32aee2bd6554 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 @@ -120,7 +120,7 @@ public class SmartReplyViewTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mReceiver = new BlockingQueueIntentReceiver(); mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION)); - mKeyguardDismissUtil.setDismissHandler((action, unused) -> action.onDismiss()); + mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) -> action.onDismiss()); mDependency.injectMockDependency(KeyguardUpdateMonitor.class); mDependency.injectMockDependency(ShadeController.class); mDependency.injectMockDependency(NotificationRemoteInputManager.class); @@ -183,7 +183,7 @@ public class SmartReplyViewTest extends SysuiTestCase { @Test public void testSendSmartReply_keyguardCancelled() throws InterruptedException { - mKeyguardDismissUtil.setDismissHandler((action, unused) -> { }); + mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) -> { }); setSmartReplies(TEST_CHOICES); mView.getChildAt(2).performClick(); @@ -195,7 +195,8 @@ public class SmartReplyViewTest extends SysuiTestCase { public void testSendSmartReply_waitsForKeyguard() throws InterruptedException { AtomicReference actionRef = new AtomicReference<>(); - mKeyguardDismissUtil.setDismissHandler((action, unused) -> actionRef.set(action)); + mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) + -> actionRef.set(action)); setSmartReplies(TEST_CHOICES); mView.getChildAt(2).performClick(); -- cgit v1.2.3-59-g8ed1b