Merge "Show side fps hint on large screen bouncer" into tm-qpr-dev

This commit is contained in:
Nicolò Mazzucato
2022-07-14 09:51:46 +00:00
committed by Android (Google) Code Review
9 changed files with 318 additions and 48 deletions

View File

@@ -336,6 +336,11 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
mKeyguardSecurityContainerController.onStartingToHide(); mKeyguardSecurityContainerController.onStartingToHide();
} }
/** Called when bouncer visibility changes. */
public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility);
}
public boolean hasDismissActions() { public boolean hasDismissActions() {
return mDismissAction != null || mCancelAction != null; return mDismissAction != null || mCancelAction != null;
} }

View File

@@ -17,6 +17,7 @@
package com.android.keyguard; package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC; import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS; import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
@@ -32,11 +33,13 @@ import android.app.admin.DevicePolicyManager;
import android.content.Intent; import android.content.Intent;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.hardware.biometrics.BiometricSourceType;
import android.metrics.LogMaker; import android.metrics.LogMaker;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log; import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -55,6 +58,7 @@ import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Gefingerpoken; import com.android.systemui.Gefingerpoken;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.biometrics.SidefpsController;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags; import com.android.systemui.flags.Flags;
@@ -67,6 +71,8 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController;
import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.GlobalSettings;
import java.util.Optional;
import javax.inject.Inject; import javax.inject.Inject;
/** Controller for {@link KeyguardSecurityContainer} */ /** Controller for {@link KeyguardSecurityContainer} */
@@ -93,6 +99,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final GlobalSettings mGlobalSettings; private final GlobalSettings mGlobalSettings;
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final SessionTracker mSessionTracker; private final SessionTracker mSessionTracker;
private final Optional<SidefpsController> mSidefpsController;
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -236,13 +243,27 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
reloadColors(); reloadColors();
} }
}; };
private boolean mBouncerVisible = false;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() { new KeyguardUpdateMonitorCallback() {
@Override @Override
public void onDevicePolicyManagerStateChanged() { public void onDevicePolicyManagerStateChanged() {
showPrimarySecurityScreen(false); showPrimarySecurityScreen(false);
} }
};
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
if (biometricSourceType == FINGERPRINT) {
updateSideFpsVisibility();
}
}
@Override
public void onStrongAuthStateChanged(int userId) {
updateSideFpsVisibility();
}
};
private KeyguardSecurityContainerController(KeyguardSecurityContainer view, private KeyguardSecurityContainerController(KeyguardSecurityContainer view,
AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory, AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
@@ -260,7 +281,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
UserSwitcherController userSwitcherController, UserSwitcherController userSwitcherController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
GlobalSettings globalSettings, GlobalSettings globalSettings,
SessionTracker sessionTracker) { SessionTracker sessionTracker,
Optional<SidefpsController> sidefpsController) {
super(view); super(view);
mLockPatternUtils = lockPatternUtils; mLockPatternUtils = lockPatternUtils;
mUpdateMonitor = keyguardUpdateMonitor; mUpdateMonitor = keyguardUpdateMonitor;
@@ -280,6 +302,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings; mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker; mSessionTracker = sessionTracker;
mSidefpsController = sidefpsController;
} }
@Override @Override
@@ -311,8 +334,23 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
getCurrentSecurityController().onPause(); getCurrentSecurityController().onPause();
} }
mView.onPause(); mView.onPause();
// It might happen that onStartingToHide is not called when the device is locked while on
// bouncer.
setBouncerVisible(false);
} }
private void updateSideFpsVisibility() {
if (!mSidefpsController.isPresent()) {
return;
}
if (mBouncerVisible && mView.isSidedSecurityMode()
&& mUpdateMonitor.isFingerprintDetectionRunning()
&& !mUpdateMonitor.userNeedsStrongAuth()) {
mSidefpsController.get().show();
} else {
mSidefpsController.get().hide();
}
}
/** /**
* Shows the primary security screen for the user. This will be either the multi-selector * Shows the primary security screen for the user. This will be either the multi-selector
@@ -397,6 +435,17 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mCurrentSecurityMode != SecurityMode.None) { if (mCurrentSecurityMode != SecurityMode.None) {
getCurrentSecurityController().onStartingToHide(); getCurrentSecurityController().onStartingToHide();
} }
setBouncerVisible(false);
}
/** Called when the bouncer changes visibility. */
public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
setBouncerVisible(visibility == View.VISIBLE);
}
private void setBouncerVisible(boolean visible) {
mBouncerVisible = visible;
updateSideFpsVisibility();
} }
/** /**
@@ -655,6 +704,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final UserSwitcherController mUserSwitcherController; private final UserSwitcherController mUserSwitcherController;
private final SessionTracker mSessionTracker; private final SessionTracker mSessionTracker;
private final Optional<SidefpsController> mSidefpsController;
@Inject @Inject
Factory(KeyguardSecurityContainer view, Factory(KeyguardSecurityContainer view,
@@ -673,7 +723,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
UserSwitcherController userSwitcherController, UserSwitcherController userSwitcherController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
GlobalSettings globalSettings, GlobalSettings globalSettings,
SessionTracker sessionTracker) { SessionTracker sessionTracker,
Optional<SidefpsController> sidefpsController) {
mView = view; mView = view;
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory; mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
mLockPatternUtils = lockPatternUtils; mLockPatternUtils = lockPatternUtils;
@@ -690,6 +741,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mGlobalSettings = globalSettings; mGlobalSettings = globalSettings;
mUserSwitcherController = userSwitcherController; mUserSwitcherController = userSwitcherController;
mSessionTracker = sessionTracker; mSessionTracker = sessionTracker;
mSidefpsController = sidefpsController;
} }
public KeyguardSecurityContainerController create( public KeyguardSecurityContainerController create(
@@ -699,7 +751,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger, mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, securityCallback, mSecurityViewFlipperController, mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
mConfigurationController, mFalsingCollector, mFalsingManager, mConfigurationController, mFalsingCollector, mFalsingManager,
mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker); mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker,
mSidefpsController);
} }
} }
} }

View File

@@ -16,6 +16,10 @@
package com.android.keyguard.dagger; package com.android.keyguard.dagger;
import static com.android.systemui.biometrics.SidefpsControllerKt.hasSideFpsSensor;
import android.annotation.Nullable;
import android.hardware.fingerprint.FingerprintManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -23,9 +27,14 @@ import com.android.keyguard.KeyguardHostView;
import com.android.keyguard.KeyguardSecurityContainer; import com.android.keyguard.KeyguardSecurityContainer;
import com.android.keyguard.KeyguardSecurityViewFlipper; import com.android.keyguard.KeyguardSecurityViewFlipper;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.biometrics.SidefpsController;
import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.KeyguardBouncer;
import java.util.Optional;
import javax.inject.Provider;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -60,4 +69,16 @@ public interface KeyguardBouncerModule {
KeyguardSecurityContainer containerView) { KeyguardSecurityContainer containerView) {
return containerView.findViewById(R.id.view_flipper); return containerView.findViewById(R.id.view_flipper);
} }
/** Provides {@link SidefpsController} if the device has the side fingerprint sensor. */
@Provides
@KeyguardBouncerScope
static Optional<SidefpsController> providesOptionalSidefpsController(
@Nullable FingerprintManager fingerprintManager,
Provider<SidefpsController> sidefpsControllerProvider) {
if (!hasSideFpsSensor(fingerprintManager)) {
return Optional.empty();
}
return Optional.of(sidefpsControllerProvider.get());
}
} }

