Merge "Fix BP disappear when devices change to unfold mode from fold mode"

This commit is contained in:
Vincent Wang
2022-12-22 09:31:21 +00:00
committed by Android (Google) Code Review
6 changed files with 85 additions and 85 deletions

View File

@@ -120,6 +120,7 @@ public class AuthContainerView extends LinearLayout
private final Interpolator mLinearOutSlowIn;
private final LockPatternUtils mLockPatternUtils;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final AuthDialogPanelInteractionDetector mPanelInteractionDetector;
private final InteractionJankMonitor mInteractionJankMonitor;
// TODO: these should be migrated out once ready
@@ -141,7 +142,6 @@ public class AuthContainerView extends LinearLayout
private final OnBackInvokedCallback mBackCallback = this::onBackInvoked;
private final @Background DelayableExecutor mBackgroundExecutor;
private boolean mIsOrientationChanged = false;
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
@Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
@@ -235,6 +235,7 @@ public class AuthContainerView extends LinearLayout
@Nullable List<FingerprintSensorPropertiesInternal> fpProps,
@Nullable List<FaceSensorPropertiesInternal> faceProps,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils,
@NonNull InteractionJankMonitor jankMonitor,
@@ -242,8 +243,9 @@ public class AuthContainerView extends LinearLayout
@NonNull Provider<CredentialViewModel> credentialViewModelProvider) {
mConfig.mSensorIds = sensorIds;
return new AuthContainerView(mConfig, fpProps, faceProps, wakefulnessLifecycle,
userManager, lockPatternUtils, jankMonitor, biometricPromptInteractor,
credentialViewModelProvider, new Handler(Looper.getMainLooper()), bgExecutor);
panelInteractionDetector, userManager, lockPatternUtils, jankMonitor,
biometricPromptInteractor, credentialViewModelProvider,
new Handler(Looper.getMainLooper()), bgExecutor);
}
}
@@ -331,6 +333,7 @@ public class AuthContainerView extends LinearLayout
@Nullable List<FingerprintSensorPropertiesInternal> fpProps,
@Nullable List<FaceSensorPropertiesInternal> faceProps,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils,
@NonNull InteractionJankMonitor jankMonitor,
@@ -346,6 +349,7 @@ public class AuthContainerView extends LinearLayout
mHandler = mainHandler;
mWindowManager = mContext.getSystemService(WindowManager.class);
mWakefulnessLifecycle = wakefulnessLifecycle;
mPanelInteractionDetector = panelInteractionDetector;
mTranslationY = getResources()
.getDimension(R.dimen.biometric_dialog_animation_translation_offset);
@@ -490,22 +494,6 @@ public class AuthContainerView extends LinearLayout
@Override
public void onOrientationChanged() {
maybeUpdatePositionForUdfps(true /* invalidate */);
mIsOrientationChanged = true;
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!hasWindowFocus) {
//it's a workaround to avoid closing BP incorrectly
//BP gets a onWindowFocusChanged(false) and then gets a onWindowFocusChanged(true)
if (mIsOrientationChanged) {
mIsOrientationChanged = false;
return;
}
Log.v(TAG, "Lost window focus, dismissing the dialog");
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
}
@Override
@@ -513,6 +501,8 @@ public class AuthContainerView extends LinearLayout
super.onAttachedToWindow();
mWakefulnessLifecycle.addObserver(this);
mPanelInteractionDetector.enable(
() -> animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED));
if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
mBiometricScrollView.addView(mBiometricView);
@@ -666,11 +656,6 @@ public class AuthContainerView extends LinearLayout
mBiometricView.restoreState(savedState);
}
if (savedState != null) {
mIsOrientationChanged = savedState.getBoolean(
AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED);
}
wm.addView(this, getLayoutParams(mWindowToken, mConfig.mPromptInfo.getTitle()));
}
@@ -689,6 +674,7 @@ public class AuthContainerView extends LinearLayout
@Override
public void dismissWithoutCallback(boolean animate) {
mPanelInteractionDetector.disable();
if (animate) {
animateAway(false /* sendReason */, 0 /* reason */);
} else {
@@ -699,6 +685,7 @@ public class AuthContainerView extends LinearLayout
@Override
public void dismissFromSystemServer() {
mPanelInteractionDetector.disable();
animateAway(false /* sendReason */, 0 /* reason */);
}
@@ -761,8 +748,6 @@ public class AuthContainerView extends LinearLayout
mBiometricView != null && mCredentialView == null);
outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
outState.putBoolean(AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED, mIsOrientationChanged);
if (mBiometricView != null) {
mBiometricView.onSaveState(outState);
}

View File

@@ -164,6 +164,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@NonNull private final SparseBooleanArray mSfpsEnrolledForUser;
@NonNull private final SensorPrivacyManager mSensorPrivacyManager;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final AuthDialogPanelInteractionDetector mPanelInteractionDetector;
private boolean mAllFingerprintAuthenticatorsRegistered;
@NonNull private final UserManager mUserManager;
@NonNull private final LockPatternUtils mLockPatternUtils;
@@ -721,6 +722,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
Provider<SideFpsController> sidefpsControllerFactory,
@NonNull DisplayManager displayManager,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils,
@NonNull UdfpsLogger udfpsLogger,
@@ -767,6 +769,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
});
mWakefulnessLifecycle = wakefulnessLifecycle;
mPanelInteractionDetector = panelInteractionDetector;
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
int[] faceAuthLocation = context.getResources().getIntArray(
@@ -1149,6 +1153,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
requestId,
multiSensorConfig,
mWakefulnessLifecycle,
mPanelInteractionDetector,
mUserManager,
mLockPatternUtils);
@@ -1239,6 +1244,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@BiometricMultiSensorMode int multiSensorConfig,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils) {
return new AuthContainerView.Builder(mContext)
@@ -1253,8 +1259,9 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
.setMultiSensorConfig(multiSensorConfig)
.setScaleFactorProvider(() -> getScaleFactor())
.build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
userManager, lockPatternUtils, mInteractionJankMonitor,
mBiometricPromptInteractor, mCredentialViewModelProvider);
panelInteractionDetector, userManager, lockPatternUtils,
mInteractionJankMonitor, mBiometricPromptInteractor,
mCredentialViewModelProvider);
}
@Override

