Merge "Fix BP disappear when devices change to unfold mode from fold mode"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user