diff options
| author | 2023-01-13 20:12:39 +0000 | |
|---|---|---|
| committer | 2023-01-13 20:12:39 +0000 | |
| commit | fa87b00c96474288701635df6ec137dce02fce6e (patch) | |
| tree | a8113bce64fda94aff657bb00b96a7313dddf840 | |
| parent | d6fac7a4875852c34118f54a8c012984b35473dc (diff) | |
| parent | e2123df927fe73b0492fa3f8f3fcee0588210a2e (diff) | |
Merge "Add multitouch to new touch architecture" into tm-qpr-dev
4 files changed, 283 insertions, 123 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt index 62bedc627b07..48d48450e13e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt @@ -26,28 +26,28 @@ data class NormalizedTouchData( * Value obtained from [MotionEvent.getPointerId], or [MotionEvent.INVALID_POINTER_ID] if the ID * is not available. */ - val pointerId: Int, + val pointerId: Int = MotionEvent.INVALID_POINTER_ID, /** [MotionEvent.getRawX] mapped to natural orientation and native resolution. */ - val x: Float, + val x: Float = 0f, /** [MotionEvent.getRawY] mapped to natural orientation and native resolution. */ - val y: Float, + val y: Float = 0f, /** [MotionEvent.getTouchMinor] mapped to natural orientation and native resolution. */ - val minor: Float, + val minor: Float = 0f, /** [MotionEvent.getTouchMajor] mapped to natural orientation and native resolution. */ - val major: Float, + val major: Float = 0f, /** [MotionEvent.getOrientation] mapped to natural orientation. */ - val orientation: Float, + val orientation: Float = 0f, /** [MotionEvent.getEventTime]. */ - val time: Long, + val time: Long = 0, /** [MotionEvent.getDownTime]. */ - val gestureStart: Long, + val gestureStart: Long = 0, ) { /** diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt index 693f64a1f93d..3a01cd502929 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt @@ -43,74 +43,72 @@ class SinglePointerTouchProcessor @Inject constructor(val overlapDetector: Overl ): TouchProcessorResult { fun preprocess(): PreprocessedTouch { - // TODO(b/253085297): Add multitouch support. pointerIndex can be > 0 for ACTION_MOVE. - val pointerIndex = 0 - val touchData = event.normalize(pointerIndex, overlayParams) - val isGoodOverlap = - overlapDetector.isGoodOverlap(touchData, overlayParams.nativeSensorBounds) - return PreprocessedTouch(touchData, previousPointerOnSensorId, isGoodOverlap) + val touchData = List(event.pointerCount) { event.normalize(it, overlayParams) } + val pointersOnSensor = + touchData + .filter { overlapDetector.isGoodOverlap(it, overlayParams.nativeSensorBounds) } + .map { it.pointerId } + return PreprocessedTouch(touchData, previousPointerOnSensorId, pointersOnSensor) } return when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> processActionDown(preprocess()) + MotionEvent.ACTION_DOWN, + MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_MOVE -> processActionMove(preprocess()) - MotionEvent.ACTION_UP -> processActionUp(preprocess()) - MotionEvent.ACTION_CANCEL -> - processActionCancel(event.normalize(pointerIndex = 0, overlayParams)) + MotionEvent.ACTION_UP, + MotionEvent.ACTION_POINTER_UP -> + processActionUp(preprocess(), event.getPointerId(event.actionIndex)) + MotionEvent.ACTION_CANCEL -> processActionCancel(NormalizedTouchData()) else -> Failure("Unsupported MotionEvent." + MotionEvent.actionToString(event.actionMasked)) } } } +/** + * [data] contains a list of NormalizedTouchData for pointers in the motionEvent ordered by + * pointerIndex + * + * [previousPointerOnSensorId] the pointerId of the previous pointer on the sensor, + * [MotionEvent.INVALID_POINTER_ID] if none + * + * [pointersOnSensor] contains a list of ids of pointers on the sensor + */ private data class PreprocessedTouch( - val data: NormalizedTouchData, + val data: List<NormalizedTouchData>, val previousPointerOnSensorId: Int, - val isGoodOverlap: Boolean, + val pointersOnSensor: List<Int>, ) -private fun processActionDown(touch: PreprocessedTouch): TouchProcessorResult { - return if (touch.isGoodOverlap) { - ProcessedTouch(InteractionEvent.DOWN, pointerOnSensorId = touch.data.pointerId, touch.data) - } else { - val event = - if (touch.data.pointerId == touch.previousPointerOnSensorId) { - InteractionEvent.UP - } else { - InteractionEvent.UNCHANGED - } - ProcessedTouch(event, pointerOnSensorId = INVALID_POINTER_ID, touch.data) - } -} - private fun processActionMove(touch: PreprocessedTouch): TouchProcessorResult { val hadPointerOnSensor = touch.previousPointerOnSensorId != INVALID_POINTER_ID - val interactionEvent = - when { - touch.isGoodOverlap && !hadPointerOnSensor -> InteractionEvent.DOWN - !touch.isGoodOverlap && hadPointerOnSensor -> InteractionEvent.UP - else -> InteractionEvent.UNCHANGED - } - val pointerOnSensorId = - when (interactionEvent) { - InteractionEvent.UNCHANGED -> touch.previousPointerOnSensorId - InteractionEvent.DOWN -> touch.data.pointerId - else -> INVALID_POINTER_ID - } - return ProcessedTouch(interactionEvent, pointerOnSensorId, touch.data) + val hasPointerOnSensor = touch.pointersOnSensor.isNotEmpty() + val pointerOnSensorId = touch.pointersOnSensor.firstOrNull() ?: INVALID_POINTER_ID + + return if (!hadPointerOnSensor && hasPointerOnSensor) { + val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData() + ProcessedTouch(InteractionEvent.DOWN, data.pointerId, data) + } else if (hadPointerOnSensor && !hasPointerOnSensor) { + ProcessedTouch(InteractionEvent.UP, INVALID_POINTER_ID, NormalizedTouchData()) + } else { + val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData() + ProcessedTouch(InteractionEvent.UNCHANGED, pointerOnSensorId, data) + } } -private fun processActionUp(touch: PreprocessedTouch): TouchProcessorResult { - return if (touch.isGoodOverlap) { - ProcessedTouch(InteractionEvent.UP, pointerOnSensorId = INVALID_POINTER_ID, touch.data) +private fun processActionUp(touch: PreprocessedTouch, actionId: Int): TouchProcessorResult { + // Finger lifted and it was the only finger on the sensor + return if (touch.pointersOnSensor.size == 1 && touch.pointersOnSensor.contains(actionId)) { + ProcessedTouch( + InteractionEvent.UP, + pointerOnSensorId = INVALID_POINTER_ID, + NormalizedTouchData() + ) } else { - val event = - if (touch.previousPointerOnSensorId != INVALID_POINTER_ID) { - InteractionEvent.UP - } else { - InteractionEvent.UNCHANGED - } - ProcessedTouch(event, pointerOnSensorId = INVALID_POINTER_ID, touch.data) + // Pick new pointerOnSensor that's not the finger that was lifted + val pointerOnSensorId = touch.pointersOnSensor.find { it != actionId } ?: INVALID_POINTER_ID + val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData() + ProcessedTouch(InteractionEvent.UNCHANGED, data.pointerId, data) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt index 56043e306c16..34ddf795c7e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt @@ -39,7 +39,8 @@ class SinglePointerTouchProcessorTest(val testCase: TestCase) : SysuiTestCase() @Test fun processTouch() { - overlapDetector.shouldReturn = testCase.isGoodOverlap + overlapDetector.shouldReturn = + testCase.currentPointers.associate { pointer -> pointer.id to pointer.onSensor } val actual = underTest.processTouch( @@ -56,7 +57,7 @@ class SinglePointerTouchProcessorTest(val testCase: TestCase) : SysuiTestCase() data class TestCase( val event: MotionEvent, - val isGoodOverlap: Boolean, + val currentPointers: List<TestPointer>, val previousPointerOnSensorId: Int, val overlayParams: UdfpsOverlayParams, val expected: TouchProcessorResult, @@ -91,28 +92,21 @@ class SinglePointerTouchProcessorTest(val testCase: TestCase) : SysuiTestCase() genPositiveTestCases( motionEventAction = MotionEvent.ACTION_DOWN, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = true, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.DOWN, - expectedPointerOnSensorId = POINTER_ID, - ), - genPositiveTestCases( - motionEventAction = MotionEvent.ACTION_DOWN, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = true, - expectedInteractionEvent = InteractionEvent.DOWN, - expectedPointerOnSensorId = POINTER_ID, + expectedPointerOnSensorId = POINTER_ID_1, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_DOWN, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = false, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.UNCHANGED, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_DOWN, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = false, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.UP, expectedPointerOnSensorId = INVALID_POINTER_ID, ), @@ -120,109 +114,226 @@ class SinglePointerTouchProcessorTest(val testCase: TestCase) : SysuiTestCase() genPositiveTestCases( motionEventAction = MotionEvent.ACTION_MOVE, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = true, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.DOWN, - expectedPointerOnSensorId = POINTER_ID, + expectedPointerOnSensorId = POINTER_ID_1, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_MOVE, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = true, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.UNCHANGED, - expectedPointerOnSensorId = POINTER_ID, + expectedPointerOnSensorId = POINTER_ID_1, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_MOVE, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = false, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.UNCHANGED, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_MOVE, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = false, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.UP, expectedPointerOnSensorId = INVALID_POINTER_ID, ), + genPositiveTestCases( + motionEventAction = MotionEvent.ACTION_MOVE, + previousPointerOnSensorId = INVALID_POINTER_ID, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = true) + ), + expectedInteractionEvent = InteractionEvent.DOWN, + expectedPointerOnSensorId = POINTER_ID_2, + ), + genPositiveTestCases( + motionEventAction = MotionEvent.ACTION_MOVE, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = true) + ), + expectedInteractionEvent = InteractionEvent.UNCHANGED, + expectedPointerOnSensorId = POINTER_ID_2, + ), // MotionEvent.ACTION_UP genPositiveTestCases( motionEventAction = MotionEvent.ACTION_UP, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = true, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.UP, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_UP, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = true, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.UP, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_UP, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = false, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.UNCHANGED, expectedPointerOnSensorId = INVALID_POINTER_ID, ), - genPositiveTestCases( - motionEventAction = MotionEvent.ACTION_UP, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = false, - expectedInteractionEvent = InteractionEvent.UP, - expectedPointerOnSensorId = INVALID_POINTER_ID, - ), // MotionEvent.ACTION_CANCEL genPositiveTestCases( motionEventAction = MotionEvent.ACTION_CANCEL, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = true, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.CANCEL, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_CANCEL, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = true, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)), expectedInteractionEvent = InteractionEvent.CANCEL, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_CANCEL, previousPointerOnSensorId = INVALID_POINTER_ID, - isGoodOverlap = false, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.CANCEL, expectedPointerOnSensorId = INVALID_POINTER_ID, ), genPositiveTestCases( motionEventAction = MotionEvent.ACTION_CANCEL, - previousPointerOnSensorId = POINTER_ID, - isGoodOverlap = false, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)), expectedInteractionEvent = InteractionEvent.CANCEL, expectedPointerOnSensorId = INVALID_POINTER_ID, ), + // MotionEvent.ACTION_POINTER_DOWN + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_DOWN + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = INVALID_POINTER_ID, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = true), + TestPointer(id = POINTER_ID_2, onSensor = false) + ), + expectedInteractionEvent = InteractionEvent.DOWN, + expectedPointerOnSensorId = POINTER_ID_1, + ), + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_DOWN + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = INVALID_POINTER_ID, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = true) + ), + expectedInteractionEvent = InteractionEvent.DOWN, + expectedPointerOnSensorId = POINTER_ID_2 + ), + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_DOWN + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = true), + TestPointer(id = POINTER_ID_2, onSensor = false) + ), + expectedInteractionEvent = InteractionEvent.UNCHANGED, + expectedPointerOnSensorId = POINTER_ID_1, + ), + // MotionEvent.ACTION_POINTER_UP + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_UP + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = INVALID_POINTER_ID, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = false) + ), + expectedInteractionEvent = InteractionEvent.UNCHANGED, + expectedPointerOnSensorId = INVALID_POINTER_ID + ), + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_UP + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = POINTER_ID_2, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = true) + ), + expectedInteractionEvent = InteractionEvent.UP, + expectedPointerOnSensorId = INVALID_POINTER_ID + ), + genPositiveTestCases( + motionEventAction = MotionEvent.ACTION_POINTER_UP, + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = true), + TestPointer(id = POINTER_ID_2, onSensor = false) + ), + expectedInteractionEvent = InteractionEvent.UP, + expectedPointerOnSensorId = INVALID_POINTER_ID + ), + genPositiveTestCases( + motionEventAction = + MotionEvent.ACTION_POINTER_UP + + (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), + previousPointerOnSensorId = POINTER_ID_1, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = true), + TestPointer(id = POINTER_ID_2, onSensor = false) + ), + expectedInteractionEvent = InteractionEvent.UNCHANGED, + expectedPointerOnSensorId = POINTER_ID_1 + ), + genPositiveTestCases( + motionEventAction = MotionEvent.ACTION_POINTER_UP, + previousPointerOnSensorId = POINTER_ID_2, + currentPointers = + listOf( + TestPointer(id = POINTER_ID_1, onSensor = false), + TestPointer(id = POINTER_ID_2, onSensor = true) + ), + expectedInteractionEvent = InteractionEvent.UNCHANGED, + expectedPointerOnSensorId = POINTER_ID_2 + ) ) .flatten() + listOf( - // Unsupported MotionEvent actions. - genTestCasesForUnsupportedAction(MotionEvent.ACTION_POINTER_DOWN), - genTestCasesForUnsupportedAction(MotionEvent.ACTION_POINTER_UP), genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_ENTER), genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_MOVE), - genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_EXIT), + genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_EXIT) ) .flatten() } } +data class TestPointer(val id: Int, val onSensor: Boolean) + /* Display dimensions in native resolution and natural orientation. */ private const val ROTATION_0_NATIVE_DISPLAY_WIDTH = 400 private const val ROTATION_0_NATIVE_DISPLAY_HEIGHT = 600 /* Placeholder touch parameters. */ -private const val POINTER_ID = 42 +private const val POINTER_ID_1 = 42 +private const val POINTER_ID_2 = 43 private const val NATIVE_MINOR = 2.71828f private const val NATIVE_MAJOR = 3.14f private const val ORIENTATION = 1.2345f @@ -325,7 +436,7 @@ private val ROTATION_270_INPUTS = private val MOTION_EVENT = obtainMotionEvent( action = 0, - pointerId = POINTER_ID, + pointerId = POINTER_ID_1, x = 0f, y = 0f, minor = 0f, @@ -338,7 +449,7 @@ private val MOTION_EVENT = /* Template [NormalizedTouchData]. */ private val NORMALIZED_TOUCH_DATA = NormalizedTouchData( - POINTER_ID, + POINTER_ID_1, x = 0f, y = 0f, NATIVE_MINOR, @@ -384,7 +495,7 @@ private data class OrientationBasedInputs( private fun genPositiveTestCases( motionEventAction: Int, previousPointerOnSensorId: Int, - isGoodOverlap: Boolean, + currentPointers: List<TestPointer>, expectedInteractionEvent: InteractionEvent, expectedPointerOnSensorId: Int ): List<SinglePointerTouchProcessorTest.TestCase> { @@ -399,22 +510,47 @@ private fun genPositiveTestCases( return scaleFactors.flatMap { scaleFactor -> orientations.map { orientation -> val overlayParams = orientation.toOverlayParams(scaleFactor) - val nativeX = orientation.getNativeX(isGoodOverlap) - val nativeY = orientation.getNativeY(isGoodOverlap) + + val pointerProperties = + currentPointers + .map { pointer -> + val pp = MotionEvent.PointerProperties() + pp.id = pointer.id + pp + } + .toList() + + val pointerCoords = + currentPointers + .map { pointer -> + val pc = MotionEvent.PointerCoords() + pc.x = orientation.getNativeX(pointer.onSensor) * scaleFactor + pc.y = orientation.getNativeY(pointer.onSensor) * scaleFactor + pc.touchMinor = NATIVE_MINOR * scaleFactor + pc.touchMajor = NATIVE_MAJOR * scaleFactor + pc.orientation = orientation.nativeOrientation + pc + } + .toList() + val event = MOTION_EVENT.copy( action = motionEventAction, - x = nativeX * scaleFactor, - y = nativeY * scaleFactor, - minor = NATIVE_MINOR * scaleFactor, - major = NATIVE_MAJOR * scaleFactor, - orientation = orientation.nativeOrientation + pointerProperties = pointerProperties, + pointerCoords = pointerCoords ) + val expectedTouchData = - NORMALIZED_TOUCH_DATA.copy( - x = ROTATION_0_INPUTS.getNativeX(isGoodOverlap), - y = ROTATION_0_INPUTS.getNativeY(isGoodOverlap), - ) + if (expectedPointerOnSensorId != INVALID_POINTER_ID) { + NORMALIZED_TOUCH_DATA.copy( + pointerId = expectedPointerOnSensorId, + x = ROTATION_0_INPUTS.getNativeX(isWithinSensor = true), + y = ROTATION_0_INPUTS.getNativeY(isWithinSensor = true) + ) + } else { + NormalizedTouchData() + } + val expected = TouchProcessorResult.ProcessedTouch( event = expectedInteractionEvent, @@ -423,7 +559,7 @@ private fun genPositiveTestCases( ) SinglePointerTouchProcessorTest.TestCase( event = event, - isGoodOverlap = isGoodOverlap, + currentPointers = currentPointers, previousPointerOnSensorId = previousPointerOnSensorId, overlayParams = overlayParams, expected = expected, @@ -436,7 +572,7 @@ private fun genTestCasesForUnsupportedAction( motionEventAction: Int ): List<SinglePointerTouchProcessorTest.TestCase> { val isGoodOverlap = true - val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID) + val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID_1) return previousPointerOnSensorIds.map { previousPointerOnSensorId -> val overlayParams = ROTATION_0_INPUTS.toOverlayParams(scaleFactor = 1f) val nativeX = ROTATION_0_INPUTS.getNativeX(isGoodOverlap) @@ -451,7 +587,7 @@ private fun genTestCasesForUnsupportedAction( ) SinglePointerTouchProcessorTest.TestCase( event = event, - isGoodOverlap = isGoodOverlap, + currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = isGoodOverlap)), previousPointerOnSensorId = previousPointerOnSensorId, overlayParams = overlayParams, expected = TouchProcessorResult.Failure(), @@ -478,13 +614,23 @@ private fun obtainMotionEvent( pc.touchMinor = minor pc.touchMajor = major pc.orientation = orientation + return obtainMotionEvent(action, arrayOf(pp), arrayOf(pc), time, gestureStart) +} + +private fun obtainMotionEvent( + action: Int, + pointerProperties: Array<MotionEvent.PointerProperties>, + pointerCoords: Array<MotionEvent.PointerCoords>, + time: Long, + gestureStart: Long, +): MotionEvent { return MotionEvent.obtain( gestureStart /* downTime */, time /* eventTime */, action /* action */, - 1 /* pointerCount */, - arrayOf(pp) /* pointerProperties */, - arrayOf(pc) /* pointerCoords */, + pointerCoords.size /* pointerCount */, + pointerProperties /* pointerProperties */, + pointerCoords /* pointerCoords */, 0 /* metaState */, 0 /* buttonState */, 1f /* xPrecision */, @@ -508,4 +654,19 @@ private fun MotionEvent.copy( gestureStart: Long = this.downTime, ) = obtainMotionEvent(action, pointerId, x, y, minor, major, orientation, time, gestureStart) +private fun MotionEvent.copy( + action: Int = this.action, + pointerProperties: List<MotionEvent.PointerProperties>, + pointerCoords: List<MotionEvent.PointerCoords>, + time: Long = this.eventTime, + gestureStart: Long = this.downTime +) = + obtainMotionEvent( + action, + pointerProperties.toTypedArray(), + pointerCoords.toTypedArray(), + time, + gestureStart + ) + private fun Rect.scaled(scaleFactor: Float) = Rect(this).apply { scale(scaleFactor) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt index 8176dd07b84a..1bdee3667d04 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt @@ -19,9 +19,10 @@ package com.android.systemui.biometrics.udfps import android.graphics.Rect class FakeOverlapDetector : OverlapDetector { - var shouldReturn: Boolean = false + var shouldReturn: Map<Int, Boolean> = mapOf() override fun isGoodOverlap(touchData: NormalizedTouchData, nativeSensorBounds: Rect): Boolean { - return shouldReturn + return shouldReturn[touchData.pointerId] + ?: error("Unexpected PointerId not declared in TestCase currentPointers") } } |