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

Commit c0c490d7 authored by Vincent Wang's avatar Vincent Wang Committed by Android (Google) Code Review
Browse files

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

parents 81612163 d3301fdc
Loading
Loading
Loading
Loading
+11 −26
Original line number Diff line number Diff line
@@ -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);
        }
+9 −2
Original line number Diff line number Diff line
@@ -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
+0 −2
Original line number Diff line number Diff line
@@ -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.
+53 −0
Original line number Diff line number Diff line
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"
+3 −51
Original line number Diff line number Diff line
@@ -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,
Loading