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

Commit 968d1b03 authored by lbill's avatar lbill
Browse files

Instrument CUJ_BIOMETRIC_PROMPT with InteractionJankMonitor

Monitor below animations
- AuthContainerView transit in  : SHOW
- AuthContainerView transit out : DISMISS
- AuthCredentialView transit in : SHOW
- AuthCredentialView transit out: DISMISS
- AuthBiometricView transit(Biometric <-> PIN/Password/Pattern): TRANSIT
  (Only add jankListener when not null)

If view do not attached to window, skip tracing.

Bug: 232176881
Test: atest SystemUITests
Test: make and get perfetto trace
Change-Id: I17fb2b5e00005c611efe2342abc30196ae4ccc31
parent 6280ea5e
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -166,6 +166,8 @@ public abstract class AuthBiometricView extends LinearLayout {
    private final Runnable mResetErrorRunnable;
    private final Runnable mResetErrorRunnable;
    private final Runnable mResetHelpRunnable;
    private final Runnable mResetHelpRunnable;


    private Animator.AnimatorListener mJankListener;

    private final OnClickListener mBackgroundClickListener = (view) -> {
    private final OnClickListener mBackgroundClickListener = (view) -> {
        if (mState == STATE_AUTHENTICATED) {
        if (mState == STATE_AUTHENTICATED) {
            Log.w(TAG, "Ignoring background click after authenticated");
            Log.w(TAG, "Ignoring background click after authenticated");
@@ -282,6 +284,10 @@ public abstract class AuthBiometricView extends LinearLayout {
        mRequireConfirmation = requireConfirmation && supportsRequireConfirmation();
        mRequireConfirmation = requireConfirmation && supportsRequireConfirmation();
    }
    }


    void setJankListener(Animator.AnimatorListener jankListener) {
        mJankListener = jankListener;
    }

    @VisibleForTesting
    @VisibleForTesting
    final void updateSize(@AuthDialog.DialogSize int newSize) {
    final void updateSize(@AuthDialog.DialogSize int newSize) {
        Log.v(TAG, "Current size: " + mSize + " New size: " + newSize);
        Log.v(TAG, "Current size: " + mSize + " New size: " + newSize);
@@ -372,6 +378,9 @@ public abstract class AuthBiometricView extends LinearLayout {
                }
                }
            });
            });


            if (mJankListener != null) {
                as.addListener(mJankListener);
            }
            as.play(iconAnimator).with(opacityAnimator);
            as.play(iconAnimator).with(opacityAnimator);
            as.start();
            as.start();
            // Animate the panel
            // Animate the panel
@@ -427,6 +436,9 @@ public abstract class AuthBiometricView extends LinearLayout {
            animators.add(translationAnimator);
            animators.add(translationAnimator);
            animators.add(opacityAnimator);
            animators.add(opacityAnimator);


            if (mJankListener != null) {
                as.addListener(mJankListener);
            }
            as.playTogether(animators);
            as.playTogether(animators);
            as.setDuration(mAnimationDurationLong * 2 / 3);
            as.setDuration(mAnimationDurationLong * 2 / 3);
            as.start();
            as.start();
+65 −2
Original line number Original line Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.systemui.biometrics;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT;
import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;


import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION;

import android.animation.Animator;
import android.annotation.DurationMillisLong;
import android.annotation.DurationMillisLong;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -53,6 +56,7 @@ import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.ScrollView;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.Interpolators;
@@ -85,6 +89,13 @@ public class AuthContainerView extends LinearLayout
    private static final int STATE_ANIMATING_OUT = 4;
    private static final int STATE_ANIMATING_OUT = 4;
    private static final int STATE_GONE = 5;
    private static final int STATE_GONE = 5;


    /** Shows biometric prompt dialog animation. */
    private static final String SHOW = "show";
    /** Dismiss biometric prompt dialog animation.  */
    private static final String DISMISS = "dismiss";
    /** Transit biometric prompt dialog to pin, password, pattern credential panel. */
    private static final String TRANSIT = "transit";

    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({STATE_UNKNOWN, STATE_ANIMATING_IN, STATE_PENDING_DISMISS, STATE_SHOWING,
    @IntDef({STATE_UNKNOWN, STATE_ANIMATING_IN, STATE_PENDING_DISMISS, STATE_SHOWING,
            STATE_ANIMATING_OUT, STATE_GONE})
            STATE_ANIMATING_OUT, STATE_GONE})
@@ -99,6 +110,7 @@ public class AuthContainerView extends LinearLayout
    private final CredentialCallback mCredentialCallback;
    private final CredentialCallback mCredentialCallback;
    private final LockPatternUtils mLockPatternUtils;
    private final LockPatternUtils mLockPatternUtils;
    private final WakefulnessLifecycle mWakefulnessLifecycle;
    private final WakefulnessLifecycle mWakefulnessLifecycle;
    private final InteractionJankMonitor mInteractionJankMonitor;


    @VisibleForTesting final BiometricCallback mBiometricCallback;
    @VisibleForTesting final BiometricCallback mBiometricCallback;


@@ -208,10 +220,12 @@ public class AuthContainerView extends LinearLayout
                @Nullable List<FaceSensorPropertiesInternal> faceProps,
                @Nullable List<FaceSensorPropertiesInternal> faceProps,
                @NonNull WakefulnessLifecycle wakefulnessLifecycle,
                @NonNull WakefulnessLifecycle wakefulnessLifecycle,
                @NonNull UserManager userManager,
                @NonNull UserManager userManager,
                @NonNull LockPatternUtils lockPatternUtils) {
                @NonNull LockPatternUtils lockPatternUtils,
                @NonNull InteractionJankMonitor jankMonitor) {
            mConfig.mSensorIds = sensorIds;
            mConfig.mSensorIds = sensorIds;
            return new AuthContainerView(mConfig, fpProps, faceProps, wakefulnessLifecycle,
            return new AuthContainerView(mConfig, fpProps, faceProps, wakefulnessLifecycle,
                    userManager, lockPatternUtils, new Handler(Looper.getMainLooper()), bgExecutor);
                    userManager, lockPatternUtils, jankMonitor, new Handler(Looper.getMainLooper()),
                    bgExecutor);
        }
        }
    }
    }


