blob: 6f01449083a35b83d74ceaa45f5ac26c9d5de449 [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
Michael Wrighta9cf4192022-12-01 23:46:39 +000023#include <ui/Rotation.h>
24
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070025namespace android {
26
27// --- Static Definitions ---
28
Michael Wrighta9cf4192022-12-01 23:46:39 +000029static int32_t rotateKeyCode(int32_t keyCode, ui::Rotation orientation) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000030 static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = {
31 // key codes enumerated counter-clockwise with the original (unrotated) key first
32 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
33 {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
34 {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
35 {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
36 {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
37 {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
38 AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
39 {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
40 AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
41 {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
42 AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
43 {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
44 AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
45 };
46
Michael Wrighta9cf4192022-12-01 23:46:39 +000047 if (orientation != ui::ROTATION_0) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000048 for (const auto& rotation : KEYCODE_ROTATION_MAP) {
Michael Wrighta9cf4192022-12-01 23:46:39 +000049 if (rotation[static_cast<size_t>(ui::ROTATION_0)] == keyCode) {
50 return rotation[static_cast<size_t>(orientation)];
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070051 }
52 }
53 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +000054 return keyCode;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070055}
56
Prabir Pradhane1a41a82022-10-14 18:06:50 +000057static bool isSupportedScanCode(int32_t scanCode) {
58 // KeyboardInputMapper handles keys from keyboards, gamepads, and styluses.
59 return scanCode < BTN_MOUSE || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI) ||
60 scanCode == BTN_STYLUS || scanCode == BTN_STYLUS2 || scanCode == BTN_STYLUS3 ||
61 scanCode >= BTN_WHEEL;
Prabir Pradhan2197cb42022-10-11 02:56:14 +000062}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070063
Prabir Pradhan2197cb42022-10-11 02:56:14 +000064static bool isMediaKey(int32_t keyCode) {
65 switch (keyCode) {
66 case AKEYCODE_MEDIA_PLAY:
67 case AKEYCODE_MEDIA_PAUSE:
68 case AKEYCODE_MEDIA_PLAY_PAUSE:
69 case AKEYCODE_MUTE:
70 case AKEYCODE_HEADSETHOOK:
71 case AKEYCODE_MEDIA_STOP:
72 case AKEYCODE_MEDIA_NEXT:
73 case AKEYCODE_MEDIA_PREVIOUS:
74 case AKEYCODE_MEDIA_REWIND:
75 case AKEYCODE_MEDIA_RECORD:
76 case AKEYCODE_MEDIA_FAST_FORWARD:
77 case AKEYCODE_MEDIA_SKIP_FORWARD:
78 case AKEYCODE_MEDIA_SKIP_BACKWARD:
79 case AKEYCODE_MEDIA_STEP_FORWARD:
80 case AKEYCODE_MEDIA_STEP_BACKWARD:
81 case AKEYCODE_MEDIA_AUDIO_TRACK:
82 case AKEYCODE_VOLUME_UP:
83 case AKEYCODE_VOLUME_DOWN:
84 case AKEYCODE_VOLUME_MUTE:
85 case AKEYCODE_TV_AUDIO_DESCRIPTION:
86 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
87 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
88 return true;
89 default:
90 return false;
91 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070092}
93
94// --- KeyboardInputMapper ---
95
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080096KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source,
97 int32_t keyboardType)
98 : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070099
Philip Junker4af3b3d2021-12-14 10:36:55 +0100100uint32_t KeyboardInputMapper::getSources() const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700101 return mSource;
102}
103
Michael Wrighta9cf4192022-12-01 23:46:39 +0000104ui::Rotation KeyboardInputMapper::getOrientation() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700105 if (mViewport) {
106 return mViewport->orientation;
107 }
Michael Wrighta9cf4192022-12-01 23:46:39 +0000108 return ui::ROTATION_0;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700109}
110
111int32_t KeyboardInputMapper::getDisplayId() {
112 if (mViewport) {
113 return mViewport->displayId;
114 }
115 return ADISPLAY_ID_NONE;
116}
117
118void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
119 InputMapper::populateDeviceInfo(info);
120
121 info->setKeyboardType(mKeyboardType);
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800122 info->setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
Zixuan Qufecb6062022-11-12 04:44:31 +0000123
124 if (mKeyboardLayoutInfo) {
125 info->setKeyboardLayoutInfo(*mKeyboardLayoutInfo);
126 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700127}
128
129void KeyboardInputMapper::dump(std::string& dump) {
130 dump += INDENT2 "Keyboard Input Mapper:\n";
131 dumpParameters(dump);
132 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
133 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
134 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
135 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Zixuan Qufecb6062022-11-12 04:44:31 +0000136 dump += INDENT3 "KeyboardLayoutInfo: ";
137 if (mKeyboardLayoutInfo) {
138 dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n";
139 } else {
140 dump += "<not set>\n";
141 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700142}
143
144std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000145 const InputReaderConfiguration* config) {
Christine Franks1ba71cc2021-04-07 14:37:42 -0700146 if (getDeviceContext().getAssociatedViewport()) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800147 return getDeviceContext().getAssociatedViewport();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700148 }
149
150 // No associated display defined, try to find default display if orientationAware.
151 if (mParameters.orientationAware) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100152 return config->getDisplayViewportByType(ViewportType::INTERNAL);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700153 }
154
155 return std::nullopt;
156}
157
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700158std::list<NotifyArgs> KeyboardInputMapper::configure(nsecs_t when,
159 const InputReaderConfiguration* config,
160 uint32_t changes) {
161 std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700162
163 if (!changes) { // first time only
164 // Configure basic parameters.
165 configureParameters();
166 }
167
168 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000169 mViewport = findViewport(config);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700170 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000171
172 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION)) {
173 mKeyboardLayoutInfo =
174 getValueByKey(config->keyboardLayoutAssociations, getDeviceContext().getLocation());
175 }
176
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700177 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700178}
179
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700180void KeyboardInputMapper::configureParameters() {
181 mParameters.orientationAware = false;
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800182 const PropertyMap& config = getDeviceContext().getConfiguration();
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700183 config.tryGetProperty("keyboard.orientationAware", mParameters.orientationAware);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700184
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700185 mParameters.handlesKeyRepeat = false;
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700186 config.tryGetProperty("keyboard.handlesKeyRepeat", mParameters.handlesKeyRepeat);
Powei Fengd041c5d2019-05-03 17:11:33 -0700187
188 mParameters.doNotWakeByDefault = false;
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -0700189 config.tryGetProperty("keyboard.doNotWakeByDefault", mParameters.doNotWakeByDefault);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700190}
191
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000192void KeyboardInputMapper::dumpParameters(std::string& dump) const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700193 dump += INDENT3 "Parameters:\n";
194 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
195 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
196}
197
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700198std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) {
199 std::list<NotifyArgs> out = cancelAllDownKeys(when);
Prabir Pradhan84395e62022-10-26 19:52:00 +0000200 mHidUsageAccumulator.reset();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700201
202 resetLedState();
203
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700204 out += InputMapper::reset(when);
205 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700206}
207
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700208std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) {
209 std::list<NotifyArgs> out;
Prabir Pradhan84395e62022-10-26 19:52:00 +0000210 mHidUsageAccumulator.process(*rawEvent);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700211 switch (rawEvent->type) {
212 case EV_KEY: {
213 int32_t scanCode = rawEvent->code;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700214
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000215 if (isSupportedScanCode(scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700216 out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0,
Prabir Pradhan84395e62022-10-26 19:52:00 +0000217 scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700218 }
219 break;
220 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700221 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700222 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700223}
224
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700225std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down,
226 int32_t scanCode, int32_t usageCode) {
227 std::list<NotifyArgs> out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700228 int32_t keyCode;
229 int32_t keyMetaState;
230 uint32_t policyFlags;
231
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800232 if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
233 &policyFlags)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700234 keyCode = AKEYCODE_UNKNOWN;
235 keyMetaState = mMetaState;
236 policyFlags = 0;
237 }
238
Arthur Hung2141d542022-08-23 07:45:21 +0000239 nsecs_t downTime = when;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000240 std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700241 if (down) {
242 // Rotate key codes according to orientation if needed.
243 if (mParameters.orientationAware) {
244 keyCode = rotateKeyCode(keyCode, getOrientation());
245 }
246
247 // Add key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000248 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700249 // key repeat, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000250 keyCode = mKeyDowns[*keyDownIndex].keyCode;
251 downTime = mKeyDowns[*keyDownIndex].downTime;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700252 } else {
253 // key down
254 if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800255 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700256 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700257 }
258 if (policyFlags & POLICY_FLAG_GESTURE) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700259 out += getDeviceContext().cancelTouch(when, readTime);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700260 }
261
262 KeyDown keyDown;
263 keyDown.keyCode = keyCode;
264 keyDown.scanCode = scanCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000265 keyDown.downTime = when;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700266 mKeyDowns.push_back(keyDown);
267 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700268 } else {
269 // Remove key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000270 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700271 // key up, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000272 keyCode = mKeyDowns[*keyDownIndex].keyCode;
273 downTime = mKeyDowns[*keyDownIndex].downTime;
274 mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700275 } else {
276 // key was not actually down
277 ALOGI("Dropping key up from device %s because the key was not down. "
278 "keyCode=%d, scanCode=%d",
279 getDeviceName().c_str(), keyCode, scanCode);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700280 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700281 }
282 }
283
284 if (updateMetaStateIfNeeded(keyCode, down)) {
285 // If global meta state changed send it along with the key.
286 // If it has not changed then we'll use what keymap gave us,
287 // since key replacement logic might temporarily reset a few
288 // meta bits for given key.
289 keyMetaState = mMetaState;
290 }
291
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700292 // Key down on external an keyboard should wake the device.
293 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
Powei Fengd041c5d2019-05-03 17:11:33 -0700294 // For internal keyboards and devices for which the default wake behavior is explicitly
295 // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
296 // wake key individually.
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700297 // TODO: Use the input device configuration to control this behavior more finely.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800298 if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
Powei Fengd041c5d2019-05-03 17:11:33 -0700299 !isMediaKey(keyCode)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700300 policyFlags |= POLICY_FLAG_WAKE;
301 }
302
303 if (mParameters.handlesKeyRepeat) {
304 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
305 }
306
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000307 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
308 mSource, getDisplayId(), policyFlags,
309 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
310 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState,
311 downTime));
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700312 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700313}
314
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000315std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700316 size_t n = mKeyDowns.size();
317 for (size_t i = 0; i < n; i++) {
318 if (mKeyDowns[i].scanCode == scanCode) {
319 return i;
320 }
321 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000322 return {};
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700323}
324
325int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800326 return getDeviceContext().getKeyCodeState(keyCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700327}
328
329int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800330 return getDeviceContext().getScanCodeState(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700331}
332
Philip Junker4af3b3d2021-12-14 10:36:55 +0100333int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
334 return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
335}
336
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700337bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
338 const std::vector<int32_t>& keyCodes,
339 uint8_t* outFlags) {
340 return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700341}
342
343int32_t KeyboardInputMapper::getMetaState() {
344 return mMetaState;
345}
346
Arthur Hungcb40a002021-08-03 14:31:01 +0000347bool KeyboardInputMapper::updateMetaState(int32_t keyCode) {
348 if (!android::isMetaKey(keyCode) || !getDeviceContext().hasKeyCode(keyCode)) {
349 return false;
350 }
351
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700352 updateMetaStateIfNeeded(keyCode, false);
Arthur Hungcb40a002021-08-03 14:31:01 +0000353 return true;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700354}
355
356bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
357 int32_t oldMetaState = mMetaState;
358 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
arthurhungc903df12020-08-11 15:08:42 +0800359 int32_t metaStateChanged = oldMetaState ^ newMetaState;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700360 if (metaStateChanged) {
361 mMetaState = newMetaState;
arthurhungc903df12020-08-11 15:08:42 +0800362 constexpr int32_t allLedMetaState =
363 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
364 if ((metaStateChanged & allLedMetaState) != 0) {
365 getContext()->updateLedMetaState(newMetaState & allLedMetaState);
366 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700367 getContext()->updateGlobalMetaState();
368 }
369
370 return metaStateChanged;
371}
372
373void KeyboardInputMapper::resetLedState() {
374 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
375 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
376 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
377
378 updateLedState(true);
379}
380
381void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800382 ledState.avail = getDeviceContext().hasLed(led);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700383 ledState.on = false;
384}
385
386void KeyboardInputMapper::updateLedState(bool reset) {
Arthur Hungfb3cc112022-04-13 07:39:50 +0000387 // Clear the local led state then union the global led state.
388 mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
arthurhungc903df12020-08-11 15:08:42 +0800389 mMetaState |= getContext()->getLedMetaState();
Chris Yea52ade12020-08-27 16:49:20 -0700390
391 constexpr int32_t META_NUM = 3;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700392 const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
393 AKEYCODE_SCROLL_LOCK};
Chris Yea52ade12020-08-27 16:49:20 -0700394 const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
395 AMETA_SCROLL_LOCK_ON};
396 std::array<uint8_t, META_NUM> flags = {0, 0, 0};
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700397 bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
Chris Yea52ade12020-08-27 16:49:20 -0700398 // If the device doesn't have the physical meta key it shouldn't generate the corresponding
399 // meta state.
400 if (hasKeyLayout) {
401 for (int i = 0; i < META_NUM; i++) {
402 if (!flags[i]) {
403 mMetaState &= ~metaCodes[i];
404 }
405 }
406 }
407
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700408 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
409 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
410 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
411}
412
413void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
414 int32_t modifier, bool reset) {
415 if (ledState.avail) {
416 bool desiredState = (mMetaState & modifier) != 0;
417 if (reset || ledState.on != desiredState) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800418 getDeviceContext().setLedState(led, desiredState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700419 ledState.on = desiredState;
420 }
421 }
422}
423
424std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
425 if (mViewport) {
426 return std::make_optional(mViewport->displayId);
427 }
428 return std::nullopt;
429}
430
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700431std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
432 std::list<NotifyArgs> out;
Arthur Hung2141d542022-08-23 07:45:21 +0000433 size_t n = mKeyDowns.size();
434 for (size_t i = 0; i < n; i++) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000435 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when,
436 systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource,
437 getDisplayId(), 0 /*policyFlags*/, AKEY_EVENT_ACTION_UP,
438 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED,
439 mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
440 mKeyDowns[i].downTime));
Arthur Hung2141d542022-08-23 07:45:21 +0000441 }
442 mKeyDowns.clear();
443 mMetaState = AMETA_NONE;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700444 return out;
Arthur Hung2141d542022-08-23 07:45:21 +0000445}
446
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700447} // namespace android