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

Commit f6a293ad authored by Austin Delgado's avatar Austin Delgado Committed by Automerger Merge Worker
Browse files

Merge "Add multitouch to new touch architecture" into tm-qpr-dev am: fa87b00c

parents 7348bc84 fa87b00c
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -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,
) {

    /**
+47 −49
Original line number Diff line number Diff line
@@ -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
    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)
    }
    return ProcessedTouch(interactionEvent, pointerOnSensorId, touch.data)
}

private fun processActionUp(touch: PreprocessedTouch): TouchProcessorResult {
    return if (touch.isGoodOverlap) {
        ProcessedTouch(InteractionEvent.UP, pointerOnSensorId = INVALID_POINTER_ID, touch.data)
    } else {
        val event =
            if (touch.previousPointerOnSensorId != INVALID_POINTER_ID) {
                InteractionEvent.UP
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 {
                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)
    }
}

+225 −64

File changed.

Preview size limit exceeded, changes collapsed.

+3 −2
Original line number Diff line number Diff line
@@ -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")
    }
}