Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "../InputDispatcher.h"
     18 
     19 #include <gtest/gtest.h>
     20 #include <linux/input.h>
     21 
     22 namespace android {
     23 
     24 // An arbitrary time value.
     25 static const nsecs_t ARBITRARY_TIME = 1234;
     26 
     27 // An arbitrary device id.
     28 static const int32_t DEVICE_ID = 1;
     29 
     30 // An arbitrary display id.
     31 static const int32_t DISPLAY_ID = 0;
     32 
     33 // An arbitrary injector pid / uid pair that has permission to inject events.
     34 static const int32_t INJECTOR_PID = 999;
     35 static const int32_t INJECTOR_UID = 1001;
     36 
     37 
     38 // --- FakeInputDispatcherPolicy ---
     39 
     40 class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
     41     InputDispatcherConfiguration mConfig;
     42 
     43 protected:
     44     virtual ~FakeInputDispatcherPolicy() {
     45     }
     46 
     47 public:
     48     FakeInputDispatcherPolicy() {
     49     }
     50 
     51 private:
     52     virtual void notifyConfigurationChanged(nsecs_t when) {
     53     }
     54 
     55     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
     56             const sp<InputWindowHandle>& inputWindowHandle,
     57             const String8& reason) {
     58         return 0;
     59     }
     60 
     61     virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
     62     }
     63 
     64     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
     65         *outConfig = mConfig;
     66     }
     67 
     68     virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
     69         return true;
     70     }
     71 
     72     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
     73     }
     74 
     75     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
     76     }
     77 
     78     virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
     79             const KeyEvent* keyEvent, uint32_t policyFlags) {
     80         return 0;
     81     }
     82 
     83     virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
     84             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     85         return false;
     86     }
     87 
     88     virtual void notifySwitch(nsecs_t when,
     89             uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
     90     }
     91 
     92     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
     93     }
     94 
     95     virtual bool checkInjectEventsPermissionNonReentrant(
     96             int32_t injectorPid, int32_t injectorUid) {
     97         return false;
     98     }
     99 };
    100 
    101 
    102 // --- InputDispatcherTest ---
    103 
    104 class InputDispatcherTest : public testing::Test {
    105 protected:
    106     sp<FakeInputDispatcherPolicy> mFakePolicy;
    107     sp<InputDispatcher> mDispatcher;
    108 
    109     virtual void SetUp() {
    110         mFakePolicy = new FakeInputDispatcherPolicy();
    111         mDispatcher = new InputDispatcher(mFakePolicy);
    112     }
    113 
    114     virtual void TearDown() {
    115         mFakePolicy.clear();
    116         mDispatcher.clear();
    117     }
    118 };
    119 
    120 
    121 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
    122     KeyEvent event;
    123 
    124     // Rejects undefined key actions.
    125     event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
    126             /*action*/ -1, 0,
    127             AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
    128     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    129             &event, DISPLAY_ID,
    130             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    131             << "Should reject key events with undefined action.";
    132 
    133     // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
    134     event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
    135             AKEY_EVENT_ACTION_MULTIPLE, 0,
    136             AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
    137     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    138             &event, DISPLAY_ID,
    139             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    140             << "Should reject key events with ACTION_MULTIPLE.";
    141 }
    142 
    143 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
    144     MotionEvent event;
    145     PointerProperties pointerProperties[MAX_POINTERS + 1];
    146     PointerCoords pointerCoords[MAX_POINTERS + 1];
    147     for (int i = 0; i <= MAX_POINTERS; i++) {
    148         pointerProperties[i].clear();
    149         pointerProperties[i].id = i;
    150         pointerCoords[i].clear();
    151     }
    152 
    153     // Rejects undefined motion actions.
    154     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    155             /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    156             ARBITRARY_TIME, ARBITRARY_TIME,
    157             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    158     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    159             &event, DISPLAY_ID,
    160             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    161             << "Should reject motion events with undefined action.";
    162 
    163     // Rejects pointer down with invalid index.
    164     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    165             AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
    166             0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    167             ARBITRARY_TIME, ARBITRARY_TIME,
    168             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    169     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    170             &event, DISPLAY_ID,
    171             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    172             << "Should reject motion events with pointer down index too large.";
    173 
    174     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    175             AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
    176             0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    177             ARBITRARY_TIME, ARBITRARY_TIME,
    178             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    179     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    180             &event, DISPLAY_ID,
    181             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    182             << "Should reject motion events with pointer down index too small.";
    183 
    184     // Rejects pointer up with invalid index.
    185     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    186             AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
    187             0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    188             ARBITRARY_TIME, ARBITRARY_TIME,
    189             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    190     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    191             &event, DISPLAY_ID,
    192             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    193             << "Should reject motion events with pointer up index too large.";
    194 
    195     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    196             AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
    197             0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    198             ARBITRARY_TIME, ARBITRARY_TIME,
    199             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    200     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    201             &event, DISPLAY_ID,
    202             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    203             << "Should reject motion events with pointer up index too small.";
    204 
    205     // Rejects motion events with invalid number of pointers.
    206     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    207             AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    208             ARBITRARY_TIME, ARBITRARY_TIME,
    209             /*pointerCount*/ 0, pointerProperties, pointerCoords);
    210     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    211             &event, DISPLAY_ID,
    212             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    213             << "Should reject motion events with 0 pointers.";
    214 
    215     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    216             AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    217             ARBITRARY_TIME, ARBITRARY_TIME,
    218             /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
    219     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    220             &event, DISPLAY_ID,
    221             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    222             << "Should reject motion events with more than MAX_POINTERS pointers.";
    223 
    224     // Rejects motion events with invalid pointer ids.
    225     pointerProperties[0].id = -1;
    226     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    227             AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    228             ARBITRARY_TIME, ARBITRARY_TIME,
    229             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    230     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    231             &event, DISPLAY_ID,
    232             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    233             << "Should reject motion events with pointer ids less than 0.";
    234 
    235     pointerProperties[0].id = MAX_POINTER_ID + 1;
    236     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    237             AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    238             ARBITRARY_TIME, ARBITRARY_TIME,
    239             /*pointerCount*/ 1, pointerProperties, pointerCoords);
    240     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    241             &event, DISPLAY_ID,
    242             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    243             << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
    244 
    245     // Rejects motion events with duplicate pointer ids.
    246     pointerProperties[0].id = 1;
    247     pointerProperties[1].id = 1;
    248     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
    249             AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
    250             ARBITRARY_TIME, ARBITRARY_TIME,
    251             /*pointerCount*/ 2, pointerProperties, pointerCoords);
    252     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
    253             &event, DISPLAY_ID,
    254             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
    255             << "Should reject motion events with duplicate pointer ids.";
    256 }
    257 
    258 } // namespace android
    259