@@ -264,6 +278,7 @@ public class AuthContainerView extends LinearLayout
            @NonNull WakefulnessLifecycle wakefulnessLifecycle,
            @NonNull WakefulnessLifecycle wakefulnessLifecycle,
            @NonNull UserManager userManager,
            @NonNull UserManager userManager,
            @NonNull LockPatternUtils lockPatternUtils,
            @NonNull LockPatternUtils lockPatternUtils,
            @NonNull InteractionJankMonitor jankMonitor,
            @NonNull Handler mainHandler,
            @NonNull Handler mainHandler,
            @NonNull @Background DelayableExecutor bgExecutor) {
            @NonNull @Background DelayableExecutor bgExecutor) {
        super(config.mContext);
        super(config.mContext);
@@ -290,6 +305,7 @@ public class AuthContainerView extends LinearLayout
        mPanelView = mFrameLayout.findViewById(R.id.panel);
        mPanelView = mFrameLayout.findViewById(R.id.panel);
        mPanelController = new AuthPanelController(mContext, mPanelView);
        mPanelController = new AuthPanelController(mContext, mPanelView);
        mBackgroundExecutor = bgExecutor;
        mBackgroundExecutor = bgExecutor;
        mInteractionJankMonitor = jankMonitor;


        // Inflate biometric view only if necessary.
        // Inflate biometric view only if necessary.
        if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
        if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
@@ -329,6 +345,8 @@ public class AuthContainerView extends LinearLayout
            mBiometricView.setBackgroundView(mBackgroundView);
            mBiometricView.setBackgroundView(mBackgroundView);
            mBiometricView.setUserId(mConfig.mUserId);
            mBiometricView.setUserId(mConfig.mUserId);
            mBiometricView.setEffectiveUserId(mEffectiveUserId);
            mBiometricView.setEffectiveUserId(mEffectiveUserId);
            mBiometricView.setJankListener(getJankListener(mBiometricView, TRANSIT,
                    AuthDialog.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS));
        }
        }


        // TODO: De-dupe the logic with AuthCredentialPasswordView
        // TODO: De-dupe the logic with AuthCredentialPasswordView
@@ -447,6 +465,7 @@ public class AuthContainerView extends LinearLayout
                        .translationY(0)
                        .translationY(0)
                        .setDuration(animateDuration)
                        .setDuration(animateDuration)
                        .setInterpolator(mLinearOutSlowIn)
                        .setInterpolator(mLinearOutSlowIn)
                        .setListener(getJankListener(mPanelView, SHOW, animateDuration))
                        .withLayer()
                        .withLayer()
                        .withEndAction(this::onDialogAnimatedIn)
                        .withEndAction(this::onDialogAnimatedIn)
                        .start();
                        .start();
@@ -454,6 +473,7 @@ public class AuthContainerView extends LinearLayout
                        .translationY(0)
                        .translationY(0)
                        .setDuration(animateDuration)
                        .setDuration(animateDuration)
                        .setInterpolator(mLinearOutSlowIn)
                        .setInterpolator(mLinearOutSlowIn)
                        .setListener(getJankListener(mBiometricScrollView, SHOW, animateDuration))
                        .withLayer()
                        .withLayer()
                        .start();
                        .start();
                if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
                if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
