Merge "Add SideFpsController dump" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-11-05 02:35:06 +00:00
committed by Android (Google) Code Review
7 changed files with 390 additions and 349 deletions

View File

@@ -58,7 +58,8 @@ 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.biometrics.SideFpsController;
import com.android.systemui.biometrics.SideFpsUiRequestSource;
import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
@@ -100,7 +101,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 final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate; private final FalsingA11yDelegate mFalsingA11yDelegate;
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -290,7 +291,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FeatureFlags featureFlags, FeatureFlags featureFlags,
GlobalSettings globalSettings, GlobalSettings globalSettings,
SessionTracker sessionTracker, SessionTracker sessionTracker,
Optional<SidefpsController> sidefpsController, Optional<SideFpsController> sideFpsController,
FalsingA11yDelegate falsingA11yDelegate) { FalsingA11yDelegate falsingA11yDelegate) {
super(view); super(view);
mLockPatternUtils = lockPatternUtils; mLockPatternUtils = lockPatternUtils;
@@ -311,7 +312,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings; mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker; mSessionTracker = sessionTracker;
mSidefpsController = sidefpsController; mSideFpsController = sideFpsController;
mFalsingA11yDelegate = falsingA11yDelegate; mFalsingA11yDelegate = falsingA11yDelegate;
} }
@@ -351,7 +352,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
} }
private void updateSideFpsVisibility() { private void updateSideFpsVisibility() {
if (!mSidefpsController.isPresent()) { if (!mSideFpsController.isPresent()) {
return; return;
} }
final boolean sfpsEnabled = getResources().getBoolean( final boolean sfpsEnabled = getResources().getBoolean(
@@ -369,9 +370,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
+ "needsStrongAuth=" + needsStrongAuth); + "needsStrongAuth=" + needsStrongAuth);
} }
if (toShow) { if (toShow) {
mSidefpsController.get().show(); mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
} else { } else {
mSidefpsController.get().hide(); mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
} }
} }
@@ -745,7 +746,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; private final Optional<SideFpsController> mSidefpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate; private final FalsingA11yDelegate mFalsingA11yDelegate;
@Inject @Inject
@@ -766,7 +767,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FeatureFlags featureFlags, FeatureFlags featureFlags,
GlobalSettings globalSettings, GlobalSettings globalSettings,
SessionTracker sessionTracker, SessionTracker sessionTracker,
Optional<SidefpsController> sidefpsController, Optional<SideFpsController> sidefpsController,
FalsingA11yDelegate falsingA11yDelegate) { FalsingA11yDelegate falsingA11yDelegate) {
mView = view; mView = view;
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory; mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;

View File

@@ -16,7 +16,7 @@
package com.android.keyguard.dagger; package com.android.keyguard.dagger;
import static com.android.systemui.biometrics.SidefpsControllerKt.hasSideFpsSensor; import static com.android.systemui.biometrics.SideFpsControllerKt.hasSideFpsSensor;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
@@ -27,7 +27,7 @@ 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.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;
@@ -70,12 +70,12 @@ public interface KeyguardBouncerModule {
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 {@link SideFpsController} if the device has the side fingerprint sensor. */
@Provides @Provides
@KeyguardBouncerScope @KeyguardBouncerScope
static Optional<SidefpsController> providesOptionalSidefpsController( static Optional<SideFpsController> providesOptionalSidefpsController(
@Nullable FingerprintManager fingerprintManager, @Nullable FingerprintManager fingerprintManager,
Provider<SidefpsController> sidefpsControllerProvider) { Provider<SideFpsController> sidefpsControllerProvider) {
if (!hasSideFpsSensor(fingerprintManager)) { if (!hasSideFpsSensor(fingerprintManager)) {
return Optional.empty(); return Optional.empty();
} }

View File

@@ -119,7 +119,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@Nullable private final FingerprintManager mFingerprintManager; @Nullable private final FingerprintManager mFingerprintManager;
@Nullable private final FaceManager mFaceManager; @Nullable private final FaceManager mFaceManager;
private final Provider<UdfpsController> mUdfpsControllerFactory; private final Provider<UdfpsController> mUdfpsControllerFactory;
private final Provider<SidefpsController> mSidefpsControllerFactory; private final Provider<SideFpsController> mSidefpsControllerFactory;
private final Display mDisplay; private final Display mDisplay;
private float mScaleFactor = 1f; private float mScaleFactor = 1f;
@@ -141,7 +141,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@NonNull private final DisplayManager mDisplayManager; @NonNull private final DisplayManager mDisplayManager;
@Nullable private UdfpsController mUdfpsController; @Nullable private UdfpsController mUdfpsController;
@Nullable private IUdfpsHbmListener mUdfpsHbmListener; @Nullable private IUdfpsHbmListener mUdfpsHbmListener;
@Nullable private SidefpsController mSidefpsController; @Nullable private SideFpsController mSideFpsController;
@Nullable private IBiometricContextListener mBiometricContextListener; @Nullable private IBiometricContextListener mBiometricContextListener;
@VisibleForTesting IBiometricSysuiReceiver mReceiver; @VisibleForTesting IBiometricSysuiReceiver mReceiver;
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener; @VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@@ -316,7 +316,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null; mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
if (mSidefpsProps != null) { if (mSidefpsProps != null) {
mSidefpsController = mSidefpsControllerFactory.get(); mSideFpsController = mSidefpsControllerFactory.get();
} }
updateSensorLocations(); updateSensorLocations();
@@ -677,7 +677,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@Nullable FingerprintManager fingerprintManager, @Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager, @Nullable FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory, Provider<UdfpsController> udfpsControllerFactory,
Provider<SidefpsController> sidefpsControllerFactory, Provider<SideFpsController> sidefpsControllerFactory,
@NonNull DisplayManager displayManager, @NonNull DisplayManager displayManager,
@NonNull WakefulnessLifecycle wakefulnessLifecycle, @NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull UserManager userManager, @NonNull UserManager userManager,
@@ -1054,7 +1054,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
* Whether the passed userId has enrolled SFPS. * Whether the passed userId has enrolled SFPS.
*/ */
public boolean isSfpsEnrolled(int userId) { public boolean isSfpsEnrolled(int userId) {
if (mSidefpsController == null) { if (mSideFpsController == null) {
return false; return false;
} }

View File

@@ -51,20 +51,25 @@ import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieProperty import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.model.KeyPath import com.airbnb.lottie.model.KeyPath
import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor
import java.io.PrintWriter
import javax.inject.Inject import javax.inject.Inject
private const val TAG = "SidefpsController" private const val TAG = "SideFpsController"
/** /**
* Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events. * Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events.
*/ */
@SysUISingleton @SysUISingleton
class SidefpsController @Inject constructor( class SideFpsController
@Inject
constructor(
private val context: Context, private val context: Context,
private val layoutInflater: LayoutInflater, private val layoutInflater: LayoutInflater,
fingerprintManager: FingerprintManager?, fingerprintManager: FingerprintManager?,
@@ -73,29 +78,34 @@ class SidefpsController @Inject constructor(
overviewProxyService: OverviewProxyService, overviewProxyService: OverviewProxyService,
displayManager: DisplayManager, displayManager: DisplayManager,
@Main private val mainExecutor: DelayableExecutor, @Main private val mainExecutor: DelayableExecutor,
@Main private val handler: Handler @Main private val handler: Handler,
) { dumpManager: DumpManager
@VisibleForTesting ) : Dumpable {
val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager val requests: HashSet<SideFpsUiRequestSource> = HashSet()
?.sideFpsSensorProperties
?: throw IllegalStateException("no side fingerprint sensor")
@VisibleForTesting @VisibleForTesting
val orientationListener = BiometricDisplayListener( val sensorProps: FingerprintSensorPropertiesInternal =
context, fingerprintManager?.sideFpsSensorProperties
displayManager, ?: throw IllegalStateException("no side fingerprint sensor")
handler,
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
) { onOrientationChanged() }
@VisibleForTesting @VisibleForTesting
val overviewProxyListener = object : OverviewProxyService.OverviewProxyListener { val orientationListener =
override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) { BiometricDisplayListener(
overlayView?.let { view -> context,
handler.postDelayed({ updateOverlayVisibility(view) }, 500) displayManager,
handler,
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
) { onOrientationChanged() }
@VisibleForTesting
val overviewProxyListener =
object : OverviewProxyService.OverviewProxyListener {
override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
overlayView?.let { view ->
handler.postDelayed({ updateOverlayVisibility(view) }, 500)
}
} }
} }
}
private val animationDuration = private val animationDuration =
context.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong() context.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()
@@ -121,19 +131,22 @@ class SidefpsController @Inject constructor(
@VisibleForTesting @VisibleForTesting
internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT
private val overlayViewParams = WindowManager.LayoutParams( private val overlayViewParams =
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, WindowManager.LayoutParams.WRAP_CONTENT,
Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
PixelFormat.TRANSLUCENT Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
).apply { PixelFormat.TRANSLUCENT
title = TAG )
fitInsetsTypes = 0 // overrides default, avoiding status bars during layout .apply {
gravity = Gravity.TOP or Gravity.LEFT title = TAG
layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION gravity = Gravity.TOP or Gravity.LEFT
} layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
}
init { init {
fingerprintManager?.setSidefpsController( fingerprintManager?.setSidefpsController(
@@ -141,15 +154,23 @@ class SidefpsController @Inject constructor(
override fun show( override fun show(
sensorId: Int, sensorId: Int,
@BiometricOverlayConstants.ShowReason reason: Int @BiometricOverlayConstants.ShowReason reason: Int
) = if (reason.isReasonToShow(activityTaskManager)) show() else hide() ) =
if (reason.isReasonToAutoShow(activityTaskManager)) {
show(SideFpsUiRequestSource.AUTO_SHOW)
} else {
hide(SideFpsUiRequestSource.AUTO_SHOW)
}
override fun hide(sensorId: Int) = hide() override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
}) }
)
overviewProxyService.addCallback(overviewProxyListener) overviewProxyService.addCallback(overviewProxyListener)
dumpManager.registerDumpable(this)
} }
/** Shows the side fps overlay if not already shown. */ /** Shows the side fps overlay if not already shown. */
fun show() { fun show(request: SideFpsUiRequestSource) {
requests.add(request)
mainExecutor.execute { mainExecutor.execute {
if (overlayView == null) { if (overlayView == null) {
createOverlayForDisplay() createOverlayForDisplay()
@@ -160,8 +181,20 @@ class SidefpsController @Inject constructor(
} }
/** Hides the fps overlay if shown. */ /** Hides the fps overlay if shown. */
fun hide() { fun hide(request: SideFpsUiRequestSource) {
mainExecutor.execute { overlayView = null } requests.remove(request)
mainExecutor.execute {
if (requests.isEmpty()) {
overlayView = null
}
}
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println("requests:")
for (requestSource in requests) {
pw.println(" $requestSource.name")
}
} }
private fun onOrientationChanged() { private fun onOrientationChanged() {
@@ -174,12 +207,13 @@ class SidefpsController @Inject constructor(
val view = layoutInflater.inflate(R.layout.sidefps_view, null, false) val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
overlayView = view overlayView = view
val display = context.display!! val display = context.display!!
val offsets = sensorProps.getLocation(display.uniqueId).let { location -> val offsets =
if (location == null) { sensorProps.getLocation(display.uniqueId).let { location ->
Log.w(TAG, "No location specified for display: ${display.uniqueId}") if (location == null) {
Log.w(TAG, "No location specified for display: ${display.uniqueId}")
}
location ?: sensorProps.location
} }
location ?: sensorProps.location
}
overlayOffsets = offsets overlayOffsets = offsets
val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView
@@ -195,21 +229,25 @@ class SidefpsController @Inject constructor(
/** /**
* Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from
* speaking @string/accessibility_fingerprint_label twice when sensor location indicator * speaking @string/accessibility_fingerprint_label twice when sensor location indicator is
* is in focus * in focus
*/ */
view.setAccessibilityDelegate(object : AccessibilityDelegate() { view.setAccessibilityDelegate(
override fun dispatchPopulateAccessibilityEvent( object : AccessibilityDelegate() {
host: View, override fun dispatchPopulateAccessibilityEvent(
event: AccessibilityEvent host: View,
): Boolean { event: AccessibilityEvent
return if (event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { ): Boolean {
true return if (
} else { event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
super.dispatchPopulateAccessibilityEvent(host, event) ) {
true
} else {
super.dispatchPopulateAccessibilityEvent(host, event)
}
} }
} }
}) )
} }
@VisibleForTesting @VisibleForTesting
@@ -220,21 +258,22 @@ class SidefpsController @Inject constructor(
val displayHeight = if (isNaturalOrientation) size.height() else size.width() val displayHeight = if (isNaturalOrientation) size.height() else size.width()
val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height() val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height()
val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width() val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width()
val sensorBounds = if (overlayOffsets.isYAligned()) { val sensorBounds =
Rect( if (overlayOffsets.isYAligned()) {
displayWidth - boundsWidth, Rect(
overlayOffsets.sensorLocationY, displayWidth - boundsWidth,
displayWidth, overlayOffsets.sensorLocationY,
overlayOffsets.sensorLocationY + boundsHeight displayWidth,
) overlayOffsets.sensorLocationY + boundsHeight
} else { )
Rect( } else {
overlayOffsets.sensorLocationX, Rect(
0, overlayOffsets.sensorLocationX,
overlayOffsets.sensorLocationX + boundsWidth, 0,
boundsHeight overlayOffsets.sensorLocationX + boundsWidth,
) boundsHeight
} )
}
RotationUtils.rotateBounds( RotationUtils.rotateBounds(
sensorBounds, sensorBounds,
@@ -254,19 +293,25 @@ class SidefpsController @Inject constructor(
// hide after a few seconds if the sensor is oriented down and there are // hide after a few seconds if the sensor is oriented down and there are
// large overlapping system bars // large overlapping system bars
val rotation = context.display?.rotation val rotation = context.display?.rotation
if (windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() && if (
((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) || windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
(rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))) { ((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
overlayHideAnimator = view.animate() (rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))
.alpha(0f) ) {
.setStartDelay(3_000) overlayHideAnimator =
.setDuration(animationDuration) view
.setListener(object : AnimatorListenerAdapter() { .animate()
override fun onAnimationEnd(animation: Animator) { .alpha(0f)
view.visibility = View.GONE .setStartDelay(3_000)
overlayHideAnimator = null .setDuration(animationDuration)
} .setListener(
}) object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
view.visibility = View.GONE
overlayHideAnimator = null
}
}
)
} else { } else {
overlayHideAnimator?.cancel() overlayHideAnimator?.cancel()
overlayHideAnimator = null overlayHideAnimator = null
@@ -283,32 +328,36 @@ private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorProper
fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
@BiometricOverlayConstants.ShowReason @BiometricOverlayConstants.ShowReason
private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) { private fun Int.isReasonToAutoShow(activityTaskManager: ActivityTaskManager): Boolean =
REASON_AUTH_KEYGUARD -> false when (this) {
REASON_AUTH_SETTINGS -> when (activityTaskManager.topClass()) { REASON_AUTH_KEYGUARD -> false
// TODO(b/186176653): exclude fingerprint overlays from this list view REASON_AUTH_SETTINGS ->
"com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false when (activityTaskManager.topClass()) {
// TODO(b/186176653): exclude fingerprint overlays from this list view
"com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
else -> true
}
else -> true else -> true
} }
else -> true
}
private fun ActivityTaskManager.topClass(): String = private fun ActivityTaskManager.topClass(): String =
getTasks(1).firstOrNull()?.topActivity?.className ?: "" getTasks(1).firstOrNull()?.topActivity?.className ?: ""
@RawRes @RawRes
private fun Display.asSideFpsAnimation(yAligned: Boolean): Int = when (rotation) { private fun Display.asSideFpsAnimation(yAligned: Boolean): Int =
Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape when (rotation) {
Surface.ROTATION_180 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
else -> if (yAligned) R.raw.sfps_pulse_landscape else R.raw.sfps_pulse Surface.ROTATION_180 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
} else -> if (yAligned) R.raw.sfps_pulse_landscape else R.raw.sfps_pulse
}
private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float = when (rotation) { private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float =
Surface.ROTATION_90 -> if (yAligned) 0f else 180f when (rotation) {
Surface.ROTATION_180 -> 180f Surface.ROTATION_90 -> if (yAligned) 0f else 180f
Surface.ROTATION_270 -> if (yAligned) 180f else 0f Surface.ROTATION_180 -> 180f
else -> 0f Surface.ROTATION_270 -> if (yAligned) 180f else 0f
} else -> 0f
}
private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0 private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0
@@ -322,10 +371,9 @@ private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
fun update() { fun update() {
val c = context.getColor(R.color.biometric_dialog_accent) val c = context.getColor(R.color.biometric_dialog_accent)
for (key in listOf(".blue600", ".blue400")) { for (key in listOf(".blue600", ".blue400")) {
addValueCallback( addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
KeyPath(key, "**"), PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP)
LottieProperty.COLOR_FILTER }
) { PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) }
} }
} }
@@ -335,3 +383,15 @@ private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
addLottieOnCompositionLoadedListener { update() } addLottieOnCompositionLoadedListener { update() }
} }
} }
/**
* The source of a request to show the side fps visual indicator. This is distinct from
* [BiometricOverlayConstants] which corrresponds with the reason fingerprint authentication is
* requested.
*/
enum class SideFpsUiRequestSource {
/** see [isReasonToAutoShow] */
AUTO_SHOW,
/** Pin, pattern or password bouncer */
PRIMARY_BOUNCER,
}

View File

@@ -54,7 +54,8 @@ 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.biometrics.SideFpsController;
import com.android.systemui.biometrics.SideFpsUiRequestSource;
import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
@@ -141,7 +142,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
@Mock @Mock
private KeyguardViewController mKeyguardViewController; private KeyguardViewController mKeyguardViewController;
@Mock @Mock
private SidefpsController mSidefpsController; private SideFpsController mSideFpsController;
@Mock @Mock
private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock; private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
@Mock @Mock
@@ -189,7 +190,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mKeyguardStateController, mKeyguardSecurityViewFlipperController, mKeyguardStateController, mKeyguardSecurityViewFlipperController,
mConfigurationController, mFalsingCollector, mFalsingManager, mConfigurationController, mFalsingCollector, mFalsingManager,
mUserSwitcherController, mFeatureFlags, mGlobalSettings, mUserSwitcherController, mFeatureFlags, mGlobalSettings,
mSessionTracker, Optional.of(mSidefpsController), mFalsingA11yDelegate).create( mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create(
mSecurityCallback); mSecurityCallback);
} }
@@ -345,48 +346,48 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
@Test @Test
public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() { public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).show(); verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).hide(); verify(mSideFpsController, never()).hide(any());
} }
@Test @Test
public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() { public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
setFingerprintDetectionRunning(false); setFingerprintDetectionRunning(false);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() { public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
setSideFpsHintEnabledFromResources(false); setSideFpsHintEnabledFromResources(false);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() { public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
setNeedsStrongAuth(true); setNeedsStrongAuth(true);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
@@ -394,13 +395,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
setupGetSecurityView(); setupGetSecurityView();
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show(); verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
@@ -408,13 +409,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
setupGetSecurityView(); setupGetSecurityView();
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show(); verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onStartingToHide(); mKeyguardSecurityContainerController.onStartingToHide();
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
@@ -422,13 +423,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
setupGetSecurityView(); setupGetSecurityView();
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
verify(mSidefpsController, atLeastOnce()).show(); verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onPause(); mKeyguardSecurityContainerController.onPause();
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test
@@ -436,12 +437,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
setupGetSecurityView(); setupGetSecurityView();
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onResume(0); mKeyguardSecurityContainerController.onResume(0);
verify(mSidefpsController).show(); verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).hide(); verify(mSideFpsController, never()).hide(any());
} }
@Test @Test
@@ -450,12 +451,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
setupConditionsToEnableSideFpsHint(); setupConditionsToEnableSideFpsHint();
setSideFpsHintEnabledFromResources(false); setSideFpsHintEnabledFromResources(false);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
reset(mSidefpsController); reset(mSideFpsController);
mKeyguardSecurityContainerController.onResume(0); mKeyguardSecurityContainerController.onResume(0);
verify(mSidefpsController).hide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
verify(mSidefpsController, never()).show(); verify(mSideFpsController, never()).show(any());
} }
@Test @Test

View File

@@ -145,7 +145,7 @@ public class AuthControllerTest extends SysuiTestCase {
@Mock @Mock
private UdfpsController mUdfpsController; private UdfpsController mUdfpsController;
@Mock @Mock
private SidefpsController mSidefpsController; private SideFpsController mSideFpsController;
@Mock @Mock
private DisplayManager mDisplayManager; private DisplayManager mDisplayManager;
@Mock @Mock
@@ -225,7 +225,7 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue, mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager, mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
() -> mUdfpsController, () -> mSidefpsController, mStatusBarStateController, () -> mUdfpsController, () -> mSideFpsController, mStatusBarStateController,
mVibratorHelper); mVibratorHelper);
mAuthController.start(); mAuthController.start();
@@ -256,7 +256,7 @@ public class AuthControllerTest extends SysuiTestCase {
// This test requires an uninitialized AuthController. // This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution, AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager, mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
mFaceManager, () -> mUdfpsController, () -> mSidefpsController, mFaceManager, () -> mUdfpsController, () -> mSideFpsController,
mStatusBarStateController, mVibratorHelper); mStatusBarStateController, mVibratorHelper);
authController.start(); authController.start();
@@ -282,7 +282,7 @@ public class AuthControllerTest extends SysuiTestCase {
// This test requires an uninitialized AuthController. // This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution, AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager, mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
mFaceManager, () -> mUdfpsController, () -> mSidefpsController, mFaceManager, () -> mUdfpsController, () -> mSideFpsController,
mStatusBarStateController, mVibratorHelper); mStatusBarStateController, mVibratorHelper);
authController.start(); authController.start();
@@ -936,7 +936,7 @@ public class AuthControllerTest extends SysuiTestCase {
FingerprintManager fingerprintManager, FingerprintManager fingerprintManager,
FaceManager faceManager, FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory, Provider<UdfpsController> udfpsControllerFactory,
Provider<SidefpsController> sidefpsControllerFactory, Provider<SideFpsController> sidefpsControllerFactory,
StatusBarStateController statusBarStateController, StatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper) { VibratorHelper vibratorHelper) {
super(context, execution, commandQueue, activityTaskManager, windowManager, super(context, execution, commandQueue, activityTaskManager, windowManager,

View File

@@ -52,6 +52,7 @@ import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView import com.airbnb.lottie.LottieAnimationView
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock
@@ -82,37 +83,31 @@ private const val SENSOR_ID = 1
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper @TestableLooper.RunWithLooper
class SidefpsControllerTest : SysuiTestCase() { class SideFpsControllerTest : SysuiTestCase() {
@JvmField @Rule @JvmField @Rule var rule = MockitoJUnit.rule()
var rule = MockitoJUnit.rule()
@Mock @Mock lateinit var layoutInflater: LayoutInflater
lateinit var layoutInflater: LayoutInflater @Mock lateinit var fingerprintManager: FingerprintManager
@Mock @Mock lateinit var windowManager: WindowManager
lateinit var fingerprintManager: FingerprintManager @Mock lateinit var activityTaskManager: ActivityTaskManager
@Mock @Mock lateinit var sideFpsView: View
lateinit var windowManager: WindowManager @Mock lateinit var displayManager: DisplayManager
@Mock @Mock lateinit var overviewProxyService: OverviewProxyService
lateinit var activityTaskManager: ActivityTaskManager @Mock lateinit var handler: Handler
@Mock @Mock lateinit var dumpManager: DumpManager
lateinit var sidefpsView: View @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
@Mock @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
lateinit var displayManager: DisplayManager
@Mock
lateinit var overviewProxyService: OverviewProxyService
@Mock
lateinit var handler: Handler
@Captor
lateinit var overlayCaptor: ArgumentCaptor<View>
@Captor
lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
private val executor = FakeExecutor(FakeSystemClock()) private val executor = FakeExecutor(FakeSystemClock())
private lateinit var overlayController: ISidefpsController private lateinit var overlayController: ISidefpsController
private lateinit var sideFpsController: SidefpsController private lateinit var sideFpsController: SideFpsController
enum class DeviceConfig { X_ALIGNED, Y_ALIGNED_UNFOLDED, Y_ALIGNED_FOLDED } enum class DeviceConfig {
X_ALIGNED,
Y_ALIGNED_UNFOLDED,
Y_ALIGNED_FOLDED
}
private lateinit var deviceConfig: DeviceConfig private lateinit var deviceConfig: DeviceConfig
private lateinit var indicatorBounds: Rect private lateinit var indicatorBounds: Rect
@@ -128,17 +123,18 @@ 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)
whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView) whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
whenEver(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)) {
whenEver(sidefpsView.animate()).thenReturn(this) whenEver(sideFpsView.animate()).thenReturn(this)
whenEver(alpha(anyFloat())).thenReturn(this) whenEver(alpha(anyFloat())).thenReturn(this)
whenEver(setStartDelay(anyLong())).thenReturn(this) whenEver(setStartDelay(anyLong())).thenReturn(this)
whenEver(setDuration(anyLong())).thenReturn(this) whenEver(setDuration(anyLong())).thenReturn(this)
whenEver(setListener(any())).thenAnswer { whenEver(setListener(any())).thenAnswer {
(it.arguments[0] as Animator.AnimatorListener) (it.arguments[0] as Animator.AnimatorListener).onAnimationEnd(
.onAnimationEnd(mock(Animator::class.java)) mock(Animator::class.java)
)
this this
} }
} }
@@ -179,20 +175,21 @@ class SidefpsControllerTest : SysuiTestCase() {
displayBounds = Rect(0, 0, displayWidth, displayHeight) displayBounds = Rect(0, 0, displayWidth, displayHeight)
var locations = listOf(sensorLocation) var locations = listOf(sensorLocation)
whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn( whenEver(fingerprintManager.sensorPropertiesInternal)
listOf( .thenReturn(
FingerprintSensorPropertiesInternal( listOf(
SENSOR_ID, FingerprintSensorPropertiesInternal(
SensorProperties.STRENGTH_STRONG, SENSOR_ID,
5 /* maxEnrollmentsPerUser */, SensorProperties.STRENGTH_STRONG,
listOf() /* componentInfo */, 5 /* maxEnrollmentsPerUser */,
FingerprintSensorProperties.TYPE_POWER_BUTTON, listOf() /* componentInfo */,
true /* halControlsIllumination */, FingerprintSensorProperties.TYPE_POWER_BUTTON,
true /* resetLockoutRequiresHardwareAuthToken */, true /* halControlsIllumination */,
locations true /* resetLockoutRequiresHardwareAuthToken */,
locations
)
) )
) )
)
val displayInfo = DisplayInfo() val displayInfo = DisplayInfo()
displayInfo.initInfo() displayInfo.initInfo()
@@ -200,22 +197,29 @@ class SidefpsControllerTest : SysuiTestCase() {
val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS) val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
whenEver(windowManager.defaultDisplay).thenReturn(display) whenEver(windowManager.defaultDisplay).thenReturn(display)
whenEver(windowManager.maximumWindowMetrics).thenReturn( whenEver(windowManager.maximumWindowMetrics)
WindowMetrics(displayBounds, WindowInsets.CONSUMED) .thenReturn(WindowMetrics(displayBounds, WindowInsets.CONSUMED))
) whenEver(windowManager.currentWindowMetrics)
whenEver(windowManager.currentWindowMetrics).thenReturn( .thenReturn(WindowMetrics(displayBounds, windowInsets))
WindowMetrics(displayBounds, windowInsets)
)
sideFpsController = SidefpsController( sideFpsController =
context.createDisplayContext(display), layoutInflater, fingerprintManager, SideFpsController(
windowManager, activityTaskManager, overviewProxyService, displayManager, executor, context.createDisplayContext(display),
handler layoutInflater,
) fingerprintManager,
windowManager,
activityTaskManager,
overviewProxyService,
displayManager,
executor,
handler,
dumpManager
)
overlayController = ArgumentCaptor.forClass(ISidefpsController::class.java).apply { overlayController =
verify(fingerprintManager).setSidefpsController(capture()) ArgumentCaptor.forClass(ISidefpsController::class.java)
}.value .apply { verify(fingerprintManager).setSidefpsController(capture()) }
.value
block() block()
} }
@@ -272,10 +276,7 @@ class SidefpsControllerTest : SysuiTestCase() {
verify(windowManager).removeView(any()) verify(windowManager).removeView(any())
} }
@Test @Test fun testIgnoredForKeyguard() = testWithDisplay { testIgnoredFor(REASON_AUTH_KEYGUARD) }
fun testIgnoredForKeyguard() = testWithDisplay {
testIgnoredFor(REASON_AUTH_KEYGUARD)
}
@Test @Test
fun testShowsForMostSettings() = testWithDisplay { fun testShowsForMostSettings() = testWithDisplay {
@@ -297,88 +298,76 @@ class SidefpsControllerTest : SysuiTestCase() {
} }
@Test @Test
fun showsWithTaskbar() = testWithDisplay( fun showsWithTaskbar() =
deviceConfig = DeviceConfig.X_ALIGNED, testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_0 }) {
{ rotation = Surface.ROTATION_0 } hidesWithTaskbar(visible = true)
) { }
hidesWithTaskbar(visible = true)
}
@Test @Test
fun showsWithTaskbarOnY() = testWithDisplay( fun showsWithTaskbarOnY() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, testWithDisplay(
{ rotation = Surface.ROTATION_0 } deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
) { { rotation = Surface.ROTATION_0 }
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun showsWithTaskbar90() = testWithDisplay( fun showsWithTaskbar90() =
deviceConfig = DeviceConfig.X_ALIGNED, testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_90 }) {
{ rotation = Surface.ROTATION_90 } hidesWithTaskbar(visible = true)
) { }
hidesWithTaskbar(visible = true)
}
@Test @Test
fun showsWithTaskbar90OnY() = testWithDisplay( fun showsWithTaskbar90OnY() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, testWithDisplay(
{ rotation = Surface.ROTATION_90 } deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
) { { rotation = Surface.ROTATION_90 }
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun showsWithTaskbar180() = testWithDisplay( fun showsWithTaskbar180() =
deviceConfig = DeviceConfig.X_ALIGNED, testWithDisplay(
{ rotation = Surface.ROTATION_180 } deviceConfig = DeviceConfig.X_ALIGNED,
) { { rotation = Surface.ROTATION_180 }
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun showsWithTaskbar270OnY() = testWithDisplay( fun showsWithTaskbar270OnY() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, testWithDisplay(
{ rotation = Surface.ROTATION_270 } deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
) { { rotation = Surface.ROTATION_270 }
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun showsWithTaskbarCollapsedDown() = testWithDisplay( fun showsWithTaskbarCollapsedDown() =
deviceConfig = DeviceConfig.X_ALIGNED, testWithDisplay(
{ rotation = Surface.ROTATION_270 }, deviceConfig = DeviceConfig.X_ALIGNED,
windowInsets = insetsForSmallNavbar() { rotation = Surface.ROTATION_270 },
) { windowInsets = insetsForSmallNavbar()
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun showsWithTaskbarCollapsedDownOnY() = testWithDisplay( fun showsWithTaskbarCollapsedDownOnY() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, testWithDisplay(
{ rotation = Surface.ROTATION_180 }, deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
windowInsets = insetsForSmallNavbar() { rotation = Surface.ROTATION_180 },
) { windowInsets = insetsForSmallNavbar()
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
@Test @Test
fun hidesWithTaskbarDown() = testWithDisplay( fun hidesWithTaskbarDown() =
deviceConfig = DeviceConfig.X_ALIGNED, testWithDisplay(
{ rotation = Surface.ROTATION_180 }, deviceConfig = DeviceConfig.X_ALIGNED,
windowInsets = insetsForLargeNavbar() { rotation = Surface.ROTATION_180 },
) { windowInsets = insetsForLargeNavbar()
hidesWithTaskbar(visible = false) ) { hidesWithTaskbar(visible = false) }
}
@Test @Test
fun hidesWithTaskbarDownOnY() = testWithDisplay( fun hidesWithTaskbarDownOnY() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, testWithDisplay(
{ rotation = Surface.ROTATION_270 }, deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
windowInsets = insetsForLargeNavbar() { rotation = Surface.ROTATION_270 },
) { windowInsets = insetsForLargeNavbar()
hidesWithTaskbar(visible = true) ) { hidesWithTaskbar(visible = true) }
}
private fun hidesWithTaskbar(visible: Boolean) { private fun hidesWithTaskbar(visible: Boolean) {
overlayController.show(SENSOR_ID, REASON_UNKNOWN) overlayController.show(SENSOR_ID, REASON_UNKNOWN)
@@ -389,43 +378,35 @@ class SidefpsControllerTest : SysuiTestCase() {
verify(windowManager).addView(any(), any()) verify(windowManager).addView(any(), any())
verify(windowManager, never()).removeView(any()) verify(windowManager, never()).removeView(any())
verify(sidefpsView).visibility = if (visible) View.VISIBLE else View.GONE verify(sideFpsView).visibility = if (visible) View.VISIBLE else View.GONE
} }
@Test @Test
fun testIndicatorPlacementForXAlignedSensor() = testWithDisplay( fun testIndicatorPlacementForXAlignedSensor() =
deviceConfig = DeviceConfig.X_ALIGNED testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED) {
) { overlayController.show(SENSOR_ID, REASON_UNKNOWN)
overlayController.show(SENSOR_ID, REASON_UNKNOWN) sideFpsController.overlayOffsets = sensorLocation
sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
sideFpsController.updateOverlayParams( executor.runAllReady()
windowManager.defaultDisplay,
indicatorBounds
)
executor.runAllReady()
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
} }
@Test @Test
fun testIndicatorPlacementForYAlignedSensor() = testWithDisplay( fun testIndicatorPlacementForYAlignedSensor() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
) { sideFpsController.overlayOffsets = sensorLocation
sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
sideFpsController.updateOverlayParams( overlayController.show(SENSOR_ID, REASON_UNKNOWN)
windowManager.defaultDisplay, executor.runAllReady()
indicatorBounds
)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
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 @Test
fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay { fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
@@ -442,52 +423,50 @@ class SidefpsControllerTest : SysuiTestCase() {
} }
@Test @Test
fun testLayoutParams_hasNoMoveAnimationWindowFlag() = testWithDisplay( fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
) { sideFpsController.overlayOffsets = sensorLocation
sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
sideFpsController.updateOverlayParams( overlayController.show(SENSOR_ID, REASON_UNKNOWN)
windowManager.defaultDisplay, executor.runAllReady()
indicatorBounds
)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
val lpFlags = overlayViewParamsCaptor.value.privateFlags val lpFlags = overlayViewParamsCaptor.value.privateFlags
assertThat((lpFlags and PRIVATE_FLAG_NO_MOVE_ANIMATION) != 0).isTrue() assertThat((lpFlags and PRIVATE_FLAG_NO_MOVE_ANIMATION) != 0).isTrue()
} }
@Test @Test
fun testLayoutParams_hasTrustedOverlayWindowFlag() = testWithDisplay( fun testLayoutParams_hasTrustedOverlayWindowFlag() =
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
) { sideFpsController.overlayOffsets = sensorLocation
sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
sideFpsController.updateOverlayParams( overlayController.show(SENSOR_ID, REASON_UNKNOWN)
windowManager.defaultDisplay, executor.runAllReady()
indicatorBounds
)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
val lpFlags = overlayViewParamsCaptor.value.privateFlags val lpFlags = overlayViewParamsCaptor.value.privateFlags
assertThat((lpFlags and PRIVATE_FLAG_TRUSTED_OVERLAY) != 0).isTrue() assertThat((lpFlags and PRIVATE_FLAG_TRUSTED_OVERLAY) != 0).isTrue()
} }
} }
private fun insetsForSmallNavbar() = insetsWithBottom(60) private fun insetsForSmallNavbar() = insetsWithBottom(60)
private fun insetsForLargeNavbar() = insetsWithBottom(100) private fun insetsForLargeNavbar() = insetsWithBottom(100)
private fun insetsWithBottom(bottom: Int) = WindowInsets.Builder()
.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom)) private fun insetsWithBottom(bottom: Int) =
.build() WindowInsets.Builder()
.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom))
.build()
private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling") private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling")
private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings") private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings")
private fun settingsTask(cls: String) = ActivityManager.RunningTaskInfo().apply {
topActivity = ComponentName.createRelative("com.android.settings", cls) private fun settingsTask(cls: String) =
} ActivityManager.RunningTaskInfo().apply {
topActivity = ComponentName.createRelative("com.android.settings", cls)
}