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
This commit is contained in:
@@ -166,6 +166,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
private final Runnable mResetErrorRunnable;
|
||||
private final Runnable mResetHelpRunnable;
|
||||
|
||||
private Animator.AnimatorListener mJankListener;
|
||||
|
||||
private final OnClickListener mBackgroundClickListener = (view) -> {
|
||||
if (mState == STATE_AUTHENTICATED) {
|
||||
Log.w(TAG, "Ignoring background click after authenticated");
|
||||
@@ -282,6 +284,10 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
mRequireConfirmation = requireConfirmation && supportsRequireConfirmation();
|
||||
}
|
||||
|
||||
void setJankListener(Animator.AnimatorListener jankListener) {
|
||||
mJankListener = jankListener;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final void updateSize(@AuthDialog.DialogSize int 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.start();
|
||||
// Animate the panel
|
||||
@@ -427,6 +436,9 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
animators.add(translationAnimator);
|
||||
animators.add(opacityAnimator);
|
||||
|
||||
if (mJankListener != null) {
|
||||
as.addListener(mJankListener);
|
||||
}
|
||||
as.playTogether(animators);
|
||||
as.setDuration(mAnimationDurationLong * 2 / 3);
|
||||
as.start();
|
||||
|
||||
@@ -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.BiometricMultiSensorMode;
|
||||
|
||||
import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.annotation.DurationMillisLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
@@ -53,6 +56,7 @@ import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.systemui.R;
|
||||
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_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)
|
||||
@IntDef({STATE_UNKNOWN, STATE_ANIMATING_IN, STATE_PENDING_DISMISS, STATE_SHOWING,
|
||||
STATE_ANIMATING_OUT, STATE_GONE})
|
||||
@@ -99,6 +110,7 @@ public class AuthContainerView extends LinearLayout
|
||||
private final CredentialCallback mCredentialCallback;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final WakefulnessLifecycle mWakefulnessLifecycle;
|
||||
private final InteractionJankMonitor mInteractionJankMonitor;
|
||||
|
||||
@VisibleForTesting final BiometricCallback mBiometricCallback;
|
||||
|
||||
@@ -208,10 +220,12 @@ public class AuthContainerView extends LinearLayout
|
||||
@Nullable List<FaceSensorPropertiesInternal> faceProps,
|
||||
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
|
||||
@NonNull UserManager userManager,
|
||||
@NonNull LockPatternUtils lockPatternUtils) {
|
||||
@NonNull LockPatternUtils lockPatternUtils,
|
||||
@NonNull InteractionJankMonitor jankMonitor) {
|
||||
mConfig.mSensorIds = sensorIds;
|
||||
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 UserManager userManager,
|
||||
@NonNull LockPatternUtils lockPatternUtils,
|
||||
@NonNull InteractionJankMonitor jankMonitor,
|
||||
@NonNull Handler mainHandler,
|
||||
@NonNull @Background DelayableExecutor bgExecutor) {
|
||||
super(config.mContext);
|
||||
@@ -290,6 +305,7 @@ public class AuthContainerView extends LinearLayout
|
||||
mPanelView = mFrameLayout.findViewById(R.id.panel);
|
||||
mPanelController = new AuthPanelController(mContext, mPanelView);
|
||||
mBackgroundExecutor = bgExecutor;
|
||||
mInteractionJankMonitor = jankMonitor;
|
||||
|
||||
// Inflate biometric view only if necessary.
|
||||
if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
|
||||
@@ -329,6 +345,8 @@ public class AuthContainerView extends LinearLayout
|
||||
mBiometricView.setBackgroundView(mBackgroundView);
|
||||
mBiometricView.setUserId(mConfig.mUserId);
|
||||
mBiometricView.setEffectiveUserId(mEffectiveUserId);
|
||||
mBiometricView.setJankListener(getJankListener(mBiometricView, TRANSIT,
|
||||
AuthDialog.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS));
|
||||
}
|
||||
|
||||
// TODO: De-dupe the logic with AuthCredentialPasswordView
|
||||
@@ -447,6 +465,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(0)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mPanelView, SHOW, animateDuration))
|
||||
.withLayer()
|
||||
.withEndAction(this::onDialogAnimatedIn)
|
||||
.start();
|
||||
@@ -454,6 +473,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(0)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mBiometricScrollView, SHOW, animateDuration))
|
||||
.withLayer()
|
||||
.start();
|
||||
if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
|
||||
@@ -462,6 +482,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(0)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mCredentialView, SHOW, animateDuration))
|
||||
.withLayer()
|
||||
.start();
|
||||
}
|
||||
@@ -470,11 +491,49 @@ public class AuthContainerView extends LinearLayout
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.withLayer()
|
||||
.setListener(getJankListener(this, SHOW, animateDuration))
|
||||
.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) {
|
||||
if (view instanceof AuthBiometricFingerprintView) {
|
||||
return ((AuthBiometricFingerprintView) view).isUdfps();
|
||||
@@ -658,6 +717,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(mTranslationY)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mPanelView, DISMISS, animateDuration))
|
||||
.withLayer()
|
||||
.withEndAction(endActionRunnable)
|
||||
.start();
|
||||
@@ -665,6 +725,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(mTranslationY)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mBiometricScrollView, DISMISS, animateDuration))
|
||||
.withLayer()
|
||||
.start();
|
||||
if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
|
||||
@@ -672,6 +733,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.translationY(mTranslationY)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(mCredentialView, DISMISS, animateDuration))
|
||||
.withLayer()
|
||||
.start();
|
||||
}
|
||||
@@ -679,6 +741,7 @@ public class AuthContainerView extends LinearLayout
|
||||
.alpha(0f)
|
||||
.setDuration(animateDuration)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.setListener(getJankListener(this, DISMISS, animateDuration))
|
||||
.withLayer()
|
||||
.start();
|
||||
});
|
||||
|
||||
@@ -62,6 +62,7 @@ import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.systemui.CoreStartable;
|
||||
@@ -143,6 +144,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
private boolean mAllFingerprintAuthenticatorsRegistered;
|
||||
@NonNull private final UserManager mUserManager;
|
||||
@NonNull private final LockPatternUtils mLockPatternUtils;
|
||||
@NonNull private final InteractionJankMonitor mInteractionJankMonitor;
|
||||
private final @Background DelayableExecutor mBackgroundExecutor;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -549,6 +551,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
@NonNull UserManager userManager,
|
||||
@NonNull LockPatternUtils lockPatternUtils,
|
||||
@NonNull StatusBarStateController statusBarStateController,
|
||||
@NonNull InteractionJankMonitor jankMonitor,
|
||||
@Main Handler handler,
|
||||
@Background DelayableExecutor bgExecutor) {
|
||||
super(context);
|
||||
@@ -566,6 +569,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
mSidefpsControllerFactory = sidefpsControllerFactory;
|
||||
mDisplayManager = displayManager;
|
||||
mWindowManager = windowManager;
|
||||
mInteractionJankMonitor = jankMonitor;
|
||||
mUdfpsEnrolledForUser = new SparseBooleanArray();
|
||||
|
||||
mOrientationListener = new BiometricDisplayListener(
|
||||
@@ -1041,7 +1045,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
return getScaleFactor();
|
||||
})
|
||||
.build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
|
||||
userManager, lockPatternUtils);
|
||||
userManager, lockPatternUtils, mInteractionJankMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import android.widget.ScrollView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.jank.InteractionJankMonitor
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
@@ -71,6 +72,8 @@ class AuthContainerViewTest : SysuiTestCase() {
|
||||
lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
||||
@Mock
|
||||
lateinit var windowToken: IBinder
|
||||
@Mock
|
||||
lateinit var interactionJankMonitor: InteractionJankMonitor
|
||||
|
||||
private var authContainer: TestAuthContainerView? = null
|
||||
|
||||
@@ -356,6 +359,7 @@ class AuthContainerViewTest : SysuiTestCase() {
|
||||
wakefulnessLifecycle,
|
||||
userManager,
|
||||
lockPatternUtils,
|
||||
interactionJankMonitor,
|
||||
Handler(TestableLooper.get(this).looper),
|
||||
FakeExecutor(FakeSystemClock())
|
||||
) {
|
||||
|
||||
@@ -77,6 +77,7 @@ import android.view.WindowManager;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle;
|
||||
@@ -150,6 +151,8 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
@Mock
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
@Mock
|
||||
private InteractionJankMonitor mInteractionJankMonitor;
|
||||
@Captor
|
||||
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
|
||||
@Captor
|
||||
@@ -788,8 +791,8 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
super(context, execution, commandQueue, activityTaskManager, windowManager,
|
||||
fingerprintManager, faceManager, udfpsControllerFactory,
|
||||
sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle,
|
||||
mUserManager, mLockPatternUtils, statusBarStateController, mHandler,
|
||||
mBackgroundExecutor);
|
||||
mUserManager, mLockPatternUtils, statusBarStateController,
|
||||
mInteractionJankMonitor, mHandler, mBackgroundExecutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user