@@ -462,6 +482,7 @@ public class AuthContainerView extends LinearLayout
                            .translationY(0)
                            .translationY(0)
                            .setDuration(animateDuration)
                            .setDuration(animateDuration)
                            .setInterpolator(mLinearOutSlowIn)
                            .setInterpolator(mLinearOutSlowIn)
                            .setListener(getJankListener(mCredentialView, SHOW, animateDuration))
                            .withLayer()
                            .withLayer()
                            .start();
                            .start();
                }
                }
@@ -470,11 +491,49 @@ public class AuthContainerView extends LinearLayout
                        .setDuration(animateDuration)
                        .setDuration(animateDuration)
                        .setInterpolator(mLinearOutSlowIn)
                        .setInterpolator(mLinearOutSlowIn)
                        .withLayer()
                        .withLayer()
                        .setListener(getJankListener(this, SHOW, animateDuration))
                        .start();
                        .start();
            });
            });
        }
        }
    }
    }


    private Animator.AnimatorListener getJankListener(View v, String type, long timeout) {
        return new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(@androidx.annotation.NonNull Animator animation) {
                if (!v.isAttachedToWindow()) {
                    Log.w(TAG, "Un-attached view should not begin Jank trace.");
                    return;
                }
                mInteractionJankMonitor.begin(InteractionJankMonitor.Configuration.Builder.withView(
                        CUJ_BIOMETRIC_PROMPT_TRANSITION, v).setTag(type).setTimeout(timeout));
            }

            @Override
            public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) {
                if (!v.isAttachedToWindow()) {
                    Log.w(TAG, "Un-attached view should not end Jank trace.");
                    return;
                }
                mInteractionJankMonitor.end(CUJ_BIOMETRIC_PROMPT_TRANSITION);
            }

            @Override
            public void onAnimationCancel(@androidx.annotation.NonNull Animator animation) {
                if (!v.isAttachedToWindow()) {
                    Log.w(TAG, "Un-attached view should not cancel Jank trace.");
                    return;
                }
                mInteractionJankMonitor.cancel(CUJ_BIOMETRIC_PROMPT_TRANSITION);
            }

            @Override
            public void onAnimationRepeat(@androidx.annotation.NonNull Animator animation) {
                // no-op
            }
        };
    }

    private static boolean shouldUpdatePositionForUdfps(@NonNull View view) {
    private static boolean shouldUpdatePositionForUdfps(@NonNull View view) {
        if (view instanceof AuthBiometricFingerprintView) {
        if (view instanceof AuthBiometricFingerprintView) {
            return ((AuthBiometricFingerprintView) view).isUdfps();
            return ((AuthBiometricFingerprintView) view).isUdfps();
@@ -658,6 +717,7 @@ public class AuthContainerView extends LinearLayout
                    .translationY(mTranslationY)
                    .translationY(mTranslationY)
                    .setDuration(animateDuration)
                    .setDuration(animateDuration)
                    .setInterpolator(mLinearOutSlowIn)
                    .setInterpolator(mLinearOutSlowIn)
                    .setListener(getJankListener(mPanelView, DISMISS, animateDuration))
                    .withLayer()
                    .withLayer()
                    .withEndAction(endActionRunnable)
                    .withEndAction(endActionRunnable)
                    .start();
                    .start();
@@ -665,6 +725,7 @@ public class AuthContainerView extends LinearLayout
                    .translationY(mTranslationY)
                    .translationY(mTranslationY)
                    .setDuration(animateDuration)
                    .setDuration(animateDuration)
                    .setInterpolator(mLinearOutSlowIn)
                    .setInterpolator(mLinearOutSlowIn)
                    .setListener(getJankListener(mBiometricScrollView, DISMISS, animateDuration))
                    .withLayer()
                    .withLayer()
                    .start();
                    .start();
            if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
            if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
@@ -672,6 +733,7 @@ public class AuthContainerView extends LinearLayout
                        .translationY(mTranslationY)
                        .translationY(mTranslationY)
                        .setDuration(animateDuration)
                        .setDuration(animateDuration)
                        .setInterpolator(mLinearOutSlowIn)
                        .setInterpolator(mLinearOutSlowIn)
                        .setListener(getJankListener(mCredentialView, DISMISS, animateDuration))
                        .withLayer()
                        .withLayer()
                        .start();
                        .start();
            }
            }
@@ -679,6 +741,7 @@ public class AuthContainerView extends LinearLayout
                    .alpha(0f)
                    .alpha(0f)
                    .setDuration(animateDuration)
                    .setDuration(animateDuration)
                    .setInterpolator(mLinearOutSlowIn)
                    .setInterpolator(mLinearOutSlowIn)
                    .setListener(getJankListener(this, DISMISS, animateDuration))
                    .withLayer()
                    .withLayer()
                    .start();
                    .start();
        });
        });
