1 /*
2  * Copyright (C) 2019 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 // clang-format off
18 #include "../Macros.h"
19 // clang-format on
20 
21 #include "KeyboardInputMapper.h"
22 
23 #include <ftl/enum.h>
24 #include <input/KeyboardClassifier.h>
25 #include <ui/Rotation.h>
26 
27 namespace android {
28 
29 // --- Static Definitions ---
30 
rotateKeyCode(int32_t keyCode,ui::Rotation orientation)31 static int32_t rotateKeyCode(int32_t keyCode, ui::Rotation orientation) {
32     static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = {
33             // key codes enumerated counter-clockwise with the original (unrotated) key first
34             // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
35             {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
36             {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
37             {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
38             {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
39             {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
40              AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
41             {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
42              AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
43             {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
44              AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
45             {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
46              AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
47     };
48 
49     if (orientation != ui::ROTATION_0) {
50         for (const auto& rotation : KEYCODE_ROTATION_MAP) {
51             if (rotation[static_cast<size_t>(ui::ROTATION_0)] == keyCode) {
52                 return rotation[static_cast<size_t>(orientation)];
53             }
54         }
55     }
56     return keyCode;
57 }
58 
isSupportedScanCode(int32_t scanCode)59 static bool isSupportedScanCode(int32_t scanCode) {
60     // KeyboardInputMapper handles keys from keyboards, gamepads, and styluses.
61     return scanCode < BTN_MOUSE || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI) ||
62             scanCode == BTN_STYLUS || scanCode == BTN_STYLUS2 || scanCode == BTN_STYLUS3 ||
63             scanCode >= BTN_WHEEL;
64 }
65 
isMediaKey(int32_t keyCode)66 static bool isMediaKey(int32_t keyCode) {
67     switch (keyCode) {
68         case AKEYCODE_MEDIA_PLAY:
69         case AKEYCODE_MEDIA_PAUSE:
70         case AKEYCODE_MEDIA_PLAY_PAUSE:
71         case AKEYCODE_MUTE:
72         case AKEYCODE_HEADSETHOOK:
73         case AKEYCODE_MEDIA_STOP:
74         case AKEYCODE_MEDIA_NEXT:
75         case AKEYCODE_MEDIA_PREVIOUS:
76         case AKEYCODE_MEDIA_REWIND:
77         case AKEYCODE_MEDIA_RECORD:
78         case AKEYCODE_MEDIA_FAST_FORWARD:
79         case AKEYCODE_MEDIA_SKIP_FORWARD:
80         case AKEYCODE_MEDIA_SKIP_BACKWARD:
81         case AKEYCODE_MEDIA_STEP_FORWARD:
82         case AKEYCODE_MEDIA_STEP_BACKWARD:
83         case AKEYCODE_MEDIA_AUDIO_TRACK:
84         case AKEYCODE_VOLUME_UP:
85         case AKEYCODE_VOLUME_DOWN:
86         case AKEYCODE_VOLUME_MUTE:
87         case AKEYCODE_TV_AUDIO_DESCRIPTION:
88         case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
89         case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
90             return true;
91         default:
92             return false;
93     }
94 }
95 
96 // --- KeyboardInputMapper ---
97 
KeyboardInputMapper(InputDeviceContext & deviceContext,const InputReaderConfiguration & readerConfig,uint32_t source)98 KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext,
99                                          const InputReaderConfiguration& readerConfig,
100                                          uint32_t source)
101       : InputMapper(deviceContext, readerConfig), mSource(source) {}
102 
getSources() const103 uint32_t KeyboardInputMapper::getSources() const {
104     return mSource;
105 }
106 
getOrientation()107 ui::Rotation KeyboardInputMapper::getOrientation() {
108     if (mViewport) {
109         return mViewport->orientation;
110     }
111     return ui::ROTATION_0;
112 }
113 
getDisplayId()114 ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
115     if (mViewport) {
116         return mViewport->displayId;
117     }
118     return ui::LogicalDisplayId::INVALID;
119 }
120 
getKeyboardLayoutInfo() const121 std::optional<KeyboardLayoutInfo> KeyboardInputMapper::getKeyboardLayoutInfo() const {
122     if (mKeyboardLayoutInfo) {
123         return mKeyboardLayoutInfo;
124     }
125     std::optional<RawLayoutInfo> layoutInfo = getDeviceContext().getRawLayoutInfo();
126     if (!layoutInfo) {
127         return std::nullopt;
128     }
129     return KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType);
130 }
131 
populateDeviceInfo(InputDeviceInfo & info)132 void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
133     InputMapper::populateDeviceInfo(info);
134 
135     info.setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
136 
137     std::optional keyboardLayoutInfo = getKeyboardLayoutInfo();
138     if (keyboardLayoutInfo) {
139         info.setKeyboardLayoutInfo(*keyboardLayoutInfo);
140     }
141 }
142 
dump(std::string & dump)143 void KeyboardInputMapper::dump(std::string& dump) {
144     dump += INDENT2 "Keyboard Input Mapper:\n";
145     dumpParameters(dump);
146     dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(getOrientation()).c_str());
147     dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
148     dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
149     dump += INDENT3 "KeyboardLayoutInfo: ";
150     if (mKeyboardLayoutInfo) {
151         dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n";
152     } else {
153         dump += "<not set>\n";
154     }
155 }
156 
findViewport(const InputReaderConfiguration & readerConfig)157 std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
158         const InputReaderConfiguration& readerConfig) {
159     if (getDeviceContext().getAssociatedViewport()) {
160         return getDeviceContext().getAssociatedViewport();
161     }
162 
163     // No associated display defined, try to find default display if orientationAware.
164     if (mParameters.orientationAware) {
165         return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL);
166     }
167 
168     return std::nullopt;
169 }
170 
reconfigure(nsecs_t when,const InputReaderConfiguration & config,ConfigurationChanges changes)171 std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
172                                                        const InputReaderConfiguration& config,
173                                                        ConfigurationChanges changes) {
174     std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
175 
176     if (!changes.any()) { // first time only
177         // Configure basic parameters.
178         configureParameters();
179     }
180 
181     if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
182         mViewport = findViewport(config);
183     }
184 
185     if (!changes.any() ||
186         changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) {
187         std::optional<KeyboardLayoutInfo> newKeyboardLayoutInfo =
188                 getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
189         if (mKeyboardLayoutInfo != newKeyboardLayoutInfo) {
190             mKeyboardLayoutInfo = newKeyboardLayoutInfo;
191             // Also update keyboard layout overlay as soon as we find the new layout info
192             updateKeyboardLayoutOverlay();
193             bumpGeneration();
194         }
195     }
196 
197     if (!changes.any() || changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUTS)) {
198         if (!getDeviceContext().getDeviceClasses().test(InputDeviceClass::VIRTUAL) &&
199             updateKeyboardLayoutOverlay()) {
200             bumpGeneration();
201         }
202     }
203     return out;
204 }
205 
updateKeyboardLayoutOverlay()206 bool KeyboardInputMapper::updateKeyboardLayoutOverlay() {
207     std::shared_ptr<KeyCharacterMap> keyboardLayout =
208             getDeviceContext()
209                     .getContext()
210                     ->getPolicy()
211                     ->getKeyboardLayoutOverlay(getDeviceContext().getDeviceIdentifier(),
212                                                getKeyboardLayoutInfo());
213     return getDeviceContext().setKeyboardLayoutOverlay(keyboardLayout);
214 }
215 
configureParameters()216 void KeyboardInputMapper::configureParameters() {
217     const PropertyMap& config = getDeviceContext().getConfiguration();
218     mParameters.orientationAware = config.getBool("keyboard.orientationAware").value_or(false);
219     mParameters.handlesKeyRepeat = config.getBool("keyboard.handlesKeyRepeat").value_or(false);
220     mParameters.doNotWakeByDefault = config.getBool("keyboard.doNotWakeByDefault").value_or(false);
221 }
222 
dumpParameters(std::string & dump) const223 void KeyboardInputMapper::dumpParameters(std::string& dump) const {
224     dump += INDENT3 "Parameters:\n";
225     dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
226     dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
227 }
228 
reset(nsecs_t when)229 std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) {
230     std::list<NotifyArgs> out = cancelAllDownKeys(when);
231     mHidUsageAccumulator.reset();
232 
233     resetLedState();
234 
235     out += InputMapper::reset(when);
236     return out;
237 }
238 
process(const RawEvent & rawEvent)239 std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent& rawEvent) {
240     std::list<NotifyArgs> out;
241     mHidUsageAccumulator.process(rawEvent);
242     switch (rawEvent.type) {
243         case EV_KEY: {
244             int32_t scanCode = rawEvent.code;
245 
246             if (isSupportedScanCode(scanCode)) {
247                 out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0,
248                                   scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
249             }
250             break;
251         }
252     }
253     return out;
254 }
255 
processKey(nsecs_t when,nsecs_t readTime,bool down,int32_t scanCode,int32_t usageCode)256 std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down,
257                                                       int32_t scanCode, int32_t usageCode) {
258     std::list<NotifyArgs> out;
259     int32_t keyCode;
260     int32_t keyMetaState;
261     uint32_t policyFlags;
262     int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
263 
264     if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
265                                   &policyFlags)) {
266         keyCode = AKEYCODE_UNKNOWN;
267         keyMetaState = mMetaState;
268         policyFlags = 0;
269     }
270 
271     nsecs_t downTime = when;
272     std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode);
273     if (down) {
274         // Rotate key codes according to orientation if needed.
275         if (mParameters.orientationAware) {
276             keyCode = rotateKeyCode(keyCode, getOrientation());
277         }
278 
279         // Add key down.
280         if (keyDownIndex) {
281             // key repeat, be sure to use same keycode as before in case of rotation
282             keyCode = mKeyDowns[*keyDownIndex].keyCode;
283             downTime = mKeyDowns[*keyDownIndex].downTime;
284             flags = mKeyDowns[*keyDownIndex].flags;
285         } else {
286             // key down
287             if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
288                 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
289                 return out;
290             }
291             if (policyFlags & POLICY_FLAG_GESTURE) {
292                 out += getDeviceContext().cancelTouch(when, readTime);
293                 flags |= AKEY_EVENT_FLAG_KEEP_TOUCH_MODE;
294             }
295 
296             KeyDown keyDown;
297             keyDown.keyCode = keyCode;
298             keyDown.scanCode = scanCode;
299             keyDown.downTime = when;
300             keyDown.flags = flags;
301             mKeyDowns.push_back(keyDown);
302         }
303         onKeyDownProcessed(downTime);
304     } else {
305         // Remove key down.
306         if (keyDownIndex) {
307             // key up, be sure to use same keycode as before in case of rotation
308             keyCode = mKeyDowns[*keyDownIndex].keyCode;
309             downTime = mKeyDowns[*keyDownIndex].downTime;
310             flags = mKeyDowns[*keyDownIndex].flags;
311             mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex);
312         } else {
313             // key was not actually down
314             ALOGI("Dropping key up from device %s because the key was not down.  "
315                   "keyCode=%d, scanCode=%d",
316                   getDeviceName().c_str(), keyCode, scanCode);
317             return out;
318         }
319     }
320 
321     if (updateMetaStateIfNeeded(keyCode, down)) {
322         // If global meta state changed send it along with the key.
323         // If it has not changed then we'll use what keymap gave us,
324         // since key replacement logic might temporarily reset a few
325         // meta bits for given key.
326         keyMetaState = mMetaState;
327     }
328 
329     DeviceId deviceId = getDeviceId();
330 
331     // On first down: Process key for keyboard classification (will send reconfiguration if the
332     // keyboard type change)
333     if (down && !keyDownIndex) {
334         KeyboardClassifier& classifier = getDeviceContext().getContext()->getKeyboardClassifier();
335         classifier.processKey(deviceId, scanCode, keyMetaState);
336         getDeviceContext().setKeyboardType(classifier.getKeyboardType(deviceId));
337     }
338 
339     KeyboardType keyboardType = getDeviceContext().getKeyboardType();
340     // Any key down on an external keyboard should wake the device.
341     // We don't do this for internal keyboards to prevent them from waking up in your pocket.
342     // For internal keyboards and devices for which the default wake behavior is explicitly
343     // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
344     // wake key individually.
345     if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
346         !(keyboardType != KeyboardType::ALPHABETIC && isMediaKey(keyCode))) {
347         policyFlags |= POLICY_FLAG_WAKE;
348     }
349 
350     if (mParameters.handlesKeyRepeat) {
351         policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
352     }
353 
354     out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, mSource,
355                                    getDisplayId(), policyFlags,
356                                    down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags,
357                                    keyCode, scanCode, keyMetaState, downTime));
358     return out;
359 }
360 
findKeyDownIndex(int32_t scanCode)361 std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) {
362     size_t n = mKeyDowns.size();
363     for (size_t i = 0; i < n; i++) {
364         if (mKeyDowns[i].scanCode == scanCode) {
365             return i;
366         }
367     }
368     return {};
369 }
370 
getKeyCodeState(uint32_t sourceMask,int32_t keyCode)371 int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
372     return getDeviceContext().getKeyCodeState(keyCode);
373 }
374 
getScanCodeState(uint32_t sourceMask,int32_t scanCode)375 int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
376     return getDeviceContext().getScanCodeState(scanCode);
377 }
378 
getKeyCodeForKeyLocation(int32_t locationKeyCode) const379 int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
380     return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
381 }
382 
markSupportedKeyCodes(uint32_t sourceMask,const std::vector<int32_t> & keyCodes,uint8_t * outFlags)383 bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
384                                                 const std::vector<int32_t>& keyCodes,
385                                                 uint8_t* outFlags) {
386     return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
387 }
388 
getMetaState()389 int32_t KeyboardInputMapper::getMetaState() {
390     return mMetaState;
391 }
392 
updateMetaState(int32_t keyCode)393 bool KeyboardInputMapper::updateMetaState(int32_t keyCode) {
394     if (!android::isMetaKey(keyCode) || !getDeviceContext().hasKeyCode(keyCode)) {
395         return false;
396     }
397 
398     updateMetaStateIfNeeded(keyCode, false);
399     return true;
400 }
401 
updateMetaStateIfNeeded(int32_t keyCode,bool down)402 bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
403     int32_t oldMetaState = mMetaState;
404     int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
405     int32_t metaStateChanged = oldMetaState ^ newMetaState;
406     if (metaStateChanged) {
407         mMetaState = newMetaState;
408         constexpr int32_t allLedMetaState =
409                 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
410         if ((metaStateChanged & allLedMetaState) != 0) {
411             getContext()->updateLedMetaState(newMetaState & allLedMetaState);
412         }
413         getContext()->updateGlobalMetaState();
414     }
415 
416     return metaStateChanged;
417 }
418 
resetLedState()419 void KeyboardInputMapper::resetLedState() {
420     initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
421     initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
422     initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
423 
424     updateLedState(true);
425 }
426 
initializeLedState(LedState & ledState,int32_t led)427 void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
428     ledState.avail = getDeviceContext().hasLed(led);
429     ledState.on = false;
430 }
431 
updateLedState(bool reset)432 void KeyboardInputMapper::updateLedState(bool reset) {
433     // Clear the local led state then union the global led state.
434     mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
435     mMetaState |= getContext()->getLedMetaState();
436 
437     constexpr int32_t META_NUM = 3;
438     const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
439                                         AKEYCODE_SCROLL_LOCK};
440     const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
441                                                      AMETA_SCROLL_LOCK_ON};
442     std::array<uint8_t, META_NUM> flags = {0, 0, 0};
443     bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
444     // If the device doesn't have the physical meta key it shouldn't generate the corresponding
445     // meta state.
446     if (hasKeyLayout) {
447         for (int i = 0; i < META_NUM; i++) {
448             if (!flags[i]) {
449                 mMetaState &= ~metaCodes[i];
450             }
451         }
452     }
453 
454     updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
455     updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
456     updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
457 }
458 
updateLedStateForModifier(LedState & ledState,int32_t led,int32_t modifier,bool reset)459 void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
460                                                     int32_t modifier, bool reset) {
461     if (ledState.avail) {
462         bool desiredState = (mMetaState & modifier) != 0;
463         if (reset || ledState.on != desiredState) {
464             getDeviceContext().setLedState(led, desiredState);
465             ledState.on = desiredState;
466         }
467     }
468 }
469 
getAssociatedDisplayId()470 std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
471     if (mViewport) {
472         return std::make_optional(mViewport->displayId);
473     }
474     return std::nullopt;
475 }
476 
cancelAllDownKeys(nsecs_t when)477 std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
478     std::list<NotifyArgs> out;
479     size_t n = mKeyDowns.size();
480     for (size_t i = 0; i < n; i++) {
481         out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when,
482                                        systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource,
483                                        getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP,
484                                        mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED,
485                                        mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
486                                        mKeyDowns[i].downTime));
487     }
488     mKeyDowns.clear();
489     mMetaState = AMETA_NONE;
490     return out;
491 }
492 
onKeyDownProcessed(nsecs_t downTime)493 void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
494     InputReaderContext& context = *getContext();
495     context.setLastKeyDownTimestamp(downTime);
496     // Ignore meta keys or multiple simultaneous down keys as they are likely to be keyboard
497     // shortcuts
498     bool shouldHideCursor = mKeyDowns.size() == 1 && !isMetaKey(mKeyDowns[0].keyCode);
499     if (shouldHideCursor && context.getPolicy()->isInputMethodConnectionActive()) {
500         context.setPreventingTouchpadTaps(true);
501     }
502 }
503 
504 } // namespace android
505