Merge "Instrument CUJ_BIOMETRIC_PROMPT with InteractionJankMonitor" into tm-d1-dev am: 9ecbf3139d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18482949

Change-Id: Ib6f382af259b37ec54d12e732000b3372bbece66
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Bill Lin
2022-05-23 18:17:58 +00:00
committed by Automerger Merge Worker
5 changed files with 91 additions and 5 deletions

View File

@@ -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();

View File

@@ -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();
}); });

View File

@@ -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);
} }
/** /**

View File

@@ -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())
) { ) {

View File

@@ -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