blob: 6932a2e2d454062fb44caf76a5a689c4197e4461 [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 Pradhanbaa5c822019-08-30 15:27:05 -070064// --- KeyboardInputMapper ---
65
Arpit Singh8e6fb252023-04-06 11:49:17 +000066KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext,
67 const InputReaderConfiguration& readerConfig,
68 uint32_t source, int32_t keyboardType)
69 : InputMapper(deviceContext, readerConfig), mSource(source), mKeyboardType(keyboardType) {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070070
Philip Junker4af3b3d2021-12-14 10:36:55 +010071uint32_t KeyboardInputMapper::getSources() const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070072 return mSource;
73}
74
Michael Wrighta9cf4192022-12-01 23:46:39 +000075ui::Rotation KeyboardInputMapper::getOrientation() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070076 if (mViewport) {
77 return mViewport->orientation;
78 }
Michael Wrighta9cf4192022-12-01 23:46:39 +000079 return ui::ROTATION_0;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070080}
81
82int32_t KeyboardInputMapper::getDisplayId() {
83 if (mViewport) {
84 return mViewport->displayId;
85 }
86 return ADISPLAY_ID_NONE;
87}
88
Vaibhav Devmuraridec30802023-07-11 15:02:03 +000089std::optional<KeyboardLayoutInfo> KeyboardInputMapper::getKeyboardLayoutInfo() const {
90 if (mKeyboardLayoutInfo) {
91 return mKeyboardLayoutInfo;
92 }
93 std::optional<RawLayoutInfo> layoutInfo = getDeviceContext().getRawLayoutInfo();
94 if (!layoutInfo) {
95 return std::nullopt;
96 }
97 return KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType);
98}
99
Harry Cuttsd02ea102023-03-17 18:21:30 +0000100void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700101 InputMapper::populateDeviceInfo(info);
102
Harry Cuttsd02ea102023-03-17 18:21:30 +0000103 info.setKeyboardType(mKeyboardType);
104 info.setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
Zixuan Qufecb6062022-11-12 04:44:31 +0000105
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000106 std::optional keyboardLayoutInfo = getKeyboardLayoutInfo();
107 if (keyboardLayoutInfo) {
108 info.setKeyboardLayoutInfo(*keyboardLayoutInfo);
Zixuan Qufecb6062022-11-12 04:44:31 +0000109 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700110}
111
112void KeyboardInputMapper::dump(std::string& dump) {
113 dump += INDENT2 "Keyboard Input Mapper:\n";
114 dumpParameters(dump);
115 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
116 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
117 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
118 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Zixuan Qufecb6062022-11-12 04:44:31 +0000119 dump += INDENT3 "KeyboardLayoutInfo: ";
120 if (mKeyboardLayoutInfo) {
121 dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n";
122 } else {
123 dump += "<not set>\n";
124 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700125}
126
127std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
Arpit Singhed6c3de2023-04-05 19:24:37 +0000128 const InputReaderConfiguration& readerConfig) {
Christine Franks1ba71cc2021-04-07 14:37:42 -0700129 if (getDeviceContext().getAssociatedViewport()) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800130 return getDeviceContext().getAssociatedViewport();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700131 }
132
133 // No associated display defined, try to find default display if orientationAware.
134 if (mParameters.orientationAware) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000135 return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700136 }
137
138 return std::nullopt;
139}
140
Arpit Singh4be4eef2023-03-28 14:26:01 +0000141std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
Arpit Singhed6c3de2023-04-05 19:24:37 +0000142 const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000143 ConfigurationChanges changes) {
Arpit Singh4be4eef2023-03-28 14:26:01 +0000144 std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700145
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000146 if (!changes.any()) { // first time only
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700147 // Configure basic parameters.
148 configureParameters();
149 }
150
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000151 if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000152 mViewport = findViewport(config);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700153 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000154
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000155 if (!changes.any() ||
156 changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) {
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000157 std::optional<KeyboardLayoutInfo> newKeyboardLayoutInfo =
Arpit Singhed6c3de2023-04-05 19:24:37 +0000158 getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000159 if (mKeyboardLayoutInfo != newKeyboardLayoutInfo) {
160 mKeyboardLayoutInfo = newKeyboardLayoutInfo;
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000161 // Also update keyboard layout overlay as soon as we find the new layout info
162 updateKeyboardLayoutOverlay();
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000163 bumpGeneration();
164 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000165 }
166
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000167 if (!changes.any() || changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUTS)) {
168 if (!getDeviceContext().getDeviceClasses().test(InputDeviceClass::VIRTUAL) &&
169 updateKeyboardLayoutOverlay()) {
170 bumpGeneration();
171 }
172 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700173 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700174}
175
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000176bool KeyboardInputMapper::updateKeyboardLayoutOverlay() {
177 std::shared_ptr<KeyCharacterMap> keyboardLayout =
178 getDeviceContext()
179 .getContext()
180 ->getPolicy()
181 ->getKeyboardLayoutOverlay(getDeviceContext().getDeviceIdentifier(),
182 getKeyboardLayoutInfo());
183 return getDeviceContext().setKeyboardLayoutOverlay(keyboardLayout);
184}
185
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700186void KeyboardInputMapper::configureParameters() {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800187 const PropertyMap& config = getDeviceContext().getConfiguration();
Harry Cuttsf13161a2023-03-08 14:15:49 +0000188 mParameters.orientationAware = config.getBool("keyboard.orientationAware").value_or(false);
189 mParameters.handlesKeyRepeat = config.getBool("keyboard.handlesKeyRepeat").value_or(false);
190 mParameters.doNotWakeByDefault = config.getBool("keyboard.doNotWakeByDefault").value_or(false);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700191}
192
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000193void KeyboardInputMapper::dumpParameters(std::string& dump) const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700194 dump += INDENT3 "Parameters:\n";
195 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
196 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
197}
198
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700199std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) {
200 std::list<NotifyArgs> out = cancelAllDownKeys(when);
Prabir Pradhan84395e62022-10-26 19:52:00 +0000201 mHidUsageAccumulator.reset();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700202
203 resetLedState();
204
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700205 out += InputMapper::reset(when);
206 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700207}
208
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700209std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) {
210 std::list<NotifyArgs> out;
Prabir Pradhan84395e62022-10-26 19:52:00 +0000211 mHidUsageAccumulator.process(*rawEvent);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700212 switch (rawEvent->type) {
213 case EV_KEY: {
214 int32_t scanCode = rawEvent->code;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700215
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000216 if (isSupportedScanCode(scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700217 out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0,
Prabir Pradhan84395e62022-10-26 19:52:00 +0000218 scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700219 }
220 break;
221 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700222 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700223 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700224}
225
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700226std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down,
227 int32_t scanCode, int32_t usageCode) {
228 std::list<NotifyArgs> out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700229 int32_t keyCode;
230 int32_t keyMetaState;
231 uint32_t policyFlags;
Justin Chung71ddb432023-03-27 04:29:07 +0000232 int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700233
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800234 if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
235 &policyFlags)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700236 keyCode = AKEYCODE_UNKNOWN;
237 keyMetaState = mMetaState;
238 policyFlags = 0;
239 }
240
Arthur Hung2141d542022-08-23 07:45:21 +0000241 nsecs_t downTime = when;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000242 std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700243 if (down) {
244 // Rotate key codes according to orientation if needed.
245 if (mParameters.orientationAware) {
246 keyCode = rotateKeyCode(keyCode, getOrientation());
247 }
248
249 // Add key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000250 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700251 // key repeat, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000252 keyCode = mKeyDowns[*keyDownIndex].keyCode;
253 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000254 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700255 } else {
256 // key down
257 if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800258 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700259 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700260 }
261 if (policyFlags & POLICY_FLAG_GESTURE) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700262 out += getDeviceContext().cancelTouch(when, readTime);
Justin Chung71ddb432023-03-27 04:29:07 +0000263 flags |= AKEY_EVENT_FLAG_KEEP_TOUCH_MODE;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700264 }
265
266 KeyDown keyDown;
267 keyDown.keyCode = keyCode;
268 keyDown.scanCode = scanCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000269 keyDown.downTime = when;
Justin Chung71ddb432023-03-27 04:29:07 +0000270 keyDown.flags = flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700271 mKeyDowns.push_back(keyDown);
272 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700273 } else {
274 // Remove key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000275 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700276 // key up, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000277 keyCode = mKeyDowns[*keyDownIndex].keyCode;
278 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000279 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000280 mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700281 } else {
282 // key was not actually down
283 ALOGI("Dropping key up from device %s because the key was not down. "
284 "keyCode=%d, scanCode=%d",
285 getDeviceName().c_str(), keyCode, scanCode);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700286 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700287 }
288 }
289
290 if (updateMetaStateIfNeeded(keyCode, down)) {
291 // If global meta state changed send it along with the key.
292 // If it has not changed then we'll use what keymap gave us,
293 // since key replacement logic might temporarily reset a few
294 // meta bits for given key.
295 keyMetaState = mMetaState;
296 }
297
Vaibhav Devmurari16257862023-03-06 10:06:32 +0000298 // Any key down on an external keyboard should wake the device.
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700299 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
Powei Fengd041c5d2019-05-03 17:11:33 -0700300 // For internal keyboards and devices for which the default wake behavior is explicitly
301 // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
302 // wake key individually.
Vaibhav Devmurari16257862023-03-06 10:06:32 +0000303 if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700304 policyFlags |= POLICY_FLAG_WAKE;
305 }
306
307 if (mParameters.handlesKeyRepeat) {
308 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
309 }
310
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000311 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
312 mSource, getDisplayId(), policyFlags,
Justin Chung71ddb432023-03-27 04:29:07 +0000313 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags,
314 keyCode, scanCode, keyMetaState, downTime));
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700315 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700316}
317
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000318std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700319 size_t n = mKeyDowns.size();
320 for (size_t i = 0; i < n; i++) {
321 if (mKeyDowns[i].scanCode == scanCode) {
322 return i;
323 }
324 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000325 return {};
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700326}
327
328int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800329 return getDeviceContext().getKeyCodeState(keyCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700330}
331
332int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800333 return getDeviceContext().getScanCodeState(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700334}
335
Philip Junker4af3b3d2021-12-14 10:36:55 +0100336int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
337 return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
338}
339
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700340bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
341 const std::vector<int32_t>& keyCodes,
342 uint8_t* outFlags) {
343 return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700344}
345
346int32_t KeyboardInputMapper::getMetaState() {
347 return mMetaState;
348}
349
Arthur Hungcb40a002021-08-03 14:31:01 +0000350bool KeyboardInputMapper::updateMetaState(int32_t keyCode) {
351 if (!android::isMetaKey(keyCode) || !getDeviceContext().hasKeyCode(keyCode)) {
352 return false;
353 }
354
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700355 updateMetaStateIfNeeded(keyCode, false);
Arthur Hungcb40a002021-08-03 14:31:01 +0000356 return true;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700357}
358
359bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
360 int32_t oldMetaState = mMetaState;
361 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
arthurhungc903df12020-08-11 15:08:42 +0800362 int32_t metaStateChanged = oldMetaState ^ newMetaState;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700363 if (metaStateChanged) {
364 mMetaState = newMetaState;
arthurhungc903df12020-08-11 15:08:42 +0800365 constexpr int32_t allLedMetaState =
366 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
367 if ((metaStateChanged & allLedMetaState) != 0) {
368 getContext()->updateLedMetaState(newMetaState & allLedMetaState);
369 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700370 getContext()->updateGlobalMetaState();
371 }
372
373 return metaStateChanged;
374}
375
376void KeyboardInputMapper::resetLedState() {
377 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
378 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
379 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
380
381 updateLedState(true);
382}
383
384void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800385 ledState.avail = getDeviceContext().hasLed(led);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700386 ledState.on = false;
387}
388
389void KeyboardInputMapper::updateLedState(bool reset) {
Arthur Hungfb3cc112022-04-13 07:39:50 +0000390 // Clear the local led state then union the global led state.
391 mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
arthurhungc903df12020-08-11 15:08:42 +0800392 mMetaState |= getContext()->getLedMetaState();
Chris Yea52ade12020-08-27 16:49:20 -0700393
394 constexpr int32_t META_NUM = 3;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700395 const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
396 AKEYCODE_SCROLL_LOCK};
Chris Yea52ade12020-08-27 16:49:20 -0700397 const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
398 AMETA_SCROLL_LOCK_ON};
399 std::array<uint8_t, META_NUM> flags = {0, 0, 0};
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700400 bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
Chris Yea52ade12020-08-27 16:49:20 -0700401 // If the device doesn't have the physical meta key it shouldn't generate the corresponding
402 // meta state.
403 if (hasKeyLayout) {
404 for (int i = 0; i < META_NUM; i++) {
405 if (!flags[i]) {
406 mMetaState &= ~metaCodes[i];
407 }
408 }
409 }
410
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700411 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
412 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
413 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
414}
415
416void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
417 int32_t modifier, bool reset) {
418 if (ledState.avail) {
419 bool desiredState = (mMetaState & modifier) != 0;
420 if (reset || ledState.on != desiredState) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800421 getDeviceContext().setLedState(led, desiredState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700422 ledState.on = desiredState;
423 }
424 }
425}
426
427std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
428 if (mViewport) {
429 return std::make_optional(mViewport->displayId);
430 }
431 return std::nullopt;
432}
433
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700434std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
435 std::list<NotifyArgs> out;
Arthur Hung2141d542022-08-23 07:45:21 +0000436 size_t n = mKeyDowns.size();
437 for (size_t i = 0; i < n; i++) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000438 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when,
439 systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource,
Harry Cutts33476232023-01-30 19:57:29 +0000440 getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP,
Justin Chung71ddb432023-03-27 04:29:07 +0000441 mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED,
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000442 mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
443 mKeyDowns[i].downTime));
Arthur Hung2141d542022-08-23 07:45:21 +0000444 }
445 mKeyDowns.clear();
446 mMetaState = AMETA_NONE;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700447 return out;
Arthur Hung2141d542022-08-23 07:45:21 +0000448}
449
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700450} // namespace android