Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9935dae6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents dc72403d 11674494
Loading
Loading
Loading
Loading
+10 −9
Original line number Original line Diff line number Diff line
@@ -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;
+5 −5
Original line number Original line Diff line number Diff line
@@ -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();
        }
        }
+5 −5
Original line number Original line Diff line number Diff line
@@ -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;
        }
        }


+164 −104
Original line number Original line Diff line number Diff line
@@ -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,15 +78,19 @@ 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
) : Dumpable {
    val requests: HashSet<SideFpsUiRequestSource> = HashSet()

    @VisibleForTesting
    @VisibleForTesting
    val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager
    val sensorProps: FingerprintSensorPropertiesInternal =
        ?.sideFpsSensorProperties
        fingerprintManager?.sideFpsSensorProperties
            ?: throw IllegalStateException("no side fingerprint sensor")
            ?: throw IllegalStateException("no side fingerprint sensor")


    @VisibleForTesting
    @VisibleForTesting
    val orientationListener = BiometricDisplayListener(
    val orientationListener =
        BiometricDisplayListener(
            context,
            context,
            displayManager,
            displayManager,
            handler,
            handler,
@@ -89,7 +98,8 @@ class SidefpsController @Inject constructor(
        ) { onOrientationChanged() }
        ) { onOrientationChanged() }


    @VisibleForTesting
    @VisibleForTesting
    val overviewProxyListener = object : OverviewProxyService.OverviewProxyListener {
    val overviewProxyListener =
        object : OverviewProxyService.OverviewProxyListener {
            override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
            override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
                overlayView?.let { view ->
                overlayView?.let { view ->
                    handler.postDelayed({ updateOverlayVisibility(view) }, 500)
                    handler.postDelayed({ updateOverlayVisibility(view) }, 500)
@@ -121,17 +131,20 @@ 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(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
                WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
                Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
                Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
                PixelFormat.TRANSLUCENT
                PixelFormat.TRANSLUCENT
    ).apply {
            )
            .apply {
                title = TAG
                title = TAG
                fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
                fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
                gravity = Gravity.TOP or Gravity.LEFT
                gravity = Gravity.TOP or Gravity.LEFT
        layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
                layoutInDisplayCutoutMode =
                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
                privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
                privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
            }
            }


@@ -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,7 +207,8 @@ 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 =
            sensorProps.getLocation(display.uniqueId).let { location ->
                if (location == null) {
                if (location == null) {
                    Log.w(TAG, "No location specified for display: ${display.uniqueId}")
                    Log.w(TAG, "No location specified for display: ${display.uniqueId}")
                }
                }
@@ -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(
            object : AccessibilityDelegate() {
                override fun dispatchPopulateAccessibilityEvent(
                override fun dispatchPopulateAccessibilityEvent(
                    host: View,
                    host: View,
                    event: AccessibilityEvent
                    event: AccessibilityEvent
                ): Boolean {
                ): Boolean {
                return if (event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                    return if (
                        event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                    ) {
                        true
                        true
                    } else {
                    } else {
                        super.dispatchPopulateAccessibilityEvent(host, event)
                        super.dispatchPopulateAccessibilityEvent(host, event)
                    }
                    }
                }
                }
        })
            }
        )
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -220,7 +258,8 @@ 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 =
            if (overlayOffsets.isYAligned()) {
                Rect(
                Rect(
                    displayWidth - boundsWidth,
                    displayWidth - boundsWidth,
                    overlayOffsets.sensorLocationY,
                    overlayOffsets.sensorLocationY,
@@ -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 (
            windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
                ((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
                ((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
                    (rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))) {
                    (rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))
            overlayHideAnimator = view.animate()
        ) {
            overlayHideAnimator =
                view
                    .animate()
                    .alpha(0f)
                    .alpha(0f)
                    .setStartDelay(3_000)
                    .setStartDelay(3_000)
                    .setDuration(animationDuration)
                    .setDuration(animationDuration)
                .setListener(object : AnimatorListenerAdapter() {
                    .setListener(
                        object : AnimatorListenerAdapter() {
                            override fun onAnimationEnd(animation: Animator) {
                            override fun onAnimationEnd(animation: Animator) {
                                view.visibility = View.GONE
                                view.visibility = View.GONE
                                overlayHideAnimator = null
                                overlayHideAnimator = null
                            }
                            }
                })
                        }
                    )
        } else {
        } else {
            overlayHideAnimator?.cancel()
            overlayHideAnimator?.cancel()
            overlayHideAnimator = null
            overlayHideAnimator = null
@@ -283,9 +328,11 @@ 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 =
    when (this) {
        REASON_AUTH_KEYGUARD -> false
        REASON_AUTH_KEYGUARD -> false
    REASON_AUTH_SETTINGS -> when (activityTaskManager.topClass()) {
        REASON_AUTH_SETTINGS ->
            when (activityTaskManager.topClass()) {
                // TODO(b/186176653): exclude fingerprint overlays from this list view
                // TODO(b/186176653): exclude fingerprint overlays from this list view
                "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
                "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
                else -> true
                else -> true
@@ -297,13 +344,15 @@ 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 =
    when (rotation) {
        Surface.ROTATION_0 -> 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
        Surface.ROTATION_180 -> 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
        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 =
    when (rotation) {
        Surface.ROTATION_90 -> if (yAligned) 0f else 180f
        Surface.ROTATION_90 -> if (yAligned) 0f else 180f
        Surface.ROTATION_180 -> 180f
        Surface.ROTATION_180 -> 180f
        Surface.ROTATION_270 -> if (yAligned) 180f else 0f
        Surface.ROTATION_270 -> if (yAligned) 180f else 0f
@@ -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,
}
+34 −33
Original line number Original line Diff line number Diff line
@@ -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
Loading