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

Commit 0f05bc7b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update the usage of receiveFinishedSignal -- try 2" into sc-dev

parents b7e0678d ec393c80
Loading
Loading
Loading
Loading
+11 −16
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@

#include "core_jni_helpers.h"

using android::base::Result;

namespace android {

// Log debug messages about the dispatch cycle.
@@ -197,16 +199,9 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
    ScopedLocalRef<jobject> senderObj(env, NULL);
    bool skipCallbacks = false;
    for (;;) {
        uint32_t publishedSeq;
        bool handled;
        std::function<void(uint32_t seq, bool handled, nsecs_t consumeTime)> callback =
                [&publishedSeq, &handled](uint32_t inSeq, bool inHandled,
                                          nsecs_t inConsumeTime) -> void {
            publishedSeq = inSeq;
            handled = inHandled;
        };
        status_t status = mInputPublisher.receiveFinishedSignal(callback);
        if (status) {
        Result<InputPublisher::Finished> result = mInputPublisher.receiveFinishedSignal();
        if (!result.ok()) {
            const status_t status = result.error().code();
            if (status == WOULD_BLOCK) {
                return OK;
            }
@@ -215,7 +210,7 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
            return status;
        }

        auto it = mPublishedSeqMap.find(publishedSeq);
        auto it = mPublishedSeqMap.find(result->seq);
        if (it == mPublishedSeqMap.end()) {
            continue;
        }
@@ -226,7 +221,7 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
        if (kDebugDispatchCycle) {
            ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
                  "pendingEvents=%zu.",
                    getInputChannelName().c_str(), seq, handled ? "true" : "false",
                  getInputChannelName().c_str(), seq, result->handled ? "true" : "false",
                  mPublishedSeqMap.size());
        }

@@ -242,7 +237,7 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {

            env->CallVoidMethod(senderObj.get(),
                                gInputEventSenderClassInfo.dispatchInputEventFinished,
                    jint(seq), jboolean(handled));
                                static_cast<jint>(seq), static_cast<jboolean>(result->handled));
            if (env->ExceptionCheck()) {
                ALOGE("Exception dispatching finished signal.");
                skipCallbacks = true;
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ fun createMotionEvent(action: Int, eventTime: Long, source: Int): MotionEvent {
            xPrecision, yPrecision, deviceId, edgeFlags, source, displayId)
}

fun createKeyEvent(action: Int, eventTime: Long): KeyEvent {
private fun createKeyEvent(action: Int, eventTime: Long): KeyEvent {
    val code = KeyEvent.KEYCODE_A
    val repeat = 0
    return KeyEvent(eventTime, eventTime, action, code, repeat)
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.test.input

import android.os.HandlerThread
import android.os.Looper
import android.view.InputChannel
import android.view.InputEvent
import android.view.InputEventReceiver
import android.view.InputEventSender
import android.view.KeyEvent
import android.view.MotionEvent
import java.util.concurrent.CountDownLatch
import org.junit.Assert.assertEquals
import org.junit.After
import org.junit.Before
import org.junit.Test

private fun assertKeyEvent(expected: KeyEvent, received: KeyEvent) {
    assertEquals(expected.action, received.action)
    assertEquals(expected.deviceId, received.deviceId)
    assertEquals(expected.downTime, received.downTime)
    assertEquals(expected.eventTime, received.eventTime)
    assertEquals(expected.keyCode, received.keyCode)
    assertEquals(expected.scanCode, received.scanCode)
    assertEquals(expected.repeatCount, received.repeatCount)
    assertEquals(expected.metaState, received.metaState)
    assertEquals(expected.flags, received.flags)
    assertEquals(expected.source, received.source)
    assertEquals(expected.displayId, received.displayId)
}

class TestInputEventReceiver(channel: InputChannel, looper: Looper) :
        InputEventReceiver(channel, looper) {
    companion object {
        const val TAG = "TestInputEventReceiver"
    }

    var lastEvent: InputEvent? = null

    override fun onInputEvent(event: InputEvent) {
        lastEvent = when (event) {
            is KeyEvent -> KeyEvent.obtain(event)
            is MotionEvent -> MotionEvent.obtain(event)
            else -> throw Exception("Received $event is neither a key nor a motion")
        }
        finishInputEvent(event, true /*handled*/)
    }
}

class TestInputEventSender(channel: InputChannel, looper: Looper) :
        InputEventSender(channel, looper) {
    companion object {
        const val TAG = "TestInputEventSender"
    }
    data class FinishedResult(val seq: Int, val handled: Boolean)

    private var mFinishedSignal = CountDownLatch(1)
    override fun onInputEventFinished(seq: Int, handled: Boolean) {
        finishedResult = FinishedResult(seq, handled)
        mFinishedSignal.countDown()
    }
    lateinit var finishedResult: FinishedResult

    fun waitForFinish() {
        mFinishedSignal.await()
        mFinishedSignal = CountDownLatch(1) // Ready for next event
    }
}

class InputEventSenderAndReceiverTest {
    companion object {
        private const val TAG = "InputEventSenderAndReceiverTest"
    }
    private val mHandlerThread = HandlerThread("Process input events")
    private lateinit var mReceiver: TestInputEventReceiver
    private lateinit var mSender: TestInputEventSender

    @Before
    fun setUp() {
        val channels = InputChannel.openInputChannelPair("TestChannel")
        mHandlerThread.start()

        val looper = mHandlerThread.getLooper()
        mSender = TestInputEventSender(channels[0], looper)
        mReceiver = TestInputEventReceiver(channels[1], looper)
    }

    @After
    fun tearDown() {
        mHandlerThread.quitSafely()
    }

    @Test
    fun testSendAndReceiveKey() {
        val key = KeyEvent(1 /*downTime*/, 1 /*eventTime*/, KeyEvent.ACTION_DOWN,
                KeyEvent.KEYCODE_A, 0 /*repeat*/)
        val seq = 10
        mSender.sendInputEvent(seq, key)
        mSender.waitForFinish()

        // Check receiver
        assertKeyEvent(key, mReceiver.lastEvent!! as KeyEvent)

        // Check sender
        assertEquals(seq, mSender.finishedResult.seq)
        assertEquals(true, mSender.finishedResult.handled)
    }
}