View File

@@ -48,8 +48,6 @@ public interface AuthDialog extends Dumpable {
String KEY_BIOMETRIC_SENSOR_TYPE = "sensor_type";
String KEY_BIOMETRIC_SENSOR_PROPS = "sensor_props";
String KEY_BIOMETRIC_ORIENTATION_CHANGED = "orientation_changed";
int SIZE_UNKNOWN = 0;
/**
* Minimal UI, showing only biometric icon.

View File

@@ -0,0 +1,53 @@
package com.android.systemui.biometrics
import android.annotation.AnyThread
import android.annotation.MainThread
import android.util.Log
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
import java.util.concurrent.Executor
import javax.inject.Inject
class AuthDialogPanelInteractionDetector
@Inject
constructor(
private val shadeExpansionStateManager: ShadeExpansionStateManager,
@Main private val mainExecutor: Executor,
) {
private var action: Action? = null
@MainThread
fun enable(onPanelInteraction: Runnable) {
if (action == null) {
action = Action(onPanelInteraction)
shadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged)
} else {
Log.e(TAG, "Already enabled")
}
}
@MainThread
fun disable() {
if (action != null) {
action = null
shadeExpansionStateManager.removeExpansionListener(this::onPanelExpansionChanged)
}
}
@AnyThread
private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) =
mainExecutor.execute {
action?.let {
if (event.tracking) {
Log.v(TAG, "Detected panel interaction, event: $event")
it.onPanelInteraction.run()
disable()
}
}
}
}
private data class Action(val onPanelInteraction: Runnable)
private const val TAG = "AuthDialogPanelInteractionDetector"

View File

@@ -35,8 +35,6 @@ import android.view.WindowInsets
import android.view.WindowManager
import android.widget.ScrollView
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.R
@@ -81,6 +79,8 @@ class AuthContainerViewTest : SysuiTestCase() {
@Mock
lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock
lateinit var panelInteractionDetector: AuthDialogPanelInteractionDetector
@Mock
lateinit var windowToken: IBinder
@Mock
lateinit var interactionJankMonitor: InteractionJankMonitor
@@ -169,26 +169,6 @@ class AuthContainerViewTest : SysuiTestCase() {
verify(callback, times(2)).onDialogAnimatedIn(authContainer?.requestId ?: 0L)
}
@Test
fun testDismissesOnFocusLoss() {
val container = initializeFingerprintContainer()
waitForIdleSync()
val requestID = authContainer?.requestId ?: 0L
verify(callback).onDialogAnimatedIn(requestID)
container.onWindowFocusChanged(false)
waitForIdleSync()
verify(callback).onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq<ByteArray?>(null), /* credentialAttestation */
eq(requestID)
)
assertThat(container.parent).isNull()
}
@Test
fun testFocusLossAfterRotating() {
val container = initializeFingerprintContainer()
@@ -208,35 +188,6 @@ class AuthContainerViewTest : SysuiTestCase() {
)
}
@Test
fun testDismissesOnFocusLoss_hidesKeyboardWhenVisible() {
val container = initializeFingerprintContainer(
authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL
)
waitForIdleSync()
val requestID = authContainer?.requestId ?: 0L
// Simulate keyboard was shown on the credential view
val windowInsetsController = container.windowInsetsController
spyOn(windowInsetsController)
spyOn(container.rootWindowInsets)
doReturn(true).`when`(container.rootWindowInsets).isVisible(WindowInsets.Type.ime())
container.onWindowFocusChanged(false)
waitForIdleSync()
// Expect hiding IME request will be invoked when dismissing the view
verify(windowInsetsController)?.hide(WindowInsets.Type.ime())
verify(callback).onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq<ByteArray?>(null), /* credentialAttestation */
eq(requestID)
)
assertThat(container.parent).isNull()
}
@Test
fun testActionAuthenticated_sendsDismissedAuthenticated() {
val container = initializeFingerprintContainer()
@@ -519,6 +470,7 @@ class AuthContainerViewTest : SysuiTestCase() {
fingerprintProps,
faceProps,
wakefulnessLifecycle,
panelInteractionDetector,
userManager,
lockPatternUtils,
interactionJankMonitor,

View File

@@ -152,6 +152,8 @@ public class AuthControllerTest extends SysuiTestCase {
@Mock
private WakefulnessLifecycle mWakefulnessLifecycle;
@Mock
private AuthDialogPanelInteractionDetector mPanelInteractionDetector;
@Mock
private UserManager mUserManager;
@Mock
private LockPatternUtils mLockPatternUtils;
@@ -953,9 +955,10 @@ public class AuthControllerTest extends SysuiTestCase {
super(context, mExecution, mCommandQueue, mActivityTaskManager, mWindowManager,
mFingerprintManager, mFaceManager, () -> mUdfpsController,
() -> mSideFpsController, mDisplayManager, mWakefulnessLifecycle,
mUserManager, mLockPatternUtils, mUdfpsLogger, mLogContextInteractor,
() -> mBiometricPromptCredentialInteractor, () -> mCredentialViewModel,
mInteractionJankMonitor, mHandler, mBackgroundExecutor, mVibratorHelper);
mPanelInteractionDetector, mUserManager, mLockPatternUtils, mUdfpsLogger,
mLogContextInteractor, () -> mBiometricPromptCredentialInteractor,
() -> mCredentialViewModel, mInteractionJankMonitor, mHandler,
mBackgroundExecutor, mVibratorHelper);
}
@Override
@@ -963,7 +966,9 @@ public class AuthControllerTest extends SysuiTestCase {
boolean requireConfirmation, int userId, int[] sensorIds,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@BiometricManager.BiometricMultiSensorMode int multiSensorConfig,
WakefulnessLifecycle wakefulnessLifecycle, UserManager userManager,
WakefulnessLifecycle wakefulnessLifecycle,
AuthDialogPanelInteractionDetector panelInteractionDetector,
UserManager userManager,
LockPatternUtils lockPatternUtils) {
mLastBiometricPromptInfo = promptInfo;