Merge "Add SideFpsController dump" into tm-qpr-dev am: 9935dae627
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20378334 Change-Id: I6d2875caeafcd9c9bed7991aada01ad055adb4d1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -58,7 +58,8 @@ import com.android.keyguard.dagger.KeyguardBouncerScope;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.systemui.Gefingerpoken;
|
||||
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.FalsingCollector;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
@@ -100,7 +101,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
private final GlobalSettings mGlobalSettings;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final SessionTracker mSessionTracker;
|
||||
private final Optional<SidefpsController> mSidefpsController;
|
||||
private final Optional<SideFpsController> mSideFpsController;
|
||||
private final FalsingA11yDelegate mFalsingA11yDelegate;
|
||||
|
||||
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
@@ -290,7 +291,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
FeatureFlags featureFlags,
|
||||
GlobalSettings globalSettings,
|
||||
SessionTracker sessionTracker,
|
||||
Optional<SidefpsController> sidefpsController,
|
||||
Optional<SideFpsController> sideFpsController,
|
||||
FalsingA11yDelegate falsingA11yDelegate) {
|
||||
super(view);
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
@@ -311,7 +312,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
mFeatureFlags = featureFlags;
|
||||
mGlobalSettings = globalSettings;
|
||||
mSessionTracker = sessionTracker;
|
||||
mSidefpsController = sidefpsController;
|
||||
mSideFpsController = sideFpsController;
|
||||
mFalsingA11yDelegate = falsingA11yDelegate;
|
||||
}
|
||||
|
||||
@@ -351,7 +352,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
}
|
||||
|
||||
private void updateSideFpsVisibility() {
|
||||
if (!mSidefpsController.isPresent()) {
|
||||
if (!mSideFpsController.isPresent()) {
|
||||
return;
|
||||
}
|
||||
final boolean sfpsEnabled = getResources().getBoolean(
|
||||
@@ -369,9 +370,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
+ "needsStrongAuth=" + needsStrongAuth);
|
||||
}
|
||||
if (toShow) {
|
||||
mSidefpsController.get().show();
|
||||
mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
} 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 UserSwitcherController mUserSwitcherController;
|
||||
private final SessionTracker mSessionTracker;
|
||||
private final Optional<SidefpsController> mSidefpsController;
|
||||
private final Optional<SideFpsController> mSidefpsController;
|
||||
private final FalsingA11yDelegate mFalsingA11yDelegate;
|
||||
|
||||
@Inject
|
||||
@@ -766,7 +767,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
FeatureFlags featureFlags,
|
||||
GlobalSettings globalSettings,
|
||||
SessionTracker sessionTracker,
|
||||
Optional<SidefpsController> sidefpsController,
|
||||
Optional<SideFpsController> sidefpsController,
|
||||
FalsingA11yDelegate falsingA11yDelegate) {
|
||||
mView = view;
|
||||
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
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.hardware.fingerprint.FingerprintManager;
|
||||
@@ -27,7 +27,7 @@ import com.android.keyguard.KeyguardHostView;
|
||||
import com.android.keyguard.KeyguardSecurityContainer;
|
||||
import com.android.keyguard.KeyguardSecurityViewFlipper;
|
||||
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.statusbar.phone.KeyguardBouncer;
|
||||
|
||||
@@ -70,12 +70,12 @@ public interface KeyguardBouncerModule {
|
||||
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
|
||||
@KeyguardBouncerScope
|
||||
static Optional<SidefpsController> providesOptionalSidefpsController(
|
||||
static Optional<SideFpsController> providesOptionalSidefpsController(
|
||||
@Nullable FingerprintManager fingerprintManager,
|
||||
Provider<SidefpsController> sidefpsControllerProvider) {
|
||||
Provider<SideFpsController> sidefpsControllerProvider) {
|
||||
if (!hasSideFpsSensor(fingerprintManager)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@Nullable private final FingerprintManager mFingerprintManager;
|
||||
@Nullable private final FaceManager mFaceManager;
|
||||
private final Provider<UdfpsController> mUdfpsControllerFactory;
|
||||
private final Provider<SidefpsController> mSidefpsControllerFactory;
|
||||
private final Provider<SideFpsController> mSidefpsControllerFactory;
|
||||
|
||||
private final Display mDisplay;
|
||||
private float mScaleFactor = 1f;
|
||||
@@ -141,7 +141,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@NonNull private final DisplayManager mDisplayManager;
|
||||
@Nullable private UdfpsController mUdfpsController;
|
||||
@Nullable private IUdfpsHbmListener mUdfpsHbmListener;
|
||||
@Nullable private SidefpsController mSidefpsController;
|
||||
@Nullable private SideFpsController mSideFpsController;
|
||||
@Nullable private IBiometricContextListener mBiometricContextListener;
|
||||
@VisibleForTesting IBiometricSysuiReceiver mReceiver;
|
||||
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
|
||||
@@ -316,7 +316,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
|
||||
mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
|
||||
if (mSidefpsProps != null) {
|
||||
mSidefpsController = mSidefpsControllerFactory.get();
|
||||
mSideFpsController = mSidefpsControllerFactory.get();
|
||||
}
|
||||
|
||||
updateSensorLocations();
|
||||
@@ -677,7 +677,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@Nullable FingerprintManager fingerprintManager,
|
||||
@Nullable FaceManager faceManager,
|
||||
Provider<UdfpsController> udfpsControllerFactory,
|
||||
Provider<SidefpsController> sidefpsControllerFactory,
|
||||
Provider<SideFpsController> sidefpsControllerFactory,
|
||||
@NonNull DisplayManager displayManager,
|
||||
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
|
||||
@NonNull UserManager userManager,
|
||||
@@ -1057,7 +1057,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
* Whether the passed userId has enrolled SFPS.
|
||||
*/
|
||||
public boolean isSfpsEnrolled(int userId) {
|
||||
if (mSidefpsController == null) {
|
||||
if (mSideFpsController == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,20 +51,25 @@ import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieProperty
|
||||
import com.airbnb.lottie.model.KeyPath
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.recents.OverviewProxyService
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import java.io.PrintWriter
|
||||
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.
|
||||
*/
|
||||
@SysUISingleton
|
||||
class SidefpsController @Inject constructor(
|
||||
class SideFpsController
|
||||
@Inject
|
||||
constructor(
|
||||
private val context: Context,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
fingerprintManager: FingerprintManager?,
|
||||
@@ -73,29 +78,34 @@ class SidefpsController @Inject constructor(
|
||||
overviewProxyService: OverviewProxyService,
|
||||
displayManager: DisplayManager,
|
||||
@Main private val mainExecutor: DelayableExecutor,
|
||||
@Main private val handler: Handler
|
||||
) {
|
||||
@VisibleForTesting
|
||||
val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager
|
||||
?.sideFpsSensorProperties
|
||||
?: throw IllegalStateException("no side fingerprint sensor")
|
||||
@Main private val handler: Handler,
|
||||
dumpManager: DumpManager
|
||||
) : Dumpable {
|
||||
val requests: HashSet<SideFpsUiRequestSource> = HashSet()
|
||||
|
||||
@VisibleForTesting
|
||||
val orientationListener = BiometricDisplayListener(
|
||||
context,
|
||||
displayManager,
|
||||
handler,
|
||||
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
|
||||
) { onOrientationChanged() }
|
||||
val sensorProps: FingerprintSensorPropertiesInternal =
|
||||
fingerprintManager?.sideFpsSensorProperties
|
||||
?: throw IllegalStateException("no side fingerprint sensor")
|
||||
|
||||
@VisibleForTesting
|
||||
val overviewProxyListener = object : OverviewProxyService.OverviewProxyListener {
|
||||
override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
|
||||
overlayView?.let { view ->
|
||||
handler.postDelayed({ updateOverlayVisibility(view) }, 500)
|
||||
val orientationListener =
|
||||
BiometricDisplayListener(
|
||||
context,
|
||||
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 =
|
||||
context.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()
|
||||
@@ -121,19 +131,22 @@ class SidefpsController @Inject constructor(
|
||||
@VisibleForTesting
|
||||
internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT
|
||||
|
||||
private val overlayViewParams = WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
|
||||
Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
|
||||
PixelFormat.TRANSLUCENT
|
||||
).apply {
|
||||
title = TAG
|
||||
fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
|
||||
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
|
||||
}
|
||||
private val overlayViewParams =
|
||||
WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
|
||||
Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
|
||||
PixelFormat.TRANSLUCENT
|
||||
)
|
||||
.apply {
|
||||
title = TAG
|
||||
fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
|
||||
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 {
|
||||
fingerprintManager?.setSidefpsController(
|
||||
@@ -141,15 +154,23 @@ class SidefpsController @Inject constructor(
|
||||
override fun show(
|
||||
sensorId: 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)
|
||||
dumpManager.registerDumpable(this)
|
||||
}
|
||||
|
||||
/** Shows the side fps overlay if not already shown. */
|
||||
fun show() {
|
||||
fun show(request: SideFpsUiRequestSource) {
|
||||
requests.add(request)
|
||||
mainExecutor.execute {
|
||||
if (overlayView == null) {
|
||||
createOverlayForDisplay()
|
||||
@@ -160,8 +181,20 @@ class SidefpsController @Inject constructor(
|
||||
}
|
||||
|
||||
/** Hides the fps overlay if shown. */
|
||||
fun hide() {
|
||||
mainExecutor.execute { overlayView = null }
|
||||
fun hide(request: SideFpsUiRequestSource) {
|
||||
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() {
|
||||
@@ -174,12 +207,13 @@ class SidefpsController @Inject constructor(
|
||||
val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
|
||||
overlayView = view
|
||||
val display = context.display!!
|
||||
val offsets = sensorProps.getLocation(display.uniqueId).let { location ->
|
||||
if (location == null) {
|
||||
Log.w(TAG, "No location specified for display: ${display.uniqueId}")
|
||||
val offsets =
|
||||
sensorProps.getLocation(display.uniqueId).let { location ->
|
||||
if (location == null) {
|
||||
Log.w(TAG, "No location specified for display: ${display.uniqueId}")
|
||||
}
|
||||
location ?: sensorProps.location
|
||||
}
|
||||
location ?: sensorProps.location
|
||||
}
|
||||
overlayOffsets = offsets
|
||||
|
||||
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
|
||||
* speaking @string/accessibility_fingerprint_label twice when sensor location indicator
|
||||
* is in focus
|
||||
* speaking @string/accessibility_fingerprint_label twice when sensor location indicator is
|
||||
* in focus
|
||||
*/
|
||||
view.setAccessibilityDelegate(object : AccessibilityDelegate() {
|
||||
override fun dispatchPopulateAccessibilityEvent(
|
||||
host: View,
|
||||
event: AccessibilityEvent
|
||||
): Boolean {
|
||||
return if (event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
||||
true
|
||||
} else {
|
||||
super.dispatchPopulateAccessibilityEvent(host, event)
|
||||
view.setAccessibilityDelegate(
|
||||
object : AccessibilityDelegate() {
|
||||
override fun dispatchPopulateAccessibilityEvent(
|
||||
host: View,
|
||||
event: AccessibilityEvent
|
||||
): Boolean {
|
||||
return if (
|
||||
event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
) {
|
||||
true
|
||||
} else {
|
||||
super.dispatchPopulateAccessibilityEvent(host, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -220,21 +258,22 @@ class SidefpsController @Inject constructor(
|
||||
val displayHeight = if (isNaturalOrientation) size.height() else size.width()
|
||||
val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height()
|
||||
val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width()
|
||||
val sensorBounds = if (overlayOffsets.isYAligned()) {
|
||||
Rect(
|
||||
displayWidth - boundsWidth,
|
||||
overlayOffsets.sensorLocationY,
|
||||
displayWidth,
|
||||
overlayOffsets.sensorLocationY + boundsHeight
|
||||
)
|
||||
} else {
|
||||
Rect(
|
||||
overlayOffsets.sensorLocationX,
|
||||
0,
|
||||
overlayOffsets.sensorLocationX + boundsWidth,
|
||||
boundsHeight
|
||||
)
|
||||
}
|
||||
val sensorBounds =
|
||||
if (overlayOffsets.isYAligned()) {
|
||||
Rect(
|
||||
displayWidth - boundsWidth,
|
||||
overlayOffsets.sensorLocationY,
|
||||
displayWidth,
|
||||
overlayOffsets.sensorLocationY + boundsHeight
|
||||
)
|
||||
} else {
|
||||
Rect(
|
||||
overlayOffsets.sensorLocationX,
|
||||
0,
|
||||
overlayOffsets.sensorLocationX + boundsWidth,
|
||||
boundsHeight
|
||||
)
|
||||
}
|
||||
|
||||
RotationUtils.rotateBounds(
|
||||
sensorBounds,
|
||||
@@ -254,19 +293,25 @@ class SidefpsController @Inject constructor(
|
||||
// hide after a few seconds if the sensor is oriented down and there are
|
||||
// large overlapping system bars
|
||||
val rotation = context.display?.rotation
|
||||
if (windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
|
||||
((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
|
||||
(rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))) {
|
||||
overlayHideAnimator = view.animate()
|
||||
.alpha(0f)
|
||||
.setStartDelay(3_000)
|
||||
.setDuration(animationDuration)
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
view.visibility = View.GONE
|
||||
overlayHideAnimator = null
|
||||
}
|
||||
})
|
||||
if (
|
||||
windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
|
||||
((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
|
||||
(rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))
|
||||
) {
|
||||
overlayHideAnimator =
|
||||
view
|
||||
.animate()
|
||||
.alpha(0f)
|
||||
.setStartDelay(3_000)
|
||||
.setDuration(animationDuration)
|
||||
.setListener(
|
||||
object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
view.visibility = View.GONE
|
||||
overlayHideAnimator = null
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
overlayHideAnimator?.cancel()
|
||||
overlayHideAnimator = null
|
||||
@@ -283,32 +328,36 @@ private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorProper
|
||||
fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
|
||||
|
||||
@BiometricOverlayConstants.ShowReason
|
||||
private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) {
|
||||
REASON_AUTH_KEYGUARD -> false
|
||||
REASON_AUTH_SETTINGS -> when (activityTaskManager.topClass()) {
|
||||
// TODO(b/186176653): exclude fingerprint overlays from this list view
|
||||
"com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
|
||||
private fun Int.isReasonToAutoShow(activityTaskManager: ActivityTaskManager): Boolean =
|
||||
when (this) {
|
||||
REASON_AUTH_KEYGUARD -> false
|
||||
REASON_AUTH_SETTINGS ->
|
||||
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
|
||||
}
|
||||
|
||||
private fun ActivityTaskManager.topClass(): String =
|
||||
getTasks(1).firstOrNull()?.topActivity?.className ?: ""
|
||||
|
||||
@RawRes
|
||||
private fun Display.asSideFpsAnimation(yAligned: Boolean): Int = when (rotation) {
|
||||
Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
|
||||
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.asSideFpsAnimation(yAligned: Boolean): Int =
|
||||
when (rotation) {
|
||||
Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
|
||||
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) {
|
||||
Surface.ROTATION_90 -> if (yAligned) 0f else 180f
|
||||
Surface.ROTATION_180 -> 180f
|
||||
Surface.ROTATION_270 -> if (yAligned) 180f else 0f
|
||||
else -> 0f
|
||||
}
|
||||
private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float =
|
||||
when (rotation) {
|
||||
Surface.ROTATION_90 -> if (yAligned) 0f else 180f
|
||||
Surface.ROTATION_180 -> 180f
|
||||
Surface.ROTATION_270 -> if (yAligned) 180f else 0f
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0
|
||||
|
||||
@@ -322,10 +371,9 @@ private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
|
||||
fun update() {
|
||||
val c = context.getColor(R.color.biometric_dialog_accent)
|
||||
for (key in listOf(".blue600", ".blue400")) {
|
||||
addValueCallback(
|
||||
KeyPath(key, "**"),
|
||||
LottieProperty.COLOR_FILTER
|
||||
) { PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) }
|
||||
addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
|
||||
PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,3 +383,15 @@ private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
|
||||
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,
|
||||
}
|
||||
@@ -54,7 +54,8 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
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.FalsingCollector;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
@@ -141,7 +142,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private KeyguardViewController mKeyguardViewController;
|
||||
@Mock
|
||||
private SidefpsController mSidefpsController;
|
||||
private SideFpsController mSideFpsController;
|
||||
@Mock
|
||||
private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
|
||||
@Mock
|
||||
@@ -189,7 +190,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
|
||||
mConfigurationController, mFalsingCollector, mFalsingManager,
|
||||
mUserSwitcherController, mFeatureFlags, mGlobalSettings,
|
||||
mSessionTracker, Optional.of(mSidefpsController), mFalsingA11yDelegate).create(
|
||||
mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create(
|
||||
mSecurityCallback);
|
||||
}
|
||||
|
||||
@@ -345,48 +346,48 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
|
||||
verify(mSidefpsController).show();
|
||||
verify(mSidefpsController, never()).hide();
|
||||
verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).hide(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
setFingerprintDetectionRunning(false);
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
setSideFpsHintEnabledFromResources(false);
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() {
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
setNeedsStrongAuth(true);
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -394,13 +395,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupGetSecurityView();
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
verify(mSidefpsController, atLeastOnce()).show();
|
||||
reset(mSidefpsController);
|
||||
verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -408,13 +409,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupGetSecurityView();
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
verify(mSidefpsController, atLeastOnce()).show();
|
||||
reset(mSidefpsController);
|
||||
verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onStartingToHide();
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -422,13 +423,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupGetSecurityView();
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
verify(mSidefpsController, atLeastOnce()).show();
|
||||
reset(mSidefpsController);
|
||||
verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onPause();
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -436,12 +437,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupGetSecurityView();
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onResume(0);
|
||||
|
||||
verify(mSidefpsController).show();
|
||||
verify(mSidefpsController, never()).hide();
|
||||
verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).hide(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -450,12 +451,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupConditionsToEnableSideFpsHint();
|
||||
setSideFpsHintEnabledFromResources(false);
|
||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||
reset(mSidefpsController);
|
||||
reset(mSideFpsController);
|
||||
|
||||
mKeyguardSecurityContainerController.onResume(0);
|
||||
|
||||
verify(mSidefpsController).hide();
|
||||
verify(mSidefpsController, never()).show();
|
||||
verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||
verify(mSideFpsController, never()).show(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -145,7 +145,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private UdfpsController mUdfpsController;
|
||||
@Mock
|
||||
private SidefpsController mSidefpsController;
|
||||
private SideFpsController mSideFpsController;
|
||||
@Mock
|
||||
private DisplayManager mDisplayManager;
|
||||
@Mock
|
||||
@@ -225,7 +225,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
|
||||
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
|
||||
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
|
||||
() -> mUdfpsController, () -> mSidefpsController, mStatusBarStateController,
|
||||
() -> mUdfpsController, () -> mSideFpsController, mStatusBarStateController,
|
||||
mVibratorHelper);
|
||||
|
||||
mAuthController.start();
|
||||
@@ -256,7 +256,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
// This test requires an uninitialized AuthController.
|
||||
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
|
||||
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
|
||||
mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
|
||||
mFaceManager, () -> mUdfpsController, () -> mSideFpsController,
|
||||
mStatusBarStateController, mVibratorHelper);
|
||||
authController.start();
|
||||
|
||||
@@ -282,7 +282,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
// This test requires an uninitialized AuthController.
|
||||
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
|
||||
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
|
||||
mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
|
||||
mFaceManager, () -> mUdfpsController, () -> mSideFpsController,
|
||||
mStatusBarStateController, mVibratorHelper);
|
||||
authController.start();
|
||||
|
||||
@@ -936,7 +936,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
FingerprintManager fingerprintManager,
|
||||
FaceManager faceManager,
|
||||
Provider<UdfpsController> udfpsControllerFactory,
|
||||
Provider<SidefpsController> sidefpsControllerFactory,
|
||||
Provider<SideFpsController> sidefpsControllerFactory,
|
||||
StatusBarStateController statusBarStateController,
|
||||
VibratorHelper vibratorHelper) {
|
||||
super(context, execution, commandQueue, activityTaskManager, windowManager,
|
||||
|
||||
@@ -52,6 +52,7 @@ import androidx.test.filters.SmallTest
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.recents.OverviewProxyService
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
@@ -82,37 +83,31 @@ private const val SENSOR_ID = 1
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class SidefpsControllerTest : SysuiTestCase() {
|
||||
class SideFpsControllerTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule
|
||||
var rule = MockitoJUnit.rule()
|
||||
@JvmField @Rule var rule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
lateinit var layoutInflater: LayoutInflater
|
||||
@Mock
|
||||
lateinit var fingerprintManager: FingerprintManager
|
||||
@Mock
|
||||
lateinit var windowManager: WindowManager
|
||||
@Mock
|
||||
lateinit var activityTaskManager: ActivityTaskManager
|
||||
@Mock
|
||||
lateinit var sidefpsView: View
|
||||
@Mock
|
||||
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>
|
||||
@Mock lateinit var layoutInflater: LayoutInflater
|
||||
@Mock lateinit var fingerprintManager: FingerprintManager
|
||||
@Mock lateinit var windowManager: WindowManager
|
||||
@Mock lateinit var activityTaskManager: ActivityTaskManager
|
||||
@Mock lateinit var sideFpsView: View
|
||||
@Mock lateinit var displayManager: DisplayManager
|
||||
@Mock lateinit var overviewProxyService: OverviewProxyService
|
||||
@Mock lateinit var handler: Handler
|
||||
@Mock lateinit var dumpManager: DumpManager
|
||||
@Captor lateinit var overlayCaptor: ArgumentCaptor<View>
|
||||
@Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
|
||||
|
||||
private val executor = FakeExecutor(FakeSystemClock())
|
||||
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 indicatorBounds: Rect
|
||||
@@ -128,17 +123,18 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
context.addMockSystemService(DisplayManager::class.java, displayManager)
|
||||
context.addMockSystemService(WindowManager::class.java, windowManager)
|
||||
|
||||
whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView)
|
||||
whenEver(sidefpsView.findViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
|
||||
whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
|
||||
whenEver(sideFpsView.findViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
|
||||
.thenReturn(mock(LottieAnimationView::class.java))
|
||||
with(mock(ViewPropertyAnimator::class.java)) {
|
||||
whenEver(sidefpsView.animate()).thenReturn(this)
|
||||
whenEver(sideFpsView.animate()).thenReturn(this)
|
||||
whenEver(alpha(anyFloat())).thenReturn(this)
|
||||
whenEver(setStartDelay(anyLong())).thenReturn(this)
|
||||
whenEver(setDuration(anyLong())).thenReturn(this)
|
||||
whenEver(setListener(any())).thenAnswer {
|
||||
(it.arguments[0] as Animator.AnimatorListener)
|
||||
.onAnimationEnd(mock(Animator::class.java))
|
||||
(it.arguments[0] as Animator.AnimatorListener).onAnimationEnd(
|
||||
mock(Animator::class.java)
|
||||
)
|
||||
this
|
||||
}
|
||||
}
|
||||
@@ -179,20 +175,21 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
displayBounds = Rect(0, 0, displayWidth, displayHeight)
|
||||
var locations = listOf(sensorLocation)
|
||||
|
||||
whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
SENSOR_ID,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
listOf() /* componentInfo */,
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
true /* halControlsIllumination */,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */,
|
||||
locations
|
||||
whenEver(fingerprintManager.sensorPropertiesInternal)
|
||||
.thenReturn(
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
SENSOR_ID,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
listOf() /* componentInfo */,
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
true /* halControlsIllumination */,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */,
|
||||
locations
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val displayInfo = DisplayInfo()
|
||||
displayInfo.initInfo()
|
||||
@@ -200,22 +197,29 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
|
||||
whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
|
||||
whenEver(windowManager.defaultDisplay).thenReturn(display)
|
||||
whenEver(windowManager.maximumWindowMetrics).thenReturn(
|
||||
WindowMetrics(displayBounds, WindowInsets.CONSUMED)
|
||||
)
|
||||
whenEver(windowManager.currentWindowMetrics).thenReturn(
|
||||
WindowMetrics(displayBounds, windowInsets)
|
||||
)
|
||||
whenEver(windowManager.maximumWindowMetrics)
|
||||
.thenReturn(WindowMetrics(displayBounds, WindowInsets.CONSUMED))
|
||||
whenEver(windowManager.currentWindowMetrics)
|
||||
.thenReturn(WindowMetrics(displayBounds, windowInsets))
|
||||
|
||||
sideFpsController = SidefpsController(
|
||||
context.createDisplayContext(display), layoutInflater, fingerprintManager,
|
||||
windowManager, activityTaskManager, overviewProxyService, displayManager, executor,
|
||||
handler
|
||||
)
|
||||
sideFpsController =
|
||||
SideFpsController(
|
||||
context.createDisplayContext(display),
|
||||
layoutInflater,
|
||||
fingerprintManager,
|
||||
windowManager,
|
||||
activityTaskManager,
|
||||
overviewProxyService,
|
||||
displayManager,
|
||||
executor,
|
||||
handler,
|
||||
dumpManager
|
||||
)
|
||||
|
||||
overlayController = ArgumentCaptor.forClass(ISidefpsController::class.java).apply {
|
||||
verify(fingerprintManager).setSidefpsController(capture())
|
||||
}.value
|
||||
overlayController =
|
||||
ArgumentCaptor.forClass(ISidefpsController::class.java)
|
||||
.apply { verify(fingerprintManager).setSidefpsController(capture()) }
|
||||
.value
|
||||
|
||||
block()
|
||||
}
|
||||
@@ -272,10 +276,7 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
verify(windowManager).removeView(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIgnoredForKeyguard() = testWithDisplay {
|
||||
testIgnoredFor(REASON_AUTH_KEYGUARD)
|
||||
}
|
||||
@Test fun testIgnoredForKeyguard() = testWithDisplay { testIgnoredFor(REASON_AUTH_KEYGUARD) }
|
||||
|
||||
@Test
|
||||
fun testShowsForMostSettings() = testWithDisplay {
|
||||
@@ -297,88 +298,76 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbar() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_0 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbar() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_0 }) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbarOnY() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_0 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbarOnY() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_0 }
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbar90() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_90 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbar90() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_90 }) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbar90OnY() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_90 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbar90OnY() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_90 }
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbar180() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_180 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbar180() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_180 }
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbar270OnY() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_270 }
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbar270OnY() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_270 }
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbarCollapsedDown() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_270 },
|
||||
windowInsets = insetsForSmallNavbar()
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbarCollapsedDown() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_270 },
|
||||
windowInsets = insetsForSmallNavbar()
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun showsWithTaskbarCollapsedDownOnY() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_180 },
|
||||
windowInsets = insetsForSmallNavbar()
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun showsWithTaskbarCollapsedDownOnY() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_180 },
|
||||
windowInsets = insetsForSmallNavbar()
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
@Test
|
||||
fun hidesWithTaskbarDown() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_180 },
|
||||
windowInsets = insetsForLargeNavbar()
|
||||
) {
|
||||
hidesWithTaskbar(visible = false)
|
||||
}
|
||||
fun hidesWithTaskbarDown() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED,
|
||||
{ rotation = Surface.ROTATION_180 },
|
||||
windowInsets = insetsForLargeNavbar()
|
||||
) { hidesWithTaskbar(visible = false) }
|
||||
|
||||
@Test
|
||||
fun hidesWithTaskbarDownOnY() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_270 },
|
||||
windowInsets = insetsForLargeNavbar()
|
||||
) {
|
||||
hidesWithTaskbar(visible = true)
|
||||
}
|
||||
fun hidesWithTaskbarDownOnY() =
|
||||
testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
|
||||
{ rotation = Surface.ROTATION_270 },
|
||||
windowInsets = insetsForLargeNavbar()
|
||||
) { hidesWithTaskbar(visible = true) }
|
||||
|
||||
private fun hidesWithTaskbar(visible: Boolean) {
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
@@ -389,43 +378,35 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
|
||||
verify(windowManager).addView(any(), 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
|
||||
fun testIndicatorPlacementForXAlignedSensor() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.X_ALIGNED
|
||||
) {
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(
|
||||
windowManager.defaultDisplay,
|
||||
indicatorBounds
|
||||
)
|
||||
executor.runAllReady()
|
||||
fun testIndicatorPlacementForXAlignedSensor() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED) {
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(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.y).isEqualTo(0)
|
||||
}
|
||||
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
|
||||
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIndicatorPlacementForYAlignedSensor() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED
|
||||
) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(
|
||||
windowManager.defaultDisplay,
|
||||
indicatorBounds
|
||||
)
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
executor.runAllReady()
|
||||
fun testIndicatorPlacementForYAlignedSensor() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
executor.runAllReady()
|
||||
|
||||
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
|
||||
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
|
||||
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
|
||||
}
|
||||
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
|
||||
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
|
||||
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
|
||||
@@ -442,52 +423,50 @@ class SidefpsControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLayoutParams_hasNoMoveAnimationWindowFlag() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED
|
||||
) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(
|
||||
windowManager.defaultDisplay,
|
||||
indicatorBounds
|
||||
)
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
executor.runAllReady()
|
||||
fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, 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
|
||||
fun testLayoutParams_hasTrustedOverlayWindowFlag() = testWithDisplay(
|
||||
deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED
|
||||
) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(
|
||||
windowManager.defaultDisplay,
|
||||
indicatorBounds
|
||||
)
|
||||
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
|
||||
executor.runAllReady()
|
||||
fun testLayoutParams_hasTrustedOverlayWindowFlag() =
|
||||
testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
|
||||
sideFpsController.overlayOffsets = sensorLocation
|
||||
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, 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 insetsForLargeNavbar() = insetsWithBottom(100)
|
||||
private fun insetsWithBottom(bottom: Int) = WindowInsets.Builder()
|
||||
.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom))
|
||||
.build()
|
||||
|
||||
private fun insetsWithBottom(bottom: Int) =
|
||||
WindowInsets.Builder()
|
||||
.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom))
|
||||
.build()
|
||||
|
||||
private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling")
|
||||
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user