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

Commit e9bc9d12 authored by Chen Bai's avatar Chen Bai
Browse files

clobber wom: add onKeyUp callback to SingleKeyRule

- Add a new callback, onKeyUp, in SingleKeyRule for key-up events
that are not processed by long/very-long press.

See comment in go/wear-1pg-button-clobber for the original design idea.

Test: atest WmTests:SingleKeyGestureTests
BUG: 296311571
Change-Id: I8c4907aadee94801a68ad794911a88c2293d49a4
parent a8c34f8d
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ public final class SingleKeyGestureDetector {
    private static final int MSG_KEY_LONG_PRESS = 0;
    private static final int MSG_KEY_VERY_LONG_PRESS = 1;
    private static final int MSG_KEY_DELAYED_PRESS = 2;
    private static final int MSG_KEY_UP = 3;

    private int mKeyPressCounter;
    private boolean mBeganFromNonInteractive = false;
@@ -144,6 +145,13 @@ public final class SingleKeyGestureDetector {
         *  Callback when very long press has been detected.
         */
        void onVeryLongPress(long eventTime) {}
        /**
         * Callback executed upon each key up event that hasn't been processed by long press.
         *
         * @param eventTime the timestamp of this event.
         * @param pressCount the number of presses detected leading up to this key up event.
         */
        void onKeyUp(long eventTime, int pressCount) {}

        @Override
        public String toString() {
@@ -330,6 +338,13 @@ public final class SingleKeyGestureDetector {
        }

        if (event.getKeyCode() == mActiveRule.mKeyCode) {
            // key-up action should always be triggered if not processed by long press.
            Message msgKeyUp =
                    mHandler.obtainMessage(
                            MSG_KEY_UP, mActiveRule.mKeyCode, mKeyPressCounter, mActiveRule);
            msgKeyUp.setAsynchronous(true);
            mHandler.sendMessage(msgKeyUp);

            // Directly trigger short press when max count is 1.
            if (mActiveRule.getMaxMultiPressCount() == 1) {
                if (DEBUG) {
@@ -417,6 +432,12 @@ public final class SingleKeyGestureDetector {
            final int keyCode = msg.arg1;
            final int pressCount = msg.arg2;
            switch(msg.what) {
                case MSG_KEY_UP:
                    if (DEBUG) {
                        Log.i(TAG, "Detect key up " + KeyEvent.keyCodeToString(keyCode));
                    }
                    rule.onKeyUp(mLastDownTime, pressCount);
                    break;
                case MSG_KEY_LONG_PRESS:
                    if (DEBUG) {
                        Log.i(TAG, "Detect long press " + KeyEvent.keyCodeToString(keyCode));
+66 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.app.Instrumentation;
@@ -38,7 +39,9 @@ import android.view.KeyEvent;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
@@ -57,6 +60,7 @@ public class SingleKeyGestureTests {
    private CountDownLatch mLongPressed = new CountDownLatch(1);
    private CountDownLatch mVeryLongPressed = new CountDownLatch(1);
    private CountDownLatch mMultiPressed = new CountDownLatch(1);
    private BlockingQueue<KeyUpData> mKeyUpQueue = new LinkedBlockingQueue<>();

    private final Instrumentation mInstrumentation = getInstrumentation();
    private final Context mContext = mInstrumentation.getTargetContext();
@@ -134,6 +138,11 @@ public class SingleKeyGestureTests {
                        assertTrue(mMaxMultiPressCount >= count);
                        assertEquals(mExpectedMultiPressCount, count);
                    }

                    @Override
                    void onKeyUp(long eventTime, int multiPressCount) {
                        mKeyUpQueue.add(new KeyUpData(KEYCODE_POWER, multiPressCount));
                    }
                });

        mDetector.addRule(
@@ -166,6 +175,11 @@ public class SingleKeyGestureTests {
                        assertEquals(mExpectedMultiPressCount, count);
                    }

                    @Override
                    void onKeyUp(long eventTime, int multiPressCount) {
                        mKeyUpQueue.add(new KeyUpData(KEYCODE_BACK, multiPressCount));
                    }

                    @Override
                    void onLongPress(long downTime) {
                        mLongPressed.countDown();
@@ -173,6 +187,16 @@ public class SingleKeyGestureTests {
                });
    }

    private static class KeyUpData {
        public final int keyCode;
        public final int pressCount;

        KeyUpData(int keyCode, int pressCount) {
            this.keyCode = keyCode;
            this.pressCount = pressCount;
        }
    }

    private void pressKey(int keyCode, long pressTime) {
        pressKey(keyCode, pressTime, true /* interactive */);
    }
@@ -249,6 +273,21 @@ public class SingleKeyGestureTests {
        assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
    }

    @Test
    public void testOnKeyUp() throws InterruptedException {
        pressKey(KEYCODE_POWER, 0 /* pressTime */);

        verifyKeyUpData(KEYCODE_POWER, 1 /* expectedMultiPressCount */);
    }

    private void verifyKeyUpData(int expectedKeyCode, int expectedMultiPressCount)
            throws InterruptedException {
        KeyUpData keyUpData = mKeyUpQueue.poll(mWaitTimeout, TimeUnit.MILLISECONDS);
        assertNotNull(keyUpData);
        assertEquals(expectedKeyCode, keyUpData.keyCode);
        assertEquals(expectedMultiPressCount, keyUpData.pressCount);
    }

    @Test
    public void testNonInteractive() throws InterruptedException {
        // Disallow short press behavior from non interactive.
@@ -313,6 +352,33 @@ public class SingleKeyGestureTests {
        }
    }

    @Test
    public void testOnKeyUp_Pressure() throws InterruptedException {
        final HandlerThread handlerThread =
                new HandlerThread("testInputReader", Process.THREAD_PRIORITY_DISPLAY);
        handlerThread.start();
        Handler newHandler = new Handler(handlerThread.getLooper());
        try {
            // To make sure we won't get any unexpected multi-press count.
            for (int i = 0; i < 5; i++) {
                newHandler.runWithScissors(
                        () -> {
                            pressKey(KEYCODE_POWER, 0 /* pressTime */);
                            pressKey(KEYCODE_POWER, 0 /* pressTime */);
                        },
                        mWaitTimeout);
                newHandler.runWithScissors(
                        () -> pressKey(KEYCODE_BACK, 0 /* pressTime */), mWaitTimeout);

                verifyKeyUpData(KEYCODE_POWER, 1 /* expectedMultiPressCount */);
                verifyKeyUpData(KEYCODE_POWER, 2 /* expectedMultiPressCount */);
                verifyKeyUpData(KEYCODE_BACK, 1 /* expectedMultiPressCount */);
            }
        } finally {
            handlerThread.quitSafely();
        }
    }

    @Test
    public void testUpdateRule() throws InterruptedException {
        // Power key rule doesn't allow the long press gesture.