Loading packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/UdfpsUtils.java +76 −19 Original line number Diff line number Diff line Loading @@ -54,8 +54,9 @@ public class UdfpsUtils { } /** * Gets the touch in native coordinates. Map the touch to portrait mode if the device is in * landscape mode. * Gets the touch in native coordinates. * * Maps the touch to portrait mode if the device is in landscape mode. * * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. Loading @@ -64,35 +65,87 @@ public class UdfpsUtils { */ public Point getTouchInNativeCoordinates(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams) { Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams); return getTouchInNativeCoordinates(idx, event, udfpsOverlayParams, true); } /** * Gets the touch in native coordinates. * * Optionally map the touch to portrait mode if the device is in landscape mode. * * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @param rotateToPortrait Whether to rotate the touch to portrait orientation. * @return The mapped touch event. */ public Point getTouchInNativeCoordinates(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams, boolean rotateToPortrait) { Point touch; if (rotateToPortrait) { touch = getPortraitTouch(idx, event, udfpsOverlayParams); } else { touch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx)); } // Scale the coordinates to native resolution. float scale = udfpsOverlayParams.getScaleFactor(); portraitTouch.x = (int) (portraitTouch.x / scale); portraitTouch.y = (int) (portraitTouch.y / scale); return portraitTouch; touch.x = (int) (touch.x / scale); touch.y = (int) (touch.y / scale); return touch; } /** * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @return Whether the touch event is within sensor area. * @return Whether the touch event (that needs to be rotated to portrait) is within sensor area. */ public boolean isWithinSensorArea(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams) { Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams); return udfpsOverlayParams.getSensorBounds().contains(portraitTouch.x, portraitTouch.y); return isWithinSensorArea(idx, event, udfpsOverlayParams, true); } /** * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @param rotateTouchToPortrait Whether to rotate the touch coordinates to portrait. * @return Whether the touch event is within sensor area. */ public boolean isWithinSensorArea(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams, boolean rotateTouchToPortrait) { Point touch; if (rotateTouchToPortrait) { touch = getPortraitTouch(idx, event, udfpsOverlayParams); } else { touch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx)); } return udfpsOverlayParams.getSensorBounds().contains(touch.x, touch.y); } /** * This function computes the angle of touch relative to the sensor, rotated to portrait, * and maps the angle to a list of help messages which are announced if accessibility is * enabled. * * @return announcement string */ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context, int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) { return onTouchOutsideOfSensorArea(touchExplorationEnabled, context, scaledTouchX, scaledTouchY, udfpsOverlayParams, true); } /** * This function computes the angle of touch relative to the sensor and maps the angle to a list * of help messages which are announced if accessibility is enabled. * * @return Whether the announcing string is null * @return announcement string */ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context, int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) { int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams, boolean touchRotatedToPortrait) { if (!touchExplorationEnabled) { return null; } Loading @@ -116,7 +169,8 @@ public class UdfpsUtils { scaledTouchY, scaledSensorX, scaledSensorY, udfpsOverlayParams.getRotation() udfpsOverlayParams.getRotation(), touchRotatedToPortrait ); Log.v(TAG, "Announcing touch outside : $theStr"); return theStr; Loading @@ -132,7 +186,7 @@ public class UdfpsUtils { * touchHints[1] = "Move Fingerprint down" And so on. */ private String onTouchOutsideOfSensorAreaImpl(String[] touchHints, float touchX, float touchY, float sensorX, float sensorY, int rotation) { float touchY, float sensorX, float sensorY, int rotation, boolean rotatedToPortrait) { float xRelativeToSensor = touchX - sensorX; // Touch coordinates are with respect to the upper left corner, so reverse // this calculation Loading @@ -153,6 +207,7 @@ public class UdfpsUtils { int index = (int) ((degrees + halfBucketDegrees) % 360 / degreesPerBucket); index %= touchHints.length; if (rotatedToPortrait) { // A rotation of 90 degrees corresponds to increasing the index by 1. if (rotation == Surface.ROTATION_90) { index = (index + 1) % touchHints.length; Loading @@ -160,6 +215,8 @@ public class UdfpsUtils { if (rotation == Surface.ROTATION_270) { index = (index + 3) % touchHints.length; } } return touchHints[index]; } Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +15 −10 Original line number Diff line number Diff line Loading @@ -400,10 +400,15 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (!mOverlayParams.equals(overlayParams)) { mOverlayParams = overlayParams; final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always necessary to re-create the overlay's window with // new LayoutParams. If the overlay needs to be shown, this will re-create and show the if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mOverlay != null && mOverlay.getRequestReason() == REASON_AUTH_KEYGUARD) { mOverlay.updateOverlayParams(mOverlayParams); } } else { final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always to re-create the overlay's window with new // LayoutParams. If the overlay needs to be shown, this will re-create and show the // overlay with the updated LayoutParams. Otherwise, the overlay will remain hidden. redrawOverlay(); if (wasShowingAlternateBouncer) { Loading @@ -411,6 +416,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } } } // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this. public void setAuthControllerUpdateUdfpsLocation(@Nullable Runnable r) { Loading Loading @@ -850,7 +856,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { mOverlay = null; mOrientationListener.disable(); } private void unconfigureDisplay(View view) { Loading @@ -859,7 +864,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mUdfpsDisplayMode != null) { mUdfpsDisplayMode.disable(null); // beverlt mUdfpsDisplayMode.disable(null); } } else { if (view != null) { Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +9 −0 Original line number Diff line number Diff line Loading @@ -318,6 +318,15 @@ class UdfpsControllerOverlay @JvmOverloads constructor( addViewRunnable = null } fun updateOverlayParams(updatedOverlayParams: UdfpsOverlayParams) { DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode() overlayParams = updatedOverlayParams sensorBounds = updatedOverlayParams.sensorBounds getTouchOverlay()?.let { windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null)) } } fun inflateUdfpsAnimation( view: UdfpsView, controller: UdfpsController Loading packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.biometrics.domain.interactor import android.content.Context import android.graphics.Rect import android.hardware.biometrics.SensorLocationInternal import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.biometrics.shared.model.SensorLocation Loading @@ -43,6 +44,7 @@ constructor( repository: FingerprintPropertyRepository, configurationInteractor: ConfigurationInteractor, displayStateInteractor: DisplayStateInteractor, udfpsOverlayInteractor: UdfpsOverlayInteractor, ) { val propertiesInitialized: StateFlow<Boolean> = repository.propertiesInitialized val isUdfps: StateFlow<Boolean> = Loading Loading @@ -103,4 +105,13 @@ constructor( sensorLocation.scale = scale sensorLocation } /** * Sensor location for the: * - current physical display * - current screen resolution * - device's current orientation */ val udfpsSensorBounds: Flow<Rect> = udfpsOverlayInteractor.udfpsOverlayParams.map { it.sensorBounds }.distinctUntilChanged() } packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt +15 −2 Original line number Diff line number Diff line Loading @@ -54,9 +54,21 @@ abstract class UdfpsAccessibilityOverlayViewModel( fun onHoverEvent(v: View, event: MotionEvent): Boolean { val overlayParams = udfpsOverlayParams.value val scaledTouch: Point = udfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0), event, overlayParams) udfpsUtils.getTouchInNativeCoordinates( event.getPointerId(0), event, overlayParams, /* rotateToPortrait */ false ) if (!udfpsUtils.isWithinSensorArea(event.getPointerId(0), event, overlayParams)) { if ( !udfpsUtils.isWithinSensorArea( event.getPointerId(0), event, overlayParams, /* rotateTouchToPortrait */ false ) ) { // view only receives motionEvents when [visible] which requires touchExplorationEnabled val announceStr = udfpsUtils.onTouchOutsideOfSensorArea( Loading @@ -65,6 +77,7 @@ abstract class UdfpsAccessibilityOverlayViewModel( scaledTouch.x, scaledTouch.y, overlayParams, /* touchRotatedToPortrait */ false ) if (announceStr != null) { v.announceForAccessibility(announceStr) Loading Loading
packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/UdfpsUtils.java +76 −19 Original line number Diff line number Diff line Loading @@ -54,8 +54,9 @@ public class UdfpsUtils { } /** * Gets the touch in native coordinates. Map the touch to portrait mode if the device is in * landscape mode. * Gets the touch in native coordinates. * * Maps the touch to portrait mode if the device is in landscape mode. * * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. Loading @@ -64,35 +65,87 @@ public class UdfpsUtils { */ public Point getTouchInNativeCoordinates(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams) { Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams); return getTouchInNativeCoordinates(idx, event, udfpsOverlayParams, true); } /** * Gets the touch in native coordinates. * * Optionally map the touch to portrait mode if the device is in landscape mode. * * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @param rotateToPortrait Whether to rotate the touch to portrait orientation. * @return The mapped touch event. */ public Point getTouchInNativeCoordinates(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams, boolean rotateToPortrait) { Point touch; if (rotateToPortrait) { touch = getPortraitTouch(idx, event, udfpsOverlayParams); } else { touch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx)); } // Scale the coordinates to native resolution. float scale = udfpsOverlayParams.getScaleFactor(); portraitTouch.x = (int) (portraitTouch.x / scale); portraitTouch.y = (int) (portraitTouch.y / scale); return portraitTouch; touch.x = (int) (touch.x / scale); touch.y = (int) (touch.y / scale); return touch; } /** * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @return Whether the touch event is within sensor area. * @return Whether the touch event (that needs to be rotated to portrait) is within sensor area. */ public boolean isWithinSensorArea(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams) { Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams); return udfpsOverlayParams.getSensorBounds().contains(portraitTouch.x, portraitTouch.y); return isWithinSensorArea(idx, event, udfpsOverlayParams, true); } /** * @param idx The pointer identifier. * @param event The MotionEvent object containing full information about the event. * @param udfpsOverlayParams The [UdfpsOverlayParams] used. * @param rotateTouchToPortrait Whether to rotate the touch coordinates to portrait. * @return Whether the touch event is within sensor area. */ public boolean isWithinSensorArea(int idx, MotionEvent event, UdfpsOverlayParams udfpsOverlayParams, boolean rotateTouchToPortrait) { Point touch; if (rotateTouchToPortrait) { touch = getPortraitTouch(idx, event, udfpsOverlayParams); } else { touch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx)); } return udfpsOverlayParams.getSensorBounds().contains(touch.x, touch.y); } /** * This function computes the angle of touch relative to the sensor, rotated to portrait, * and maps the angle to a list of help messages which are announced if accessibility is * enabled. * * @return announcement string */ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context, int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) { return onTouchOutsideOfSensorArea(touchExplorationEnabled, context, scaledTouchX, scaledTouchY, udfpsOverlayParams, true); } /** * This function computes the angle of touch relative to the sensor and maps the angle to a list * of help messages which are announced if accessibility is enabled. * * @return Whether the announcing string is null * @return announcement string */ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context, int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) { int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams, boolean touchRotatedToPortrait) { if (!touchExplorationEnabled) { return null; } Loading @@ -116,7 +169,8 @@ public class UdfpsUtils { scaledTouchY, scaledSensorX, scaledSensorY, udfpsOverlayParams.getRotation() udfpsOverlayParams.getRotation(), touchRotatedToPortrait ); Log.v(TAG, "Announcing touch outside : $theStr"); return theStr; Loading @@ -132,7 +186,7 @@ public class UdfpsUtils { * touchHints[1] = "Move Fingerprint down" And so on. */ private String onTouchOutsideOfSensorAreaImpl(String[] touchHints, float touchX, float touchY, float sensorX, float sensorY, int rotation) { float touchY, float sensorX, float sensorY, int rotation, boolean rotatedToPortrait) { float xRelativeToSensor = touchX - sensorX; // Touch coordinates are with respect to the upper left corner, so reverse // this calculation Loading @@ -153,6 +207,7 @@ public class UdfpsUtils { int index = (int) ((degrees + halfBucketDegrees) % 360 / degreesPerBucket); index %= touchHints.length; if (rotatedToPortrait) { // A rotation of 90 degrees corresponds to increasing the index by 1. if (rotation == Surface.ROTATION_90) { index = (index + 1) % touchHints.length; Loading @@ -160,6 +215,8 @@ public class UdfpsUtils { if (rotation == Surface.ROTATION_270) { index = (index + 3) % touchHints.length; } } return touchHints[index]; } Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +15 −10 Original line number Diff line number Diff line Loading @@ -400,10 +400,15 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (!mOverlayParams.equals(overlayParams)) { mOverlayParams = overlayParams; final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always necessary to re-create the overlay's window with // new LayoutParams. If the overlay needs to be shown, this will re-create and show the if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mOverlay != null && mOverlay.getRequestReason() == REASON_AUTH_KEYGUARD) { mOverlay.updateOverlayParams(mOverlayParams); } } else { final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always to re-create the overlay's window with new // LayoutParams. If the overlay needs to be shown, this will re-create and show the // overlay with the updated LayoutParams. Otherwise, the overlay will remain hidden. redrawOverlay(); if (wasShowingAlternateBouncer) { Loading @@ -411,6 +416,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } } } // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this. public void setAuthControllerUpdateUdfpsLocation(@Nullable Runnable r) { Loading Loading @@ -850,7 +856,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { mOverlay = null; mOrientationListener.disable(); } private void unconfigureDisplay(View view) { Loading @@ -859,7 +864,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mUdfpsDisplayMode != null) { mUdfpsDisplayMode.disable(null); // beverlt mUdfpsDisplayMode.disable(null); } } else { if (view != null) { Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +9 −0 Original line number Diff line number Diff line Loading @@ -318,6 +318,15 @@ class UdfpsControllerOverlay @JvmOverloads constructor( addViewRunnable = null } fun updateOverlayParams(updatedOverlayParams: UdfpsOverlayParams) { DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode() overlayParams = updatedOverlayParams sensorBounds = updatedOverlayParams.sensorBounds getTouchOverlay()?.let { windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null)) } } fun inflateUdfpsAnimation( view: UdfpsView, controller: UdfpsController Loading
packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.biometrics.domain.interactor import android.content.Context import android.graphics.Rect import android.hardware.biometrics.SensorLocationInternal import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.biometrics.shared.model.SensorLocation Loading @@ -43,6 +44,7 @@ constructor( repository: FingerprintPropertyRepository, configurationInteractor: ConfigurationInteractor, displayStateInteractor: DisplayStateInteractor, udfpsOverlayInteractor: UdfpsOverlayInteractor, ) { val propertiesInitialized: StateFlow<Boolean> = repository.propertiesInitialized val isUdfps: StateFlow<Boolean> = Loading Loading @@ -103,4 +105,13 @@ constructor( sensorLocation.scale = scale sensorLocation } /** * Sensor location for the: * - current physical display * - current screen resolution * - device's current orientation */ val udfpsSensorBounds: Flow<Rect> = udfpsOverlayInteractor.udfpsOverlayParams.map { it.sensorBounds }.distinctUntilChanged() }
packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt +15 −2 Original line number Diff line number Diff line Loading @@ -54,9 +54,21 @@ abstract class UdfpsAccessibilityOverlayViewModel( fun onHoverEvent(v: View, event: MotionEvent): Boolean { val overlayParams = udfpsOverlayParams.value val scaledTouch: Point = udfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0), event, overlayParams) udfpsUtils.getTouchInNativeCoordinates( event.getPointerId(0), event, overlayParams, /* rotateToPortrait */ false ) if (!udfpsUtils.isWithinSensorArea(event.getPointerId(0), event, overlayParams)) { if ( !udfpsUtils.isWithinSensorArea( event.getPointerId(0), event, overlayParams, /* rotateTouchToPortrait */ false ) ) { // view only receives motionEvents when [visible] which requires touchExplorationEnabled val announceStr = udfpsUtils.onTouchOutsideOfSensorArea( Loading @@ -65,6 +77,7 @@ abstract class UdfpsAccessibilityOverlayViewModel( scaledTouch.x, scaledTouch.y, overlayParams, /* touchRotatedToPortrait */ false ) if (announceStr != null) { v.announceForAccessibility(announceStr) Loading