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

Commit c3e039f9 authored by Joe Bolinger's avatar Joe Bolinger
Browse files

Add a device orientation listener for updaing UDFPS layouts.

Configuration change events are only generated when switching to/from portrait/landscape modes and can't be used for udfps overlays.

Fix: 190832486
Test: manual (put device in landscape, start auth, flip 180 degrees)
Change-Id: If03d8ee3ec479b91eab93622a6e93f00b3f14765
parent 571124ed
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.UserManager;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -475,6 +476,11 @@ public class AuthContainerView extends LinearLayout
        mPanelController.setContainerDimensions(getMeasuredWidth(), getMeasuredHeight());
    }

    @Override
    public void onOrientationChanged() {
        maybeUpdatePositionForUdfps(true /* invalidate */);
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
@@ -555,11 +561,15 @@ public class AuthContainerView extends LinearLayout
    }

    private boolean maybeUpdatePositionForUdfps(boolean invalidate) {
        final Display display = getDisplay();
        if (display == null) {
            return false;
        }
        if (!shouldUpdatePositionForUdfps(mBiometricView)) {
            return false;
        }

        final int displayRotation = getDisplay().getRotation();
        final int displayRotation = display.getRotation();
        switch (displayRotation) {
            case Surface.ROTATION_0:
                mPanelController.setPosition(AuthPanelController.POSITION_BOTTOM);
+56 −28
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.PointF;
import android.graphics.RectF;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
@@ -49,7 +48,10 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.WindowManager;

import com.android.internal.R;
@@ -97,17 +99,15 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
    @VisibleForTesting
    AuthDialog mCurrentDialog;

    private WindowManager mWindowManager;
    @Nullable
    private UdfpsController mUdfpsController;
    @Nullable
    private IUdfpsHbmListener mUdfpsHbmListener;
    @Nullable
    private SidefpsController mSidefpsController;
    @NonNull private final WindowManager mWindowManager;
    @Nullable private UdfpsController mUdfpsController;
    @Nullable private IUdfpsHbmListener mUdfpsHbmListener;
    @Nullable private SidefpsController mSidefpsController;
    @VisibleForTesting
    TaskStackListener mTaskStackListener;
    @VisibleForTesting
    IBiometricSysuiReceiver mReceiver;
    @NonNull private final BiometricOrientationEventListener mOrientationListener;
    @Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
    @Nullable private List<FingerprintSensorPropertiesInternal> mFpProps;
    @Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
@@ -120,6 +120,42 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        }
    }

    private class BiometricOrientationEventListener extends OrientationEventListener {
        @Surface.Rotation private int mLastRotation;

        BiometricOrientationEventListener(Context context) {
            super(context);
            mLastRotation = context.getDisplay().getRotation();
        }

        @Override
        public void onOrientationChanged(int orientation) {
            if (orientation == ORIENTATION_UNKNOWN) {
                return;
            }

            final Display display = mContext.getDisplay();
            if (display == null) {
                return;
            }

            final int rotation = display.getRotation();
            if (mLastRotation != rotation) {
                mLastRotation = rotation;

                if (mCurrentDialog != null) {
                    mCurrentDialog.onOrientationChanged();
                }
                if (mUdfpsController != null) {
                    mUdfpsController.onOrientationChanged();
                }
                if (mSidefpsController != null) {
                    mSidefpsController.onOrientationChanged();
                }
            }
        }
    }

    @NonNull
    private final IFingerprintAuthenticatorsRegisteredCallback
            mFingerprintAuthenticatorsRegisteredCallback =