View File

@@ -34,16 +34,16 @@ import android.hardware.fingerprint.ISidefpsController
import android.os.Handler import android.os.Handler
import android.util.Log import android.util.Log
import android.util.RotationUtils import android.util.RotationUtils
import android.view.View.AccessibilityDelegate
import android.view.accessibility.AccessibilityEvent
import android.view.Display import android.view.Display
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Surface import android.view.Surface
import android.view.View import android.view.View
import android.view.View.AccessibilityDelegate
import android.view.ViewPropertyAnimator import android.view.ViewPropertyAnimator
import android.view.WindowInsets import android.view.WindowInsets
import android.view.WindowManager import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import androidx.annotation.RawRes import androidx.annotation.RawRes
import com.airbnb.lottie.LottieAnimationView import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieProperty import com.airbnb.lottie.LottieProperty
@@ -70,13 +70,12 @@ class SidefpsController @Inject constructor(
private val activityTaskManager: ActivityTaskManager, private val activityTaskManager: ActivityTaskManager,
overviewProxyService: OverviewProxyService, overviewProxyService: OverviewProxyService,
displayManager: DisplayManager, displayManager: DisplayManager,
@Main mainExecutor: DelayableExecutor, @Main private val mainExecutor: DelayableExecutor,
@Main private val handler: Handler @Main private val handler: Handler
) { ) {
@VisibleForTesting @VisibleForTesting
val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager
?.sensorPropertiesInternal ?.sideFpsSensorProperties
?.firstOrNull { it.isAnySidefpsType }
?: throw IllegalStateException("no side fingerprint sensor") ?: throw IllegalStateException("no side fingerprint sensor")
@VisibleForTesting @VisibleForTesting
@@ -135,25 +134,34 @@ class SidefpsController @Inject constructor(
} }
init { init {
fingerprintManager?.setSidefpsController(object : ISidefpsController.Stub() { fingerprintManager?.setSidefpsController(
override fun show( object : ISidefpsController.Stub() {
sensorId: Int, override fun show(
@BiometricOverlayConstants.ShowReason reason: Int sensorId: Int,
) = if (reason.isReasonToShow(activityTaskManager)) doShow() else hide(sensorId) @BiometricOverlayConstants.ShowReason reason: Int
) = if (reason.isReasonToShow(activityTaskManager)) show() else hide()
private fun doShow() = mainExecutor.execute { override fun hide(sensorId: Int) = hide()
if (overlayView == null) { })
createOverlayForDisplay()
} else {
Log.v(TAG, "overlay already shown")
}
}
override fun hide(sensorId: Int) = mainExecutor.execute { overlayView = null }
})
overviewProxyService.addCallback(overviewProxyListener) overviewProxyService.addCallback(overviewProxyListener)
} }
/** Shows the side fps overlay if not already shown. */
fun show() {
mainExecutor.execute {
if (overlayView == null) {
createOverlayForDisplay()
} else {
Log.v(TAG, "overlay already shown")
}
}
}
/** Hides the fps overlay if shown. */
fun hide() {
mainExecutor.execute { overlayView = null }
}
private fun onOrientationChanged() { private fun onOrientationChanged() {
if (overlayView != null) { if (overlayView != null) {
createOverlayForDisplay() createOverlayForDisplay()
@@ -266,6 +274,12 @@ class SidefpsController @Inject constructor(
} }
} }
private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorPropertiesInternal?
get() = this?.sensorPropertiesInternal?.firstOrNull { it.isAnySidefpsType }
/** Returns [True] when the device has a side fingerprint sensor. */
fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
@BiometricOverlayConstants.ShowReason @BiometricOverlayConstants.ShowReason
private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) { private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) {
REASON_AUTH_KEYGUARD -> false REASON_AUTH_KEYGUARD -> false

View File

@@ -266,6 +266,9 @@ public class KeyguardBouncer {
private void setVisibility(@View.Visibility int visibility) { private void setVisibility(@View.Visibility int visibility) {
mContainer.setVisibility(visibility); mContainer.setVisibility(visibility);
if (mKeyguardViewController != null) {
mKeyguardViewController.onBouncerVisibilityChanged(visibility);
}
dispatchVisibilityChanged(); dispatchVisibilityChanged();
} }
@@ -645,7 +648,7 @@ public class KeyguardBouncer {
/** /**
* Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}. * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}.
* This is NOT called each time the bouncer is shown, but rather only when the fully * This is NOT called each time the bouncer is shown, but rather only when the fully
* shown amount has changed based on the panel expansion. The bouncer is visibility * shown amount has changed based on the panel expansion. The bouncer's visibility
* can still change when the expansion amount hasn't changed. * can still change when the expansion amount hasn't changed.
* See {@link KeyguardBouncer#isShowing()} for the checks for the bouncer showing state. * See {@link KeyguardBouncer#isShowing()} for the checks for the bouncer showing state.
*/ */

View File

@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -31,6 +32,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.testing.TestableResources; import android.testing.TestableResources;
import android.view.Gravity; import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@@ -42,6 +44,7 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
@@ -103,6 +106,17 @@ public class KeyguardHostViewControllerTest extends SysuiTestCase {
verify(mKeyguardSecurityContainerController).onStartingToHide(); verify(mKeyguardSecurityContainerController).onStartingToHide();
} }
@Test
public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() {
mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE);
mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE);
InOrder order = inOrder(mKeyguardSecurityContainerController);
order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE);
order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(
View.INVISIBLE);
}
@Test @Test
public void testGravityReappliedOnConfigurationChange() { public void testGravityReappliedOnConfigurationChange() {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(

View File

@@ -25,17 +25,21 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsetsController; import android.view.WindowInsetsController;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -46,6 +50,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.SidefpsController;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.log.SessionTracker; import com.android.systemui.log.SessionTracker;
@@ -59,10 +64,14 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import java.util.Optional;
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper() @TestableLooper.RunWithLooper()
@@ -124,6 +133,14 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
private SessionTracker mSessionTracker; private SessionTracker mSessionTracker;
@Mock @Mock
private KeyguardViewController mKeyguardViewController; private KeyguardViewController mKeyguardViewController;
@Mock
private SidefpsController mSidefpsController;
@Mock
private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
private Configuration mConfiguration; private Configuration mConfiguration;
private KeyguardSecurityContainerController mKeyguardSecurityContainerController; private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
@@ -160,7 +177,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mKeyguardStateController, mKeyguardSecurityViewFlipperController, mKeyguardStateController, mKeyguardSecurityViewFlipperController,
mConfigurationController, mFalsingCollector, mFalsingManager, mConfigurationController, mFalsingCollector, mFalsingManager,
mUserSwitcherController, mFeatureFlags, mGlobalSettings, mUserSwitcherController, mFeatureFlags, mGlobalSettings,
mSessionTracker).create(mSecurityCallback); mSessionTracker, Optional.of(mSidefpsController)).create(mSecurityCallback);
} }
@Test @Test
@@ -258,9 +275,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
@Test @Test
public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() { public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true); when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
when(mKeyguardSecurityViewFlipperController.getSecurityView( setupGetSecurityView();
eq(SecurityMode.Password), any(KeyguardSecurityCallback.class)))
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password); mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager, verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
@@ -276,4 +291,126 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
verify(mUserSwitcherController) verify(mUserSwitcherController)
.removeUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class)); .removeUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class));
} }
@Test
public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
setupConditionsToEnableSideFpsHint();
reset(mSidefpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).show();
verify(mSidefpsController, never()).hide();
}
@Test
public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint();
setFingerprintDetectionRunning(false);
reset(mSidefpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
@Test
public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint();
setSidedSecurityMode(false);
reset(mSidefpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
@Test
public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint();
setNeedsStrongAuth(true);
reset(mSidefpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
@Test
public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() {
setupGetSecurityView();
setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show();
reset(mSidefpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
@Test
public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
setupGetSecurityView();
setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show();
reset(mSidefpsController);
mKeyguardSecurityContainerController.onStartingToHide();
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
@Test
public void onPause_sideFpsHintShown_sideFpsHintHidden() {
setupGetSecurityView();
setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show();
reset(mSidefpsController);
mKeyguardSecurityContainerController.onPause();
verify(mSidefpsController).hide();
verify(mSidefpsController, never()).show();
}
private void setupConditionsToEnableSideFpsHint() {
attachView();
setSidedSecurityMode(true);
setFingerprintDetectionRunning(true);
setNeedsStrongAuth(false);
}
private void attachView() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
}
private void setFingerprintDetectionRunning(boolean running) {
when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(running);
mKeyguardUpdateMonitorCallback.getValue().onBiometricRunningStateChanged(running,
BiometricSourceType.FINGERPRINT);
}
private void setSidedSecurityMode(boolean sided) {
when(mView.isSidedSecurityMode()).thenReturn(sided);
}
private void setNeedsStrongAuth(boolean needed) {
when(mKeyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(needed);
mKeyguardUpdateMonitorCallback.getValue().onStrongAuthStateChanged(/* userId= */ 0);
}
private void setupGetSecurityView() {
when(mKeyguardSecurityViewFlipperController.getSecurityView(
any(), any(KeyguardSecurityCallback.class)))
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewControllerMock);
}
} }

View File

@@ -62,7 +62,6 @@ import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.eq import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any import org.mockito.Mockito.any
import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyFloat
import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyInt
@@ -72,6 +71,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.reset import org.mockito.Mockito.reset
import org.mockito.Mockito.times import org.mockito.Mockito.times
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenEver
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
private const val DISPLAY_ID = 2 private const val DISPLAY_ID = 2
@@ -126,15 +126,15 @@ class SidefpsControllerTest : SysuiTestCase() {
context.addMockSystemService(DisplayManager::class.java, displayManager) context.addMockSystemService(DisplayManager::class.java, displayManager)
context.addMockSystemService(WindowManager::class.java, windowManager) context.addMockSystemService(WindowManager::class.java, windowManager)
`when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView) whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView)
`when`(sidefpsView.findViewById<LottieAnimationView>(eq(R.id.sidefps_animation))) whenEver(sidefpsView.findViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
.thenReturn(mock(LottieAnimationView::class.java)) .thenReturn(mock(LottieAnimationView::class.java))
with(mock(ViewPropertyAnimator::class.java)) { with(mock(ViewPropertyAnimator::class.java)) {
`when`(sidefpsView.animate()).thenReturn(this) whenEver(sidefpsView.animate()).thenReturn(this)
`when`(alpha(anyFloat())).thenReturn(this) whenEver(alpha(anyFloat())).thenReturn(this)
`when`(setStartDelay(anyLong())).thenReturn(this) whenEver(setStartDelay(anyLong())).thenReturn(this)
`when`(setDuration(anyLong())).thenReturn(this) whenEver(setDuration(anyLong())).thenReturn(this)
`when`(setListener(any())).thenAnswer { whenEver(setListener(any())).thenAnswer {
(it.arguments[0] as Animator.AnimatorListener) (it.arguments[0] as Animator.AnimatorListener)
.onAnimationEnd(mock(Animator::class.java)) .onAnimationEnd(mock(Animator::class.java))
this this
@@ -177,7 +177,7 @@ class SidefpsControllerTest : SysuiTestCase() {
displayBounds = Rect(0, 0, displayWidth, displayHeight) displayBounds = Rect(0, 0, displayWidth, displayHeight)
var locations = listOf(sensorLocation) var locations = listOf(sensorLocation)
`when`(fingerprintManager.sensorPropertiesInternal).thenReturn( whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(
listOf( listOf(
FingerprintSensorPropertiesInternal( FingerprintSensorPropertiesInternal(
SENSOR_ID, SENSOR_ID,
@@ -196,12 +196,12 @@ class SidefpsControllerTest : SysuiTestCase() {
displayInfo.initInfo() displayInfo.initInfo()
val dmGlobal = mock(DisplayManagerGlobal::class.java) val dmGlobal = mock(DisplayManagerGlobal::class.java)
val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS) val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
`when`(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
`when`(windowManager.defaultDisplay).thenReturn(display) whenEver(windowManager.defaultDisplay).thenReturn(display)
`when`(windowManager.maximumWindowMetrics).thenReturn( whenEver(windowManager.maximumWindowMetrics).thenReturn(
WindowMetrics(displayBounds, WindowInsets.CONSUMED) WindowMetrics(displayBounds, WindowInsets.CONSUMED)
) )
`when`(windowManager.currentWindowMetrics).thenReturn( whenEver(windowManager.currentWindowMetrics).thenReturn(
WindowMetrics(displayBounds, windowInsets) WindowMetrics(displayBounds, windowInsets)
) )
@@ -277,13 +277,13 @@ class SidefpsControllerTest : SysuiTestCase() {
@Test @Test
fun testShowsForMostSettings() = testWithDisplay { fun testShowsForMostSettings() = testWithDisplay {
`when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask())) whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask()))
testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false) testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false)
} }
@Test @Test
fun testIgnoredForVerySpecificSettings() = testWithDisplay { fun testIgnoredForVerySpecificSettings() = testWithDisplay {
`when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask())) whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask()))
testIgnoredFor(REASON_AUTH_SETTINGS) testIgnoredFor(REASON_AUTH_SETTINGS)
} }
@@ -424,6 +424,20 @@ class SidefpsControllerTest : SysuiTestCase() {
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
} }
@Test
fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
// By default all those tests assume the side fps sensor is available.
assertThat(fingerprintManager.hasSideFpsSensor()).isTrue()
}
@Test
fun hasSideFpsSensor_withoutSensorProps_returnsFalse() {
whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(null)
assertThat(fingerprintManager.hasSideFpsSensor()).isFalse()
}
} }
private fun insetsForSmallNavbar() = insetsWithBottom(60) private fun insetsForSmallNavbar() = insetsWithBottom(60)

View File

@@ -229,6 +229,15 @@ public class KeyguardBouncerTest extends SysuiTestCase {
verify(mContainer).announceForAccessibility(any()); verify(mContainer).announceForAccessibility(any());
} }
@Test
public void show_notifiesKeyguardViewController() {
mBouncer.ensureView();
mBouncer.show(/* resetSecuritySelection= */ false);
verify(mKeyguardHostViewController).onBouncerVisibilityChanged(View.VISIBLE);
}
@Test @Test
public void testHide_notifiesFalsingManager() { public void testHide_notifiesFalsingManager() {
mBouncer.hide(false); mBouncer.hide(false);