diff options
| author | 2021-07-02 16:26:31 -0700 | |
|---|---|---|
| committer | 2021-07-02 17:09:41 -0700 | |
| commit | c3e039f9cae09d9a3174fb4646057948e26d357c (patch) | |
| tree | d2dbf08c655db20c34c88668a594a0feadb0283b | |
| parent | 571124edc93a50c88f1cd778b26b2c75d7daf27e (diff) | |
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
6 files changed, 85 insertions, 35 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index a533d2cd97d2..3f61d3c6af9a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -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; @@ -476,6 +477,11 @@ public class AuthContainerView extends LinearLayout } @Override + public void onOrientationChanged() { + maybeUpdatePositionForUdfps(true /* invalidate */); + } + + @Override public void onAttachedToWindow() { super.onAttachedToWindow(); onAttachedToWindowInternal(); @@ -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); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 7947241ff794..2a18055da232 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -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, @@ -342,15 +381,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. - */ @Nullable public PointF getUdfpsSensorLocation() { if (mUdfpsController == null) { return null; @@ -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. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java index ff31e499f6e8..fa5213e94081 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java @@ -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(); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java index a52296a71960..436e1e4e3116 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 38f85cdb4a9b..81e60f316bbd 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -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 diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index 9774ea98ff0d..bfcd1310acc2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -59,6 +59,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.testing.TestableLooper.RunWithLooper; +import android.view.WindowManager; import com.android.internal.R; import com.android.systemui.SysuiTestCase; @@ -97,6 +98,8 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private ActivityTaskManager mActivityTaskManager; @Mock + private WindowManager mWindowManager; + @Mock private FingerprintManager mFingerprintManager; @Mock private FaceManager mFaceManager; @@ -149,7 +152,7 @@ public class AuthControllerTest extends SysuiTestCase { when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); mAuthController = new TestableAuthController(context, mCommandQueue, - mActivityTaskManager, mFingerprintManager, mFaceManager, + mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager, () -> mUdfpsController, () -> mSidefpsController); mAuthController.start(); @@ -576,13 +579,15 @@ public class AuthControllerTest extends SysuiTestCase { private int mBuildCount = 0; private PromptInfo mLastBiometricPromptInfo; - TestableAuthController(Context context, CommandQueue commandQueue, + TestableAuthController(Context context, + CommandQueue commandQueue, ActivityTaskManager activityTaskManager, + WindowManager windowManager, FingerprintManager fingerprintManager, FaceManager faceManager, Provider<UdfpsController> udfpsControllerFactory, Provider<SidefpsController> sidefpsControllerFactory) { - super(context, commandQueue, activityTaskManager, + super(context, commandQueue, activityTaskManager, windowManager, fingerprintManager, faceManager, udfpsControllerFactory, sidefpsControllerFactory); } |