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

Commit d79387b5 authored by Joe Bolinger's avatar Joe Bolinger Committed by Android (Google) Code Review
Browse files

Merge changes from topic "udfps-light"

* changes:
  Instrument UDFPS touch affordance CUJ.
  Split UdfpsController and backfill tests.
  Migrate small UDFPS classes to kotlin and backfill missing tests.
parents 0398f0d5 b1c14109
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -127,6 +127,11 @@ public class LatencyTracker {
     */
    public static final int ACTION_SWITCH_DISPLAY_UNFOLD = 13;

    /**
     * Time it takes for a UDFPS sensor to appear ready after it is touched.
     */
    public static final int ACTION_UDFPS_ILLUMINATE = 14;

    private static final int[] ACTIONS_ALL = {
        ACTION_EXPAND_PANEL,
        ACTION_TOGGLE_RECENTS,
@@ -141,7 +146,8 @@ public class LatencyTracker {
        ACTION_ROTATE_SCREEN_CAMERA_CHECK,
        ACTION_LOCKSCREEN_UNLOCK,
        ACTION_USER_SWITCH,
        ACTION_SWITCH_DISPLAY_UNFOLD
        ACTION_SWITCH_DISPLAY_UNFOLD,
        ACTION_UDFPS_ILLUMINATE
    };

    /** @hide */
@@ -159,7 +165,8 @@ public class LatencyTracker {
        ACTION_ROTATE_SCREEN_CAMERA_CHECK,
        ACTION_LOCKSCREEN_UNLOCK,
        ACTION_USER_SWITCH,
        ACTION_SWITCH_DISPLAY_UNFOLD
        ACTION_SWITCH_DISPLAY_UNFOLD,
        ACTION_UDFPS_ILLUMINATE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Action {
@@ -179,7 +186,8 @@ public class LatencyTracker {
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE
    };

    private static LatencyTracker sLatencyTracker;
@@ -267,6 +275,8 @@ public class LatencyTracker {
                return "ACTION_USER_SWITCH";
            case 14:
                return "ACTION_SWITCH_DISPLAY_UNFOLD";
            case 15:
                return "ACTION_UDFPS_ILLUMINATE";
            default:
                throw new IllegalArgumentException("Invalid action");
        }
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import android.widget.FrameLayout;
 * - sends sensor rect updates to fingerprint drawable
 * - optionally can override dozeTimeTick to adjust views for burn-in mitigation
 */
abstract class UdfpsAnimationView extends FrameLayout {
public abstract class UdfpsAnimationView extends FrameLayout {
    // mAlpha takes into consideration the status bar expansion amount to fade out icon when
    // the status bar is expanded
    private int mAlpha;
+170 −0
Original line number Diff line number Diff line
@@ -13,23 +13,19 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.biometrics;

import android.annotation.NonNull;
import android.graphics.PointF;
import android.graphics.RectF;

import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.util.ViewController;

import java.io.FileDescriptor;
import java.io.PrintWriter;
package com.android.systemui.biometrics

import android.graphics.PointF
import android.graphics.RectF
import com.android.systemui.Dumpable
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
import com.android.systemui.util.ViewController
import java.io.FileDescriptor
import java.io.PrintWriter

/**
 * Handles:
@@ -41,162 +37,134 @@ import java.io.PrintWriter;
 * - sensor position changes
 * - doze time event
 */
abstract class UdfpsAnimationViewController<T extends UdfpsAnimationView>
        extends ViewController<T> implements Dumpable {
    @NonNull final StatusBarStateController mStatusBarStateController;
    @NonNull final PanelExpansionStateManager mPanelExpansionStateManager;
    @NonNull final SystemUIDialogManager mDialogManager;
    @NonNull final DumpManager mDumpManger;

    boolean mNotificationShadeVisible;

    protected UdfpsAnimationViewController(
            T view,
            @NonNull StatusBarStateController statusBarStateController,
            @NonNull PanelExpansionStateManager panelExpansionStateManager,
            @NonNull SystemUIDialogManager dialogManager,
            @NonNull DumpManager dumpManager) {
        super(view);
        mStatusBarStateController = statusBarStateController;
        mPanelExpansionStateManager = panelExpansionStateManager;
        mDialogManager = dialogManager;
        mDumpManger = dumpManager;
    }
abstract class UdfpsAnimationViewController<T : UdfpsAnimationView>(
    view: T,
    protected val statusBarStateController: StatusBarStateController,
    protected val panelExpansionStateManager: PanelExpansionStateManager,
    protected val dialogManager: SystemUIDialogManager,
    private val dumpManager: DumpManager
) : ViewController<T>(view), Dumpable {

    abstract @NonNull String getTag();
    protected abstract val tag: String

    @Override
    protected void onViewAttached() {
        mPanelExpansionStateManager.addExpansionListener(mPanelExpansionListener);
        mDialogManager.registerListener(mDialogListener);
        mDumpManger.registerDumpable(getDumpTag(), this);
    }
    private val view: T
        get() = mView!!

    private val dialogListener = SystemUIDialogManager.Listener { updatePauseAuth() }

    @Override
    protected void onViewDetached() {
        mPanelExpansionStateManager.removeExpansionListener(mPanelExpansionListener);
        mDialogManager.unregisterListener(mDialogListener);
        mDumpManger.unregisterDumpable(getDumpTag());
    private val panelExpansionListener =
        PanelExpansionListener { fraction, expanded, tracking ->
            // Notification shade can be expanded but not visible (fraction: 0.0), for example
            // when a heads-up notification (HUN) is showing.
            notificationShadeVisible = expanded && fraction > 0f
            view.onExpansionChanged(fraction)
            updatePauseAuth()
        }

    /** If the notification shade is visible. */
    var notificationShadeVisible: Boolean = false

    /**
     * in some cases, onViewAttached is called for the newly added view using an instance of
     * this controller before onViewDetached is called on the previous view, so we must have a
     * unique dump tag per instance of this class
     * @return a unique tag for this instance of this class
     * The amount of translation needed if the view currently requires the user to touch
     * somewhere other than the exact center of the sensor. For example, this can happen
     * during guided enrollment.
     */
    private String getDumpTag() {
        return getTag() + " (" + this + ")";
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("mNotificationShadeVisible=" + mNotificationShadeVisible);
        pw.println("shouldPauseAuth()=" + shouldPauseAuth());
        pw.println("isPauseAuth=" + mView.isPauseAuth());
    }
    open val touchTranslation: PointF = PointF(0f, 0f)

    /**
     * Returns true if the fingerprint manager is running but we want to temporarily pause
     * authentication.
     * X-Padding to add to left and right of the sensor rectangle area to increase the size of our
     * window to draw within.
     */
    boolean shouldPauseAuth() {
        return mNotificationShadeVisible
                || mDialogManager.shouldHideAffordance();
    }
    open val paddingX: Int = 0

    /**
     * Send pause auth update to our view.
     * Y-Padding to add to top and bottom of the sensor rectangle area to increase the size of our
     * window to draw within.
     */
    void updatePauseAuth() {
        if (mView.setPauseAuth(shouldPauseAuth())) {
            mView.postInvalidate();
    open val paddingY: Int = 0

    override fun onViewAttached() {
        panelExpansionStateManager.addExpansionListener(panelExpansionListener)
        dialogManager.registerListener(dialogListener)
        dumpManager.registerDumpable(dumpTag, this)
    }

    override fun onViewDetached() {
        panelExpansionStateManager.removeExpansionListener(panelExpansionListener)
        dialogManager.unregisterListener(dialogListener)
        dumpManager.unregisterDumpable(dumpTag)
    }

    /**
     * Send sensor position change to our view. This rect contains paddingX and paddingY.
     * in some cases, onViewAttached is called for the newly added view using an instance of
     * this controller before onViewDetached is called on the previous view, so we must have a
     * unique [dumpTag] per instance of this class.
     */
    void onSensorRectUpdated(RectF sensorRect) {
        mView.onSensorRectUpdated(sensorRect);
    private val dumpTag = "$tag ($this)"

    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
        pw.println("mNotificationShadeVisible=$notificationShadeVisible")
        pw.println("shouldPauseAuth()=" + shouldPauseAuth())
        pw.println("isPauseAuth=" + view.isPauseAuth)
    }

    /**
     * Send dozeTimeTick to view in case it wants to handle its burn-in offset.
     * Returns true if the fingerprint manager is running, but we want to temporarily pause
     * authentication.
     */
    void dozeTimeTick() {
        if (mView.dozeTimeTick()) {
            mView.postInvalidate();
        }
    open fun shouldPauseAuth(): Boolean {
        return notificationShadeVisible || dialogManager.shouldHideAffordance()
    }

    /**
     * @return the amount of translation needed if the view currently requires the user to touch
     *         somewhere other than the exact center of the sensor. For example, this can happen
     *         during guided enrollment.
     * Send pause auth update to our view.
     */
    PointF getTouchTranslation() {
        return new PointF(0, 0);
    fun updatePauseAuth() {
        if (view.setPauseAuth(shouldPauseAuth())) {
            view.postInvalidate()
        }
    }

    /**
     * X-Padding to add to left and right of the sensor rectangle area to increase the size of our
     * window to draw within.
     * @return
     * Send sensor position change to our view. This rect contains paddingX and paddingY.
     */
    int getPaddingX() {
        return 0;
    fun onSensorRectUpdated(sensorRect: RectF) {
        view.onSensorRectUpdated(sensorRect)
    }

    /**
     * Y-Padding to add to top and bottom of the sensor rectangle area to increase the size of our
     * window to draw within.
     * Send dozeTimeTick to view in case it wants to handle its burn-in offset.
     */
    int getPaddingY() {
        return 0;
    fun dozeTimeTick() {
        if (view.dozeTimeTick()) {
            view.postInvalidate()
        }
    }

    /**
     * Udfps has started illuminating and the fingerprint manager is working on authenticating.
     */
    void onIlluminationStarting() {
        mView.onIlluminationStarting();
        mView.postInvalidate();
    fun onIlluminationStarting() {
        view.onIlluminationStarting()
        view.postInvalidate()
    }

    /**
     * Udfps has stopped illuminating and the fingerprint manager is no longer attempting to
     * authenticate.
     */
    void onIlluminationStopped() {
        mView.onIlluminationStopped();
        mView.postInvalidate();
    fun onIlluminationStopped() {
        view.onIlluminationStopped()
        view.postInvalidate()
    }

    /**
     * Whether to listen for touches outside of the view.
     */
    boolean listenForTouchesOutsideView() {
        return false;
    }
    open fun listenForTouchesOutsideView(): Boolean = false

    /**
     * Called on touches outside of the view if listenForTouchesOutsideView returns true
     */
    void onTouchOutsideView() { }

    private final PanelExpansionListener mPanelExpansionListener = new PanelExpansionListener() {
        @Override
        public void onPanelExpansionChanged(
                float fraction, boolean expanded, boolean tracking) {
            // Notification shade can be expanded but not visible (fraction: 0.0), for example
            // when a heads-up notification (HUN) is showing.
            mNotificationShadeVisible = expanded && fraction > 0f;
            mView.onExpansionChanged(fraction);
            updatePauseAuth();
        }
    };

    private final SystemUIDialogManager.Listener mDialogListener =
            (shouldHide) -> updatePauseAuth();
    open fun onTouchOutsideView() {}
}
 No newline at end of file
+8 −18
Original line number Diff line number Diff line
@@ -13,33 +13,23 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.biometrics

package com.android.systemui.biometrics;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.Nullable;
import android.content.Context
import android.util.AttributeSet

/**
 * Class that coordinates non-HBM animations during BiometricPrompt.
 *
 * Currently doesn't draw anything.
 *
 * Note that {@link AuthBiometricUdfpsView} also shows UDFPS animations. At some point we should
 * Note that [AuthBiometricUdfpsView] also shows UDFPS animations. At some point we should
 * de-dupe this if necessary.
 */
public class UdfpsBpView extends UdfpsAnimationView {
    private UdfpsFpDrawable mFingerprintDrawable;
class UdfpsBpView(context: Context, attrs: AttributeSet?) : UdfpsAnimationView(context, attrs) {

    public UdfpsBpView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    // Drawable isn't ever added to the view, so we don't currently show anything
        mFingerprintDrawable = new UdfpsFpDrawable(mContext);
    }
    private val fingerprintDrawable: UdfpsFpDrawable = UdfpsFpDrawable(context)

    @Override
    UdfpsDrawable getDrawable() {
        return mFingerprintDrawable;
    }
    override fun getDrawable(): UdfpsDrawable = fingerprintDrawable
}
+19 −23
Original line number Diff line number Diff line
@@ -13,32 +13,28 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.biometrics

package com.android.systemui.biometrics;

import android.annotation.NonNull;

import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager

/**
 * Class that coordinates non-HBM animations for biometric prompt.
 */
class UdfpsBpViewController extends UdfpsAnimationViewController<UdfpsBpView> {
    protected UdfpsBpViewController(
            @NonNull UdfpsBpView view,
            @NonNull StatusBarStateController statusBarStateController,
            @NonNull PanelExpansionStateManager panelExpansionStateManager,
            @NonNull SystemUIDialogManager systemUIDialogManager,
            @NonNull DumpManager dumpManager) {
        super(view, statusBarStateController, panelExpansionStateManager,
                systemUIDialogManager, dumpManager);
    }

    @Override
    @NonNull String getTag() {
        return "UdfpsBpViewController";
    }
class UdfpsBpViewController(
    view: UdfpsBpView,
    statusBarStateController: StatusBarStateController,
    panelExpansionStateManager: PanelExpansionStateManager,
    systemUIDialogManager: SystemUIDialogManager,
    dumpManager: DumpManager
) : UdfpsAnimationViewController<UdfpsBpView>(
    view,
    statusBarStateController,
    panelExpansionStateManager,
    systemUIDialogManager,
    dumpManager
) {
    override val tag = "UdfpsBpViewController"
}
Loading