blob: 21245555a257ab72104fe6e1d558e5631a74884b [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
Harry Cutts91e7fa22024-02-09 12:50:07 +000023#include <ftl/enum.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000024#include <ui/Rotation.h>
25
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070026namespace android {
27
28// --- Static Definitions ---
29
Michael Wrighta9cf4192022-12-01 23:46:39 +000030static int32_t rotateKeyCode(int32_t keyCode, ui::Rotation orientation) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000031 static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = {
32 // key codes enumerated counter-clockwise with the original (unrotated) key first
33 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
34 {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
35 {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
36 {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
37 {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
38 {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
39 AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
40 {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
41 AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
42 {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
43 AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
44 {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
45 AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
46 };
47
Michael Wrighta9cf4192022-12-01 23:46:39 +000048 if (orientation != ui::ROTATION_0) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000049 for (const auto& rotation : KEYCODE_ROTATION_MAP) {
Michael Wrighta9cf4192022-12-01 23:46:39 +000050 if (rotation[static_cast<size_t>(ui::ROTATION_0)] == keyCode) {
51 return rotation[static_cast<size_t>(orientation)];
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070052 }
53 }
54 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +000055 return keyCode;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070056}
57
Prabir Pradhane1a41a82022-10-14 18:06:50 +000058static bool isSupportedScanCode(int32_t scanCode) {
59 // KeyboardInputMapper handles keys from keyboards, gamepads, and styluses.
60 return scanCode < BTN_MOUSE || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI) ||
61 scanCode == BTN_STYLUS || scanCode == BTN_STYLUS2 || scanCode == BTN_STYLUS3 ||
62 scanCode >= BTN_WHEEL;
Prabir Pradhan2197cb42022-10-11 02:56:14 +000063}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070064
Vaibhav Devmurari2681a812024-01-11 00:15:35 +000065static bool isMediaKey(int32_t keyCode) {
66 switch (keyCode) {
67 case AKEYCODE_MEDIA_PLAY:
68 case AKEYCODE_MEDIA_PAUSE:
69 case AKEYCODE_MEDIA_PLAY_PAUSE:
70 case AKEYCODE_MUTE:
71 case AKEYCODE_HEADSETHOOK:
72 case AKEYCODE_MEDIA_STOP:
73 case AKEYCODE_MEDIA_NEXT:
74 case AKEYCODE_MEDIA_PREVIOUS:
75 case AKEYCODE_MEDIA_REWIND:
76 case AKEYCODE_MEDIA_RECORD:
77 case AKEYCODE_MEDIA_FAST_FORWARD:
78 case AKEYCODE_MEDIA_SKIP_FORWARD:
79 case AKEYCODE_MEDIA_SKIP_BACKWARD:
80 case AKEYCODE_MEDIA_STEP_FORWARD:
81 case AKEYCODE_MEDIA_STEP_BACKWARD:
82 case AKEYCODE_MEDIA_AUDIO_TRACK:
83 case AKEYCODE_VOLUME_UP:
84 case AKEYCODE_VOLUME_DOWN:
85 case AKEYCODE_VOLUME_MUTE:
86 case AKEYCODE_TV_AUDIO_DESCRIPTION:
87 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
88 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
89 return true;
90 default:
91 return false;
92 }
93}
94
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070095// --- KeyboardInputMapper ---
96
Arpit Singh8e6fb252023-04-06 11:49:17 +000097KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext,
98 const InputReaderConfiguration& readerConfig,
99 uint32_t source, int32_t keyboardType)
100 : InputMapper(deviceContext, readerConfig), mSource(source), mKeyboardType(keyboardType) {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700101
Philip Junker4af3b3d2021-12-14 10:36:55 +0100102uint32_t KeyboardInputMapper::getSources() const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700103 return mSource;
104}
105
Michael Wrighta9cf4192022-12-01 23:46:39 +0000106ui::Rotation KeyboardInputMapper::getOrientation() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700107 if (mViewport) {
108 return mViewport->orientation;
109 }
Michael Wrighta9cf4192022-12-01 23:46:39 +0000110 return ui::ROTATION_0;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700111}
112
Linnan Li13bf76a2024-05-05 19:18:02 +0800113ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700114 if (mViewport) {
115 return mViewport->displayId;
116 }
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700117 return ui::LogicalDisplayId::INVALID;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700118}
119
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000120std::optional<KeyboardLayoutInfo> KeyboardInputMapper::getKeyboardLayoutInfo() const {
121 if (mKeyboardLayoutInfo) {
122 return mKeyboardLayoutInfo;
123 }
124 std::optional<RawLayoutInfo> layoutInfo = getDeviceContext().getRawLayoutInfo();
125 if (!layoutInfo) {
126 return std::nullopt;
127 }
128 return KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType);
129}
130
Harry Cuttsd02ea102023-03-17 18:21:30 +0000131void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700132 InputMapper::populateDeviceInfo(info);
133
Harry Cuttsd02ea102023-03-17 18:21:30 +0000134 info.setKeyboardType(mKeyboardType);
135 info.setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
Zixuan Qufecb6062022-11-12 04:44:31 +0000136
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000137 std::optional keyboardLayoutInfo = getKeyboardLayoutInfo();
138 if (keyboardLayoutInfo) {
139 info.setKeyboardLayoutInfo(*keyboardLayoutInfo);
Zixuan Qufecb6062022-11-12 04:44:31 +0000140 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700141}
142
143void KeyboardInputMapper::dump(std::string& dump) {
144 dump += INDENT2 "Keyboard Input Mapper:\n";
145 dumpParameters(dump);
146 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
Harry Cutts91e7fa22024-02-09 12:50:07 +0000147 dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(getOrientation()).c_str());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700148 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
149 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Zixuan Qufecb6062022-11-12 04:44:31 +0000150 dump += INDENT3 "KeyboardLayoutInfo: ";
151 if (mKeyboardLayoutInfo) {
152 dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n";
153 } else {
154 dump += "<not set>\n";
155 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700156}
157
158std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
Arpit Singhed6c3de2023-04-05 19:24:37 +0000159 const InputReaderConfiguration& readerConfig) {
Christine Franks1ba71cc2021-04-07 14:37:42 -0700160 if (getDeviceContext().getAssociatedViewport()) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800161 return getDeviceContext().getAssociatedViewport();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700162 }
163
164 // No associated display defined, try to find default display if orientationAware.
165 if (mParameters.orientationAware) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000166 return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700167 }
168
169 return std::nullopt;
170}
171
Arpit Singh4be4eef2023-03-28 14:26:01 +0000172std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
Arpit Singhed6c3de2023-04-05 19:24:37 +0000173 const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000174 ConfigurationChanges changes) {
Arpit Singh4be4eef2023-03-28 14:26:01 +0000175 std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700176
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000177 if (!changes.any()) { // first time only
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700178 // Configure basic parameters.
179 configureParameters();
180 }
181
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000182 if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000183 mViewport = findViewport(config);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700184 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000185
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000186 if (!changes.any() ||
187 changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) {
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000188 std::optional<KeyboardLayoutInfo> newKeyboardLayoutInfo =
Arpit Singhed6c3de2023-04-05 19:24:37 +0000189 getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000190 if (mKeyboardLayoutInfo != newKeyboardLayoutInfo) {
191 mKeyboardLayoutInfo = newKeyboardLayoutInfo;
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000192 // Also update keyboard layout overlay as soon as we find the new layout info
193 updateKeyboardLayoutOverlay();
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000194 bumpGeneration();
195 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000196 }
197
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000198 if (!changes.any() || changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUTS)) {
199 if (!getDeviceContext().getDeviceClasses().test(InputDeviceClass::VIRTUAL) &&
200 updateKeyboardLayoutOverlay()) {
201 bumpGeneration();
202 }
203 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700204 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700205}
206
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000207bool KeyboardInputMapper::updateKeyboardLayoutOverlay() {
208 std::shared_ptr<KeyCharacterMap> keyboardLayout =
209 getDeviceContext()
210 .getContext()
211 ->getPolicy()
212 ->getKeyboardLayoutOverlay(getDeviceContext().getDeviceIdentifier(),
213 getKeyboardLayoutInfo());
214 return getDeviceContext().setKeyboardLayoutOverlay(keyboardLayout);
215}
216
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700217void KeyboardInputMapper::configureParameters() {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800218 const PropertyMap& config = getDeviceContext().getConfiguration();
Harry Cuttsf13161a2023-03-08 14:15:49 +0000219 mParameters.orientationAware = config.getBool("keyboard.orientationAware").value_or(false);
220 mParameters.handlesKeyRepeat = config.getBool("keyboard.handlesKeyRepeat").value_or(false);
221 mParameters.doNotWakeByDefault = config.getBool("keyboard.doNotWakeByDefault").value_or(false);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700222}
223
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000224void KeyboardInputMapper::dumpParameters(std::string& dump) const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700225 dump += INDENT3 "Parameters:\n";
226 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
227 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
228}
229
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700230std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) {
231 std::list<NotifyArgs> out = cancelAllDownKeys(when);
Prabir Pradhan84395e62022-10-26 19:52:00 +0000232 mHidUsageAccumulator.reset();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700233
234 resetLedState();
235
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700236 out += InputMapper::reset(when);
237 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700238}
239
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700240std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) {
241 std::list<NotifyArgs> out;
Prabir Pradhan84395e62022-10-26 19:52:00 +0000242 mHidUsageAccumulator.process(*rawEvent);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700243 switch (rawEvent->type) {
244 case EV_KEY: {
245 int32_t scanCode = rawEvent->code;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700246
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000247 if (isSupportedScanCode(scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700248 out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0,
Prabir Pradhan84395e62022-10-26 19:52:00 +0000249 scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700250 }
251 break;
252 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700253 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700254 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700255}
256
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700257std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down,
258 int32_t scanCode, int32_t usageCode) {
259 std::list<NotifyArgs> out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700260 int32_t keyCode;
261 int32_t keyMetaState;
262 uint32_t policyFlags;
Justin Chung71ddb432023-03-27 04:29:07 +0000263 int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700264
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800265 if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
266 &policyFlags)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700267 keyCode = AKEYCODE_UNKNOWN;
268 keyMetaState = mMetaState;
269 policyFlags = 0;
270 }
271
Arthur Hung2141d542022-08-23 07:45:21 +0000272 nsecs_t downTime = when;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000273 std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700274 if (down) {
275 // Rotate key codes according to orientation if needed.
276 if (mParameters.orientationAware) {
277 keyCode = rotateKeyCode(keyCode, getOrientation());
278 }
279
280 // Add key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000281 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700282 // key repeat, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000283 keyCode = mKeyDowns[*keyDownIndex].keyCode;
284 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000285 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700286 } else {
287 // key down
288 if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800289 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700290 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700291 }
292 if (policyFlags & POLICY_FLAG_GESTURE) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700293 out += getDeviceContext().cancelTouch(when, readTime);
Justin Chung71ddb432023-03-27 04:29:07 +0000294 flags |= AKEY_EVENT_FLAG_KEEP_TOUCH_MODE;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700295 }
296
297 KeyDown keyDown;
298 keyDown.keyCode = keyCode;
299 keyDown.scanCode = scanCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000300 keyDown.downTime = when;
Justin Chung71ddb432023-03-27 04:29:07 +0000301 keyDown.flags = flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700302 mKeyDowns.push_back(keyDown);
303 }
Arpit Singh82e413e2023-10-10 19:30:58 +0000304 onKeyDownProcessed(downTime);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700305 } else {
306 // Remove key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000307 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700308 // key up, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000309 keyCode = mKeyDowns[*keyDownIndex].keyCode;
310 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000311 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000312 mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700313 } else {
314 // key was not actually down
315 ALOGI("Dropping key up from device %s because the key was not down. "
316 "keyCode=%d, scanCode=%d",
317 getDeviceName().c_str(), keyCode, scanCode);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700318 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700319 }
320 }
321
322 if (updateMetaStateIfNeeded(keyCode, down)) {
323 // If global meta state changed send it along with the key.
324 // If it has not changed then we'll use what keymap gave us,
325 // since key replacement logic might temporarily reset a few
326 // meta bits for given key.
327 keyMetaState = mMetaState;
328 }
329
Vaibhav Devmurari16257862023-03-06 10:06:32 +0000330 // Any key down on an external keyboard should wake the device.
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700331 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
Powei Fengd041c5d2019-05-03 17:11:33 -0700332 // For internal keyboards and devices for which the default wake behavior is explicitly
333 // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
334 // wake key individually.
Vaibhav Devmurari2681a812024-01-11 00:15:35 +0000335 if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
336 !(mKeyboardType != AINPUT_KEYBOARD_TYPE_ALPHABETIC && isMediaKey(keyCode))) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700337 policyFlags |= POLICY_FLAG_WAKE;
338 }
339
340 if (mParameters.handlesKeyRepeat) {
341 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
342 }
343
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000344 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
345 mSource, getDisplayId(), policyFlags,
Justin Chung71ddb432023-03-27 04:29:07 +0000346 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags,
347 keyCode, scanCode, keyMetaState, downTime));
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700348 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700349}
350
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000351std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700352 size_t n = mKeyDowns.size();
353 for (size_t i = 0; i < n; i++) {
354 if (mKeyDowns[i].scanCode == scanCode) {
355 return i;
356 }
357 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000358 return {};
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700359}
360
361int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800362 return getDeviceContext().getKeyCodeState(keyCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700363}
364
365int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800366 return getDeviceContext().getScanCodeState(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700367}
368
Philip Junker4af3b3d2021-12-14 10:36:55 +0100369int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
370 return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
371}
372
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700373bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
374 const std::vector<int32_t>& keyCodes,
375 uint8_t* outFlags) {
376 return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700377}
378
379int32_t KeyboardInputMapper::getMetaState() {
380 return mMetaState;
381}
382
Arthur Hungcb40a002021-08-03 14:31:01 +0000383bool KeyboardInputMapper::updateMetaState(int32_t keyCode) {
384 if (!android::isMetaKey(keyCode) || !getDeviceContext().hasKeyCode(keyCode)) {
385 return false;
386 }
387
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700388 updateMetaStateIfNeeded(keyCode, false);
Arthur Hungcb40a002021-08-03 14:31:01 +0000389 return true;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700390}
391
392bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
393 int32_t oldMetaState = mMetaState;
394 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
arthurhungc903df12020-08-11 15:08:42 +0800395 int32_t metaStateChanged = oldMetaState ^ newMetaState;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700396 if (metaStateChanged) {
397 mMetaState = newMetaState;
arthurhungc903df12020-08-11 15:08:42 +0800398 constexpr int32_t allLedMetaState =
399 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
400 if ((metaStateChanged & allLedMetaState) != 0) {
401 getContext()->updateLedMetaState(newMetaState & allLedMetaState);
402 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700403 getContext()->updateGlobalMetaState();
404 }
405
406 return metaStateChanged;
407}
408
409void KeyboardInputMapper::resetLedState() {
410 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
411 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
412 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
413
414 updateLedState(true);
415}
416
417void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800418 ledState.avail = getDeviceContext().hasLed(led);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700419 ledState.on = false;
420}
421
422void KeyboardInputMapper::updateLedState(bool reset) {
Arthur Hungfb3cc112022-04-13 07:39:50 +0000423 // Clear the local led state then union the global led state.
424 mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
arthurhungc903df12020-08-11 15:08:42 +0800425 mMetaState |= getContext()->getLedMetaState();
Chris Yea52ade12020-08-27 16:49:20 -0700426
427 constexpr int32_t META_NUM = 3;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700428 const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
429 AKEYCODE_SCROLL_LOCK};
Chris Yea52ade12020-08-27 16:49:20 -0700430 const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
431 AMETA_SCROLL_LOCK_ON};
432 std::array<uint8_t, META_NUM> flags = {0, 0, 0};
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700433 bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
Chris Yea52ade12020-08-27 16:49:20 -0700434 // If the device doesn't have the physical meta key it shouldn't generate the corresponding
435 // meta state.
436 if (hasKeyLayout) {
437 for (int i = 0; i < META_NUM; i++) {
438 if (!flags[i]) {
439 mMetaState &= ~metaCodes[i];
440 }
441 }
442 }
443
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700444 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
445 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
446 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
447}
448
449void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
450 int32_t modifier, bool reset) {
451 if (ledState.avail) {
452 bool desiredState = (mMetaState & modifier) != 0;
453 if (reset || ledState.on != desiredState) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800454 getDeviceContext().setLedState(led, desiredState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700455 ledState.on = desiredState;
456 }
457 }
458}
459
Linnan Li13bf76a2024-05-05 19:18:02 +0800460std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700461 if (mViewport) {
462 return std::make_optional(mViewport->displayId);
463 }
464 return std::nullopt;
465}
466
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700467std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
468 std::list<NotifyArgs> out;
Arthur Hung2141d542022-08-23 07:45:21 +0000469 size_t n = mKeyDowns.size();
470 for (size_t i = 0; i < n; i++) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000471 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when,
472 systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource,
Harry Cutts33476232023-01-30 19:57:29 +0000473 getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP,
Justin Chung71ddb432023-03-27 04:29:07 +0000474 mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED,
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000475 mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
476 mKeyDowns[i].downTime));
Arthur Hung2141d542022-08-23 07:45:21 +0000477 }
478 mKeyDowns.clear();
479 mMetaState = AMETA_NONE;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700480 return out;
Arthur Hung2141d542022-08-23 07:45:21 +0000481}
482
Arpit Singh82e413e2023-10-10 19:30:58 +0000483void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
Arpit Singha5ea7c12023-07-05 15:39:25 +0000484 InputReaderContext& context = *getContext();
Arpit Singh82e413e2023-10-10 19:30:58 +0000485 context.setLastKeyDownTimestamp(downTime);
Prabir Pradhan2120b9e2024-05-04 00:06:37 +0000486 // TODO(b/338652288): Move cursor fading logic into PointerChoreographer.
Arpit Singha5ea7c12023-07-05 15:39:25 +0000487 // Ignore meta keys or multiple simultaneous down keys as they are likely to be keyboard
488 // shortcuts
489 bool shouldHideCursor = mKeyDowns.size() == 1 && !isMetaKey(mKeyDowns[0].keyCode);
490 if (shouldHideCursor && context.getPolicy()->isInputMethodConnectionActive()) {
Arpit Singha5ea7c12023-07-05 15:39:25 +0000491 context.setPreventingTouchpadTaps(true);
Arpit Singhb3b3f732023-07-04 14:30:05 +0000492 }
493}
494
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700495} // namespace android