Merge "Hide UDFPS overlay when bouncer is showing"

This commit is contained in:
TreeHugger Robot
2020-09-19 06:20:34 +00:00
committed by Android (Google) Code Review
6 changed files with 219 additions and 12 deletions

View File

@@ -52,6 +52,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import java.util.List;
@@ -64,7 +65,7 @@ import javax.inject.Provider;
*/
@SysUISingleton
public class AuthController extends SystemUI implements CommandQueue.Callbacks,
AuthDialogCallback, DozeReceiver {
AuthDialogCallback, DozeReceiver, KeyguardBouncer.BouncerExpansionCallback {
private static final String TAG = "AuthController";
private static final boolean DEBUG = true;
@@ -426,6 +427,35 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog = null;
}
/** See {@link KeyguardBouncer.BouncerExpansionCallback#onFullyShown}. */
@Override
public void onFullyShown() {
if (mUdfpsController != null) {
mUdfpsController.setBouncerVisibility(true);
}
}
/** See {@link KeyguardBouncer.BouncerExpansionCallback#onStartingToHide}. */
@Override
public void onStartingToHide() {
}
/** See {@link KeyguardBouncer.BouncerExpansionCallback#onStartingToShow}. */
@Override
public void onStartingToShow() {
if (mUdfpsController != null) {
mUdfpsController.setBouncerVisibility(true);
}
}
/** See {@link KeyguardBouncer.BouncerExpansionCallback#onFullyHidden}. */
@Override
public void onFullyHidden() {
if (mUdfpsController != null) {
mUdfpsController.setBouncerVisibility(false);
}
}
private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
mCurrentDialogArgs = args;
final @BiometricAuthenticator.Modality int type = args.argi1;

View File

@@ -86,7 +86,13 @@ class UdfpsController implements DozeReceiver {
// Default non-HBM backlight value normalized to the range [0, 1.0]. Used as a fallback when the
// actual brightness value cannot be retrieved.
private final float mDefaultBrightness;
// Indicates whether the overlay is currently showing. Even if it has been requested, it might
// not be showing.
private boolean mIsOverlayShowing;
// Indicates whether the overlay has been requested.
private boolean mIsOverlayRequested;
// Indicates whether the bouncer is showing. When it is showing, the overlay needs to be hidden.
private boolean mIsBouncerShowing;
// The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
// to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -98,12 +104,12 @@ class UdfpsController implements DozeReceiver {
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@Override
public void showUdfpsOverlay() {
UdfpsController.this.showUdfpsOverlay();
UdfpsController.this.setShowOverlay(true);
}
@Override
public void hideUdfpsOverlay() {
UdfpsController.this.hideUdfpsOverlay();
UdfpsController.this.setShowOverlay(false);
}
@Override
@@ -207,6 +213,35 @@ class UdfpsController implements DozeReceiver {
mView.dozeTimeTick();
}
private void setShowOverlay(boolean show) {
if (show == mIsOverlayRequested) {
return;
}
mIsOverlayRequested = show;
updateOverlay();
}
/**
* Call when the visibility of the bouncer changes.
*
* @param isShowing Whether or not the bouncer is showing
*/
void setBouncerVisibility(boolean isShowing) {
if (isShowing == mIsBouncerShowing) {
return;
}
mIsBouncerShowing = isShowing;
updateOverlay();
}
private void updateOverlay() {
if (mIsOverlayRequested && !mIsBouncerShowing) {
showUdfpsOverlay();
} else {
hideUdfpsOverlay();
}
}
private void showUdfpsOverlay() {
mFgExecutor.execute(() -> {
if (!mIsOverlayShowing) {

View File

@@ -40,12 +40,15 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.keyguard.dagger.RootView;
import com.android.systemui.DejankUtils;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -66,7 +69,8 @@ public class KeyguardBouncer {
private final FalsingManager mFalsingManager;
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final Handler mHandler;
private final BouncerExpansionCallback mExpansionCallback;
private final List<BouncerExpansionCallback> mExpansionCallbacks = new ArrayList<>();
private final AuthController mAuthController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardSecurityModel mKeyguardSecurityModel;
@@ -100,6 +104,7 @@ public class KeyguardBouncer {
ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
BouncerExpansionCallback expansionCallback,
AuthController authController,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardBypassController keyguardBypassController, Handler handler,
@@ -111,13 +116,15 @@ public class KeyguardBouncer {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mFalsingManager = falsingManager;
mDismissCallbackRegistry = dismissCallbackRegistry;
mExpansionCallback = expansionCallback;
mHandler = handler;
mKeyguardStateController = keyguardStateController;
mKeyguardSecurityModel = keyguardSecurityModel;
mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mKeyguardBypassController = keyguardBypassController;
mExpansionCallbacks.add(expansionCallback);
mExpansionCallbacks.add(authController);
mAuthController = authController;
}
public void show(boolean resetSecuritySelection) {
@@ -188,7 +195,7 @@ public class KeyguardBouncer {
}
mCallback.onBouncerVisiblityChanged(true /* shown */);
mExpansionCallback.onStartingToShow();
dispatchStartingToShow();
}
public boolean isScrimmed() {
@@ -290,6 +297,11 @@ public class KeyguardBouncer {
mIsScrimmed = false;
mFalsingManager.onBouncerHidden();
mCallback.onBouncerVisiblityChanged(false /* shown */);
// TODO(b/165257355): `mAuthController.onFullyHidden` should be `dispatchFullyHidden()`
// But, it is causing the UDFPS icon to disappear after SystemUI restarts. I guess the
// ExpansionCallback from StatusBarKeyguardViewManager can't handle the call to
// onFullyHidden after a restart.
mAuthController.onFullyHidden();
cancelShowRunnable();
if (mKeyguardViewController != null) {
mKeyguardViewController.cancelDismissAction();
@@ -382,12 +394,12 @@ public class KeyguardBouncer {
if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
onFullyShown();
mExpansionCallback.onFullyShown();
dispatchFullyShown();
} else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
onFullyHidden();
mExpansionCallback.onFullyHidden();
dispatchFullyHidden();
} else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
mExpansionCallback.onStartingToHide();
dispatchStartingToHide();
if (mKeyguardViewController != null) {
mKeyguardViewController.onStartingToHide();
}
@@ -492,6 +504,30 @@ public class KeyguardBouncer {
mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
}
private void dispatchFullyShown() {
for (BouncerExpansionCallback callback : mExpansionCallbacks) {
callback.onFullyShown();
}
}
private void dispatchStartingToHide() {
for (BouncerExpansionCallback callback : mExpansionCallbacks) {
callback.onStartingToHide();
}
}
private void dispatchStartingToShow() {
for (BouncerExpansionCallback callback : mExpansionCallbacks) {
callback.onStartingToShow();
}
}
private void dispatchFullyHidden() {
for (BouncerExpansionCallback callback : mExpansionCallbacks) {
callback.onFullyHidden();
}
}
public void dump(PrintWriter pw) {
pw.println("KeyguardBouncer");
pw.println(" isShowing(): " + isShowing());
@@ -516,6 +552,7 @@ public class KeyguardBouncer {
private final ViewMediatorCallback mCallback;
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final FalsingManager mFalsingManager;
private final AuthController mAuthController;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardBypassController mKeyguardBypassController;
@@ -526,6 +563,7 @@ public class KeyguardBouncer {
@Inject
public Factory(Context context, ViewMediatorCallback callback,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
AuthController authController,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardBypassController keyguardBypassController, Handler handler,
@@ -535,6 +573,7 @@ public class KeyguardBouncer {
mCallback = callback;
mDismissCallbackRegistry = dismissCallbackRegistry;
mFalsingManager = falsingManager;
mAuthController = authController;
mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardBypassController = keyguardBypassController;
@@ -547,8 +586,9 @@ public class KeyguardBouncer {
BouncerExpansionCallback expansionCallback) {
return new KeyguardBouncer(mContext, mCallback, container,
mDismissCallbackRegistry, mFalsingManager, expansionCallback,
mKeyguardStateController, mKeyguardUpdateMonitor, mKeyguardBypassController,
mHandler, mKeyguardSecurityModel, mKeyguardBouncerComponentFactory);
mAuthController, mKeyguardStateController, mKeyguardUpdateMonitor,
mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
mKeyguardBouncerComponentFactory);
}
}
}

View File

@@ -22,6 +22,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -505,6 +506,30 @@ public class AuthControllerTest extends SysuiTestCase {
verify(mUdfpsController).onCancelAodInterrupt();
}
@Test
public void testOnFullyShown_DelegatesToUdfpsController() {
mAuthController.onFullyShown();
verify(mUdfpsController).setBouncerVisibility(eq(true));
}
@Test
public void testOnFullyHidden_DelegatesToUdfpsController() {
mAuthController.onFullyHidden();
verify(mUdfpsController).setBouncerVisibility(eq(false));
}
@Test
public void testOnStartingToShow_NeverDelegatesToUdfpsController() {
mAuthController.onStartingToShow();
verify(mUdfpsController).setBouncerVisibility(eq(true));
}
@Test
public void testOnStartingToHide_NeverDelegatesToUdfpsController() {
mAuthController.onStartingToHide();
verify(mUdfpsController, never()).setBouncerVisibility(anyBoolean());
}
// Helpers
private void showDialog(int authenticators, int biometricModality) {

View File

@@ -19,6 +19,7 @@ package com.android.systemui.biometrics;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -150,6 +151,41 @@ public class UdfpsControllerTest extends SysuiTestCase {
verify(mWindowManager).removeView(eq(mUdfpsView));
}
@Test
public void showUdfpsOverlay_bouncerShowing() throws RemoteException {
// GIVEN that the bouncer is showing
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
// WHEN a request to show the overlay is received
mOverlayController.showUdfpsOverlay();
mFgExecutor.runAllReady();
// THEN the overlay is not attached
verify(mWindowManager, never()).addView(eq(mUdfpsView), any());
}
@Test
public void setBouncerVisibility_overlayDetached() throws RemoteException {
// GIVEN that the overlay has been requested
mOverlayController.showUdfpsOverlay();
// WHEN the bouncer becomes visible
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
mFgExecutor.runAllReady();
// THEN the overlay is detached
verify(mWindowManager).removeView(eq(mUdfpsView));
}
@Test
public void setBouncerVisibility_overlayAttached() throws RemoteException {
// GIVEN that the bouncer is visible
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
// AND the overlay has been requested
mOverlayController.showUdfpsOverlay();
// WHEN the bouncer is closed
mUdfpsController.setBouncerVisibility(/* isShowing */ false);
mFgExecutor.runAllReady();
// THEN the overlay is attached
verify(mWindowManager).addView(eq(mUdfpsView), any());
}
@Test
public void fingerDown() throws RemoteException {
// Configure UdfpsView to accept the ACTION_DOWN event

View File

@@ -50,6 +50,7 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.FalsingManager;
@@ -78,6 +79,8 @@ public class KeyguardBouncerTest extends SysuiTestCase {
@Mock
private DismissCallbackRegistry mDismissCallbackRegistry;
@Mock
private AuthController mAuthController;
@Mock
private KeyguardHostViewController mKeyguardHostViewController;
@Mock
private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback;
@@ -128,7 +131,7 @@ public class KeyguardBouncerTest extends SysuiTestCase {
final ViewGroup container = new FrameLayout(getContext());
mBouncer = new KeyguardBouncer.Factory(getContext(), mViewMediatorCallback,
mDismissCallbackRegistry, mFalsingManager,
mDismissCallbackRegistry, mFalsingManager, mAuthController,
mKeyguardStateController, mKeyguardUpdateMonitor,
mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
mKeyguardBouncerComponentFactory)
@@ -206,6 +209,12 @@ public class KeyguardBouncerTest extends SysuiTestCase {
verify(mKeyguardHostViewController).showErrorMessage(eq(errorMessage));
}
@Test
public void testShow_notifiesAuthControllerStartingToShow() {
mBouncer.show(/* resetSecuritySelection */ false);
verify(mAuthController).onStartingToShow();
}
@Test
public void testSetExpansion_notifiesFalsingManager() {
mBouncer.ensureView();
@@ -236,6 +245,38 @@ public class KeyguardBouncerTest extends SysuiTestCase {
verify(mRootView).announceForAccessibility(any());
}
@Test
public void testSetExpansion_notifiesAuthControllerFullyShown() {
mBouncer.ensureView();
mBouncer.setExpansion(0.1f);
mBouncer.setExpansion(0f);
verify(mAuthController).onFullyShown();
}
@Test
public void testSetExpansion_notifiesAuthControllerStartingToHide() {
mBouncer.ensureView();
mBouncer.setExpansion(0f);
mBouncer.setExpansion(0.1f);
verify(mAuthController).onStartingToHide();
}
@Test
public void testSetExpansion_notifiesAuthControllerFullyHidden() {
mBouncer.ensureView();
mBouncer.setExpansion(0.9f);
mBouncer.setExpansion(1f);
verify(mAuthController).onFullyHidden();
}
@Test
public void testSetExpansion_negativeAuthControllerStartingToShow() {
mBouncer.ensureView();
mBouncer.setExpansion(1f);
mBouncer.setExpansion(0.9f);
verify(mAuthController, never()).onStartingToShow();
}
@Test
public void testHide_notifiesFalsingManager() {
mBouncer.hide(false);