blob: 9bb6273d71e3f2846248e1964d20015cbcd2e331 [file] [log] [blame]
Prabir Pradhanbaa5c822019-08-30 15:27:05 -07001/*
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
Michael Wrightfe3de7d2020-07-02 19:05:30 +010017// clang-format off
Prabir Pradhan9244aea2020-02-05 20:31:40 -080018#include "../Macros.h"
Michael Wrightfe3de7d2020-07-02 19:05:30 +010019// clang-format on
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070020
21#include "KeyboardInputMapper.h"
22
23namespace android {
24
25// --- Static Definitions ---
26
27static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
28 const int32_t map[][4], size_t mapSize) {
29 if (orientation != DISPLAY_ORIENTATION_0) {
30 for (size_t i = 0; i < mapSize; i++) {
31 if (value == map[i][0]) {
32 return map[i][orientation];
33 }
34 }
35 }
36 return value;
37}
38
39static const int32_t keyCodeRotationMap[][4] = {
40 // key codes enumerated counter-clockwise with the original (unrotated) key first
41 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
42 {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
43 {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
44 {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
45 {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
46 {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
47 AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
48 {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
49 AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
50 {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
51 AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
52 {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
53 AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
54};
55
56static const size_t keyCodeRotationMapSize =
57 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
58
59static int32_t rotateStemKey(int32_t value, int32_t orientation, const int32_t map[][2],
60 size_t mapSize) {
61 if (orientation == DISPLAY_ORIENTATION_180) {
62 for (size_t i = 0; i < mapSize; i++) {
63 if (value == map[i][0]) {
64 return map[i][1];
65 }
66 }
67 }
68 return value;
69}
70
71// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
72static int32_t stemKeyRotationMap[][2] = {
73 // key codes enumerated with the original (unrotated) key first
74 // no rotation, 180 degree rotation
75 {AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY},
76 {AKEYCODE_STEM_1, AKEYCODE_STEM_1},
77 {AKEYCODE_STEM_2, AKEYCODE_STEM_2},
78 {AKEYCODE_STEM_3, AKEYCODE_STEM_3},
79};
80
81static const size_t stemKeyRotationMapSize =
82 sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
83
84static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
85 keyCode = rotateStemKey(keyCode, orientation, stemKeyRotationMap, stemKeyRotationMapSize);
86 return rotateValueUsingRotationMap(keyCode, orientation, keyCodeRotationMap,
87 keyCodeRotationMapSize);
88}
89
90// --- KeyboardInputMapper ---
91
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080092KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source,
93 int32_t keyboardType)
94 : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070095
96KeyboardInputMapper::~KeyboardInputMapper() {}
97
Philip Junker4af3b3d2021-12-14 10:36:55 +010098uint32_t KeyboardInputMapper::getSources() const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070099 return mSource;
100}
101
102int32_t KeyboardInputMapper::getOrientation() {
103 if (mViewport) {
104 return mViewport->orientation;
105 }
106 return DISPLAY_ORIENTATION_0;
107}
108
109int32_t KeyboardInputMapper::getDisplayId() {
110 if (mViewport) {
111 return mViewport->displayId;
112 }
113 return ADISPLAY_ID_NONE;
114}
115
116void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
117 InputMapper::populateDeviceInfo(info);
118
119 info->setKeyboardType(mKeyboardType);
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800120 info->setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700121}
122
123void KeyboardInputMapper::dump(std::string& dump) {
124 dump += INDENT2 "Keyboard Input Mapper:\n";
125 dumpParameters(dump);
126 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
127 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
128 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
129 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700130}
131
132std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
133 nsecs_t when, const InputReaderConfiguration* config) {
Christine Franks1ba71cc2021-04-07 14:37:42 -0700134 if (getDeviceContext().getAssociatedViewport()) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800135 return getDeviceContext().getAssociatedViewport();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700136 }
137
138 // No associated display defined, try to find default display if orientationAware.
139 if (mParameters.orientationAware) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100140 return config->getDisplayViewportByType(ViewportType::INTERNAL);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700141 }
142
143 return std::nullopt;
144}
145
146void KeyboardInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
147 uint32_t changes) {
148 InputMapper::configure(when, config, changes);
149
150 if (!changes) { // first time only
151 // Configure basic parameters.
152 configureParameters();
153 }
154
155 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
156 mViewport = findViewport(when, config);
157 }
158}
159
160static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const* property) {
161 int32_t mapped = 0;
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700162 if (config.tryGetProperty(property, mapped) && mapped > 0) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700163 for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
164 if (stemKeyRotationMap[i][0] == keyCode) {
165 stemKeyRotationMap[i][1] = mapped;
166 return;
167 }
168 }
169 }
170}
171
172void KeyboardInputMapper::configureParameters() {
173 mParameters.orientationAware = false;
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800174 const PropertyMap& config = getDeviceContext().getConfiguration();
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700175 config.tryGetProperty("keyboard.orientationAware", mParameters.orientationAware);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700176
177 if (mParameters.orientationAware) {
178 mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
179 mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
180 mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
181 mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
182 }
183
184 mParameters.handlesKeyRepeat = false;
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700185 config.tryGetProperty("keyboard.handlesKeyRepeat", mParameters.handlesKeyRepeat);
Powei Fengd041c5d2019-05-03 17:11:33 -0700186
187 mParameters.doNotWakeByDefault = false;
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700188 config.tryGetProperty("keyboard.doNotWakeByDefault", mParameters.doNotWakeByDefault);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700189}
190
191void KeyboardInputMapper::dumpParameters(std::string& dump) {
192 dump += INDENT3 "Parameters:\n";
193 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
194 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
195}
196
197void KeyboardInputMapper::reset(nsecs_t when) {
Arthur Hung2141d542022-08-23 07:45:21 +0000198 cancelAllDownKeys(when);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700199 mCurrentHidUsage = 0;
200
201 resetLedState();
202
203 InputMapper::reset(when);
204}
205
206void KeyboardInputMapper::process(const RawEvent* rawEvent) {
207 switch (rawEvent->type) {
208 case EV_KEY: {
209 int32_t scanCode = rawEvent->code;
210 int32_t usageCode = mCurrentHidUsage;
211 mCurrentHidUsage = 0;
212
213 if (isKeyboardOrGamepadKey(scanCode)) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000214 processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,
215 usageCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700216 }
217 break;
218 }
219 case EV_MSC: {
220 if (rawEvent->code == MSC_SCAN) {
221 mCurrentHidUsage = rawEvent->value;
222 }
223 break;
224 }
225 case EV_SYN: {
226 if (rawEvent->code == SYN_REPORT) {
227 mCurrentHidUsage = 0;
228 }
229 }
230 }
231}
232
233bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -0700234 return scanCode < BTN_MOUSE || scanCode >= BTN_WHEEL ||
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700235 (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) ||
236 (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
237}
238
239bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
240 switch (keyCode) {
241 case AKEYCODE_MEDIA_PLAY:
242 case AKEYCODE_MEDIA_PAUSE:
243 case AKEYCODE_MEDIA_PLAY_PAUSE:
244 case AKEYCODE_MUTE:
245 case AKEYCODE_HEADSETHOOK:
246 case AKEYCODE_MEDIA_STOP:
247 case AKEYCODE_MEDIA_NEXT:
248 case AKEYCODE_MEDIA_PREVIOUS:
249 case AKEYCODE_MEDIA_REWIND:
250 case AKEYCODE_MEDIA_RECORD:
251 case AKEYCODE_MEDIA_FAST_FORWARD:
252 case AKEYCODE_MEDIA_SKIP_FORWARD:
253 case AKEYCODE_MEDIA_SKIP_BACKWARD:
254 case AKEYCODE_MEDIA_STEP_FORWARD:
255 case AKEYCODE_MEDIA_STEP_BACKWARD:
256 case AKEYCODE_MEDIA_AUDIO_TRACK:
257 case AKEYCODE_VOLUME_UP:
258 case AKEYCODE_VOLUME_DOWN:
259 case AKEYCODE_VOLUME_MUTE:
260 case AKEYCODE_TV_AUDIO_DESCRIPTION:
261 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
262 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
263 return true;
264 }
265 return false;
266}
267
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000268void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
269 int32_t usageCode) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700270 int32_t keyCode;
271 int32_t keyMetaState;
272 uint32_t policyFlags;
273
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800274 if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
275 &policyFlags)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700276 keyCode = AKEYCODE_UNKNOWN;
277 keyMetaState = mMetaState;
278 policyFlags = 0;
279 }
280
Arthur Hung2141d542022-08-23 07:45:21 +0000281 nsecs_t downTime = when;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700282 if (down) {
283 // Rotate key codes according to orientation if needed.
284 if (mParameters.orientationAware) {
285 keyCode = rotateKeyCode(keyCode, getOrientation());
286 }
287
288 // Add key down.
289 ssize_t keyDownIndex = findKeyDown(scanCode);
290 if (keyDownIndex >= 0) {
291 // key repeat, be sure to use same keycode as before in case of rotation
292 keyCode = mKeyDowns[keyDownIndex].keyCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000293 downTime = mKeyDowns[keyDownIndex].downTime;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700294 } else {
295 // key down
296 if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800297 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700298 return;
299 }
300 if (policyFlags & POLICY_FLAG_GESTURE) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000301 getDeviceContext().cancelTouch(when, readTime);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700302 }
303
304 KeyDown keyDown;
305 keyDown.keyCode = keyCode;
306 keyDown.scanCode = scanCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000307 keyDown.downTime = when;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700308 mKeyDowns.push_back(keyDown);
309 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700310 } else {
311 // Remove key down.
312 ssize_t keyDownIndex = findKeyDown(scanCode);
313 if (keyDownIndex >= 0) {
314 // key up, be sure to use same keycode as before in case of rotation
315 keyCode = mKeyDowns[keyDownIndex].keyCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000316 downTime = mKeyDowns[keyDownIndex].downTime;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700317 mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
318 } else {
319 // key was not actually down
320 ALOGI("Dropping key up from device %s because the key was not down. "
321 "keyCode=%d, scanCode=%d",
322 getDeviceName().c_str(), keyCode, scanCode);
323 return;
324 }
325 }
326
327 if (updateMetaStateIfNeeded(keyCode, down)) {
328 // If global meta state changed send it along with the key.
329 // If it has not changed then we'll use what keymap gave us,
330 // since key replacement logic might temporarily reset a few
331 // meta bits for given key.
332 keyMetaState = mMetaState;
333 }
334
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700335 // Key down on external an keyboard should wake the device.
336 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
Powei Fengd041c5d2019-05-03 17:11:33 -0700337 // For internal keyboards and devices for which the default wake behavior is explicitly
338 // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
339 // wake key individually.
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700340 // TODO: Use the input device configuration to control this behavior more finely.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800341 if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
Powei Fengd041c5d2019-05-03 17:11:33 -0700342 !isMediaKey(keyCode)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700343 policyFlags |= POLICY_FLAG_WAKE;
344 }
345
346 if (mParameters.handlesKeyRepeat) {
347 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
348 }
349
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000350 NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
351 getDisplayId(), policyFlags,
352 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
Siarhei Vishniakouf2f073b2021-02-09 21:59:56 +0000353 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700354 getListener().notifyKey(&args);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700355}
356
357ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
358 size_t n = mKeyDowns.size();
359 for (size_t i = 0; i < n; i++) {
360 if (mKeyDowns[i].scanCode == scanCode) {
361 return i;
362 }
363 }
364 return -1;
365}
366
367int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800368 return getDeviceContext().getKeyCodeState(keyCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700369}
370
371int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800372 return getDeviceContext().getScanCodeState(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700373}
374
Philip Junker4af3b3d2021-12-14 10:36:55 +0100375int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
376 return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
377}
378
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700379bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
380 const std::vector<int32_t>& keyCodes,
381 uint8_t* outFlags) {
382 return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700383}
384
385int32_t KeyboardInputMapper::getMetaState() {
386 return mMetaState;
387}
388
Arthur Hungcb40a002021-08-03 14:31:01 +0000389bool KeyboardInputMapper::updateMetaState(int32_t keyCode) {
390 if (!android::isMetaKey(keyCode) || !getDeviceContext().hasKeyCode(keyCode)) {
391 return false;
392 }
393
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700394 updateMetaStateIfNeeded(keyCode, false);
Arthur Hungcb40a002021-08-03 14:31:01 +0000395 return true;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700396}
397
398bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
399 int32_t oldMetaState = mMetaState;
400 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
arthurhungc903df12020-08-11 15:08:42 +0800401 int32_t metaStateChanged = oldMetaState ^ newMetaState;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700402 if (metaStateChanged) {
403 mMetaState = newMetaState;
arthurhungc903df12020-08-11 15:08:42 +0800404 constexpr int32_t allLedMetaState =
405 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
406 if ((metaStateChanged & allLedMetaState) != 0) {
407 getContext()->updateLedMetaState(newMetaState & allLedMetaState);
408 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700409 getContext()->updateGlobalMetaState();
410 }
411
412 return metaStateChanged;
413}
414
415void KeyboardInputMapper::resetLedState() {
416 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
417 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
418 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
419
420 updateLedState(true);
421}
422
423void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800424 ledState.avail = getDeviceContext().hasLed(led);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700425 ledState.on = false;
426}
427
428void KeyboardInputMapper::updateLedState(bool reset) {
Arthur Hungfb3cc112022-04-13 07:39:50 +0000429 // Clear the local led state then union the global led state.
430 mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
arthurhungc903df12020-08-11 15:08:42 +0800431 mMetaState |= getContext()->getLedMetaState();
Chris Yea52ade12020-08-27 16:49:20 -0700432
433 constexpr int32_t META_NUM = 3;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700434 const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
435 AKEYCODE_SCROLL_LOCK};
Chris Yea52ade12020-08-27 16:49:20 -0700436 const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
437 AMETA_SCROLL_LOCK_ON};
438 std::array<uint8_t, META_NUM> flags = {0, 0, 0};
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700439 bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
Chris Yea52ade12020-08-27 16:49:20 -0700440 // If the device doesn't have the physical meta key it shouldn't generate the corresponding
441 // meta state.
442 if (hasKeyLayout) {
443 for (int i = 0; i < META_NUM; i++) {
444 if (!flags[i]) {
445 mMetaState &= ~metaCodes[i];
446 }
447 }
448 }
449
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700450 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
451 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
452 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
453}
454
455void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
456 int32_t modifier, bool reset) {
457 if (ledState.avail) {
458 bool desiredState = (mMetaState & modifier) != 0;
459 if (reset || ledState.on != desiredState) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800460 getDeviceContext().setLedState(led, desiredState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700461 ledState.on = desiredState;
462 }
463 }
464}
465
466std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
467 if (mViewport) {
468 return std::make_optional(mViewport->displayId);
469 }
470 return std::nullopt;
471}
472
Arthur Hung2141d542022-08-23 07:45:21 +0000473void KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
474 size_t n = mKeyDowns.size();
475 for (size_t i = 0; i < n; i++) {
476 NotifyKeyArgs args(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC),
477 getDeviceId(), mSource, getDisplayId(), 0 /*policyFlags*/,
478 AKEY_EVENT_ACTION_UP,
479 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED,
480 mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
481 mKeyDowns[i].downTime);
482 getListener().notifyKey(&args);
483 }
484 mKeyDowns.clear();
485 mMetaState = AMETA_NONE;
486}
487
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700488} // namespace android