+5 −1
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ import android.view.WindowManager;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.SomeArgs;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.CoreStartable;
import com.android.systemui.CoreStartable;
@@ -143,6 +144,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    private boolean mAllFingerprintAuthenticatorsRegistered;
    private boolean mAllFingerprintAuthenticatorsRegistered;
    @NonNull private final UserManager mUserManager;
    @NonNull private final UserManager mUserManager;
    @NonNull private final LockPatternUtils mLockPatternUtils;
    @NonNull private final LockPatternUtils mLockPatternUtils;
    @NonNull private final InteractionJankMonitor mInteractionJankMonitor;
    private final @Background DelayableExecutor mBackgroundExecutor;
    private final @Background DelayableExecutor mBackgroundExecutor;


    @VisibleForTesting
    @VisibleForTesting
@@ -549,6 +551,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
            @NonNull UserManager userManager,
            @NonNull UserManager userManager,
            @NonNull LockPatternUtils lockPatternUtils,
            @NonNull LockPatternUtils lockPatternUtils,
            @NonNull StatusBarStateController statusBarStateController,
            @NonNull StatusBarStateController statusBarStateController,
            @NonNull InteractionJankMonitor jankMonitor,
            @Main Handler handler,
            @Main Handler handler,
            @Background DelayableExecutor bgExecutor) {
            @Background DelayableExecutor bgExecutor) {
        super(context);
        super(context);
@@ -566,6 +569,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
        mSidefpsControllerFactory = sidefpsControllerFactory;
        mSidefpsControllerFactory = sidefpsControllerFactory;
        mDisplayManager = displayManager;
        mDisplayManager = displayManager;
        mWindowManager = windowManager;
        mWindowManager = windowManager;
        mInteractionJankMonitor = jankMonitor;
        mUdfpsEnrolledForUser = new SparseBooleanArray();
        mUdfpsEnrolledForUser = new SparseBooleanArray();


        mOrientationListener = new BiometricDisplayListener(
        mOrientationListener = new BiometricDisplayListener(
@@ -1041,7 +1045,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
                    return getScaleFactor();
                    return getScaleFactor();
                })
                })
                .build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
                .build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
                        userManager, lockPatternUtils);
                        userManager, lockPatternUtils, mInteractionJankMonitor);
    }
    }


    /**
    /**
+4 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import android.view.WindowInsets
import android.view.WindowManager
import android.view.WindowManager
import android.widget.ScrollView
import android.widget.ScrollView
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.R
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
@@ -71,6 +72,8 @@ class AuthContainerViewTest : SysuiTestCase() {
    lateinit var wakefulnessLifecycle: WakefulnessLifecycle
    lateinit var wakefulnessLifecycle: WakefulnessLifecycle
    @Mock
    @Mock
    lateinit var windowToken: IBinder
    lateinit var windowToken: IBinder
    @Mock
    lateinit var interactionJankMonitor: InteractionJankMonitor


    private var authContainer: TestAuthContainerView? = null
    private var authContainer: TestAuthContainerView? = null


@@ -356,6 +359,7 @@ class AuthContainerViewTest : SysuiTestCase() {
        wakefulnessLifecycle,
        wakefulnessLifecycle,
        userManager,
        userManager,
        lockPatternUtils,
        lockPatternUtils,
        interactionJankMonitor,
        Handler(TestableLooper.get(this).looper),
        Handler(TestableLooper.get(this).looper),
        FakeExecutor(FakeSystemClock())
        FakeExecutor(FakeSystemClock())
    ) {
    ) {
+5 −2
Original line number Original line Diff line number Diff line
@@ -77,6 +77,7 @@ import android.view.WindowManager;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -150,6 +151,8 @@ public class AuthControllerTest extends SysuiTestCase {
    private LockPatternUtils mLockPatternUtils;
    private LockPatternUtils mLockPatternUtils;
    @Mock
    @Mock
    private StatusBarStateController mStatusBarStateController;
    private StatusBarStateController mStatusBarStateController;
    @Mock
    private InteractionJankMonitor mInteractionJankMonitor;
    @Captor
    @Captor
    ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
    ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
    @Captor
    @Captor
@@ -788,8 +791,8 @@ public class AuthControllerTest extends SysuiTestCase {
            super(context, execution, commandQueue, activityTaskManager, windowManager,
            super(context, execution, commandQueue, activityTaskManager, windowManager,
                    fingerprintManager, faceManager, udfpsControllerFactory,
                    fingerprintManager, faceManager, udfpsControllerFactory,
                    sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle,
                    sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle,
                    mUserManager, mLockPatternUtils, statusBarStateController, mHandler,
                    mUserManager, mLockPatternUtils, statusBarStateController,
                    mBackgroundExecutor);
                    mInteractionJankMonitor, mHandler, mBackgroundExecutor);
        }
        }


        @Override
        @Override