@@ -164,6 +200,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
                Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
                mCurrentDialog.dismissWithoutCallback(true /* animate */);
                mCurrentDialog = null;
                mOrientationListener.disable();

                try {
                    if (mReceiver != null) {
@@ -192,6 +229,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
                        Log.w(TAG, "Evicting client due to: " + topPackage);
                        mCurrentDialog.dismissWithoutCallback(true /* animate */);
                        mCurrentDialog = null;
                        mOrientationListener.disable();

                        if (mReceiver != null) {
                            mReceiver.onDialogDismissed(
                                    BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
@@ -339,15 +378,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        }
    }

    /**
     * @return where the UDFPS exists on the screen in pixels in portrait mode.
     */
    @Nullable public RectF getUdfpsRegion() {
        return mUdfpsController == null
                ? null
                : mUdfpsController.getSensorLocation();
    }

    /**
     * @return where the UDFPS exists on the screen in pixels in portrait mode.
     */
@@ -422,8 +452,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
    }

    @Inject
    public AuthController(Context context, CommandQueue commandQueue,
    public AuthController(Context context,
            CommandQueue commandQueue,
            ActivityTaskManager activityTaskManager,
            @NonNull WindowManager windowManager,
            @Nullable FingerprintManager fingerprintManager,
            @Nullable FaceManager faceManager,
            Provider<UdfpsController> udfpsControllerFactory,
@@ -435,6 +467,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        mFaceManager = faceManager;
        mUdfpsControllerFactory = udfpsControllerFactory;
        mSidefpsControllerFactory = sidefpsControllerFactory;
        mWindowManager = windowManager;
        mOrientationListener = new BiometricOrientationEventListener(context);

        mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;

@@ -462,7 +496,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
    @Override
    public void start() {
        mCommandQueue.addCallback(this);
        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

        if (mFingerprintManager != null) {
            mFingerprintManager.addAuthenticatorsRegisteredCallback(
@@ -630,6 +663,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        // BiometricService will have already sent the callback to the client in this case.
        // This avoids a round trip to SystemUI. So, just dismiss the dialog and we're done.
        mCurrentDialog = null;
        mOrientationListener.disable();
    }

    /**
@@ -701,6 +735,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        mReceiver = (IBiometricSysuiReceiver) args.arg2;
        mCurrentDialog = newDialog;
        mCurrentDialog.show(mWindowManager, savedState);
        mOrientationListener.enable();
    }

    private void onDialogDismissed(@DismissedReason int reason) {
@@ -710,20 +745,12 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
        }
        mReceiver = null;
        mCurrentDialog = null;
        mOrientationListener.disable();
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // UdfpsController is not BiometricPrompt-specific. It can be active for keyguard or
        // enrollment.
        if (mUdfpsController != null) {
            mUdfpsController.onConfigurationChanged();
        }

        if (mSidefpsController != null) {
            mSidefpsController.onConfigurationChanged();
        }

        // Save the state of the current dialog (buttons showing, etc)
        if (mCurrentDialog != null) {
@@ -731,6 +758,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
            mCurrentDialog.onSaveState(savedState);
            mCurrentDialog.dismissWithoutCallback(false /* animate */);
            mCurrentDialog = null;
            mOrientationListener.disable();

            // Only show the dialog if necessary. If it was animating out, the dialog is supposed
            // to send its pending callback immediately.
+8 −0
Original line number Diff line number Diff line
@@ -156,4 +156,12 @@ public interface AuthDialog {
     * @return true if device credential is allowed.
     */
    boolean isAllowDeviceCredentials();

    /**
     * Called when the device's orientation changed and the dialog may need to do another
     * layout. This is most relevant to UDFPS since configuration changes are not sent by
     * the framework in equivalent cases (landscape to reverse landscape) but the dialog
     * must remain fixed on the physical sensor location.
     */
    void onOrientationChanged();
}
+1 −2
Original line number Diff line number Diff line
@@ -137,8 +137,7 @@ public class SidefpsController {
        }
    }


    void onConfigurationChanged() {
    void onOrientationChanged() {
        // If mView is null or if view is hidden, then return.
        if (mView == null || !mIsVisible) {
            return;
+1 −1
Original line number Diff line number Diff line
@@ -650,7 +650,7 @@ public class UdfpsController implements DozeReceiver {
        return mCoreLayoutParams;
    }

    void onConfigurationChanged() {
    void onOrientationChanged() {
        // When the configuration changes it's almost always necessary to destroy and re-create
        // the overlay's window to pass it the new LayoutParams.
        // Hiding the overlay will destroy its window. It's safe to hide the overlay regardless
Loading