blob: 585f61a3ebf7a25cc25306ebb2fed8478147562f [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>
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000024#include <input/KeyboardClassifier.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000025#include <ui/Rotation.h>
26
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070027namespace android {
28
29// --- Static Definitions ---
30
Michael Wrighta9cf4192022-12-01 23:46:39 +000031static int32_t rotateKeyCode(int32_t keyCode, ui::Rotation orientation) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000032 static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = {
33 // key codes enumerated counter-clockwise with the original (unrotated) key first
34 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
35 {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
36 {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
37 {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
38 {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
39 {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
40 AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
41 {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
42 AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
43 {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
44 AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
45 {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
46 AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
47 };
48
Michael Wrighta9cf4192022-12-01 23:46:39 +000049 if (orientation != ui::ROTATION_0) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +000050 for (const auto& rotation : KEYCODE_ROTATION_MAP) {
Michael Wrighta9cf4192022-12-01 23:46:39 +000051 if (rotation[static_cast<size_t>(ui::ROTATION_0)] == keyCode) {
52 return rotation[static_cast<size_t>(orientation)];
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070053 }
54 }
55 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +000056 return keyCode;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070057}
58
Prabir Pradhane1a41a82022-10-14 18:06:50 +000059static bool isSupportedScanCode(int32_t scanCode) {
60 // KeyboardInputMapper handles keys from keyboards, gamepads, and styluses.
61 return scanCode < BTN_MOUSE || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI) ||
62 scanCode == BTN_STYLUS || scanCode == BTN_STYLUS2 || scanCode == BTN_STYLUS3 ||
63 scanCode >= BTN_WHEEL;
Prabir Pradhan2197cb42022-10-11 02:56:14 +000064}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070065
Vaibhav Devmurari2681a812024-01-11 00:15:35 +000066static bool isMediaKey(int32_t keyCode) {
67 switch (keyCode) {
68 case AKEYCODE_MEDIA_PLAY:
69 case AKEYCODE_MEDIA_PAUSE:
70 case AKEYCODE_MEDIA_PLAY_PAUSE:
71 case AKEYCODE_MUTE:
72 case AKEYCODE_HEADSETHOOK:
73 case AKEYCODE_MEDIA_STOP:
74 case AKEYCODE_MEDIA_NEXT:
75 case AKEYCODE_MEDIA_PREVIOUS:
76 case AKEYCODE_MEDIA_REWIND:
77 case AKEYCODE_MEDIA_RECORD:
78 case AKEYCODE_MEDIA_FAST_FORWARD:
79 case AKEYCODE_MEDIA_SKIP_FORWARD:
80 case AKEYCODE_MEDIA_SKIP_BACKWARD:
81 case AKEYCODE_MEDIA_STEP_FORWARD:
82 case AKEYCODE_MEDIA_STEP_BACKWARD:
83 case AKEYCODE_MEDIA_AUDIO_TRACK:
84 case AKEYCODE_VOLUME_UP:
85 case AKEYCODE_VOLUME_DOWN:
86 case AKEYCODE_VOLUME_MUTE:
87 case AKEYCODE_TV_AUDIO_DESCRIPTION:
88 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
89 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
90 return true;
91 default:
92 return false;
93 }
94}
95
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070096// --- KeyboardInputMapper ---
97
Arpit Singh8e6fb252023-04-06 11:49:17 +000098KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext,
99 const InputReaderConfiguration& readerConfig,
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000100 uint32_t source)
Prabir Pradhan38636652024-07-23 21:59:36 +0000101 : InputMapper(deviceContext, readerConfig), mMapperSource(source) {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700102
Philip Junker4af3b3d2021-12-14 10:36:55 +0100103uint32_t KeyboardInputMapper::getSources() const {
Prabir Pradhan38636652024-07-23 21:59:36 +0000104 return mMapperSource;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700105}
106
Michael Wrighta9cf4192022-12-01 23:46:39 +0000107ui::Rotation KeyboardInputMapper::getOrientation() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700108 if (mViewport) {
109 return mViewport->orientation;
110 }
Michael Wrighta9cf4192022-12-01 23:46:39 +0000111 return ui::ROTATION_0;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700112}
113
Linnan Li13bf76a2024-05-05 19:18:02 +0800114ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700115 if (mViewport) {
116 return mViewport->displayId;
117 }
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700118 return ui::LogicalDisplayId::INVALID;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700119}
120
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000121std::optional<KeyboardLayoutInfo> KeyboardInputMapper::getKeyboardLayoutInfo() const {
122 if (mKeyboardLayoutInfo) {
123 return mKeyboardLayoutInfo;
124 }
125 std::optional<RawLayoutInfo> layoutInfo = getDeviceContext().getRawLayoutInfo();
126 if (!layoutInfo) {
127 return std::nullopt;
128 }
129 return KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType);
130}
131
Harry Cuttsd02ea102023-03-17 18:21:30 +0000132void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700133 InputMapper::populateDeviceInfo(info);
134
Linnan Lid78dd9b2024-10-15 15:50:01 +0000135 if (const auto kcm = getDeviceContext().getKeyCharacterMap(); kcm != nullptr) {
136 info.setKeyCharacterMap(std::make_unique<KeyCharacterMap>(*kcm));
137 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000138
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000139 std::optional keyboardLayoutInfo = getKeyboardLayoutInfo();
140 if (keyboardLayoutInfo) {
141 info.setKeyboardLayoutInfo(*keyboardLayoutInfo);
Zixuan Qufecb6062022-11-12 04:44:31 +0000142 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700143}
144
145void KeyboardInputMapper::dump(std::string& dump) {
146 dump += INDENT2 "Keyboard Input Mapper:\n";
147 dumpParameters(dump);
Harry Cutts91e7fa22024-02-09 12:50:07 +0000148 dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(getOrientation()).c_str());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700149 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
150 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Zixuan Qufecb6062022-11-12 04:44:31 +0000151 dump += INDENT3 "KeyboardLayoutInfo: ";
152 if (mKeyboardLayoutInfo) {
153 dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n";
154 } else {
155 dump += "<not set>\n";
156 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700157}
158
159std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
Arpit Singhed6c3de2023-04-05 19:24:37 +0000160 const InputReaderConfiguration& readerConfig) {
Christine Franks1ba71cc2021-04-07 14:37:42 -0700161 if (getDeviceContext().getAssociatedViewport()) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800162 return getDeviceContext().getAssociatedViewport();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700163 }
164
165 // No associated display defined, try to find default display if orientationAware.
166 if (mParameters.orientationAware) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000167 return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700168 }
169
170 return std::nullopt;
171}
172
Arpit Singh4be4eef2023-03-28 14:26:01 +0000173std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
Arpit Singhed6c3de2023-04-05 19:24:37 +0000174 const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000175 ConfigurationChanges changes) {
Arpit Singh4be4eef2023-03-28 14:26:01 +0000176 std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700177
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000178 if (!changes.any()) { // first time only
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700179 // Configure basic parameters.
180 configureParameters();
181 }
182
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000183 if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000184 mViewport = findViewport(config);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700185 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000186
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000187 if (!changes.any() ||
188 changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) {
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000189 std::optional<KeyboardLayoutInfo> newKeyboardLayoutInfo =
Arpit Singhed6c3de2023-04-05 19:24:37 +0000190 getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000191 if (mKeyboardLayoutInfo != newKeyboardLayoutInfo) {
192 mKeyboardLayoutInfo = newKeyboardLayoutInfo;
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000193 // Also update keyboard layout overlay as soon as we find the new layout info
194 updateKeyboardLayoutOverlay();
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +0000195 bumpGeneration();
196 }
Zixuan Qufecb6062022-11-12 04:44:31 +0000197 }
198
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000199 if (!changes.any() || changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUTS)) {
200 if (!getDeviceContext().getDeviceClasses().test(InputDeviceClass::VIRTUAL) &&
201 updateKeyboardLayoutOverlay()) {
202 bumpGeneration();
203 }
204 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700205 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700206}
207
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000208bool KeyboardInputMapper::updateKeyboardLayoutOverlay() {
209 std::shared_ptr<KeyCharacterMap> keyboardLayout =
210 getDeviceContext()
211 .getContext()
212 ->getPolicy()
213 ->getKeyboardLayoutOverlay(getDeviceContext().getDeviceIdentifier(),
214 getKeyboardLayoutInfo());
215 return getDeviceContext().setKeyboardLayoutOverlay(keyboardLayout);
216}
217
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700218void KeyboardInputMapper::configureParameters() {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800219 const PropertyMap& config = getDeviceContext().getConfiguration();
Harry Cuttsf13161a2023-03-08 14:15:49 +0000220 mParameters.orientationAware = config.getBool("keyboard.orientationAware").value_or(false);
221 mParameters.handlesKeyRepeat = config.getBool("keyboard.handlesKeyRepeat").value_or(false);
222 mParameters.doNotWakeByDefault = config.getBool("keyboard.doNotWakeByDefault").value_or(false);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700223}
224
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000225void KeyboardInputMapper::dumpParameters(std::string& dump) const {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700226 dump += INDENT3 "Parameters:\n";
227 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
228 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
229}
230
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700231std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) {
232 std::list<NotifyArgs> out = cancelAllDownKeys(when);
Prabir Pradhan84395e62022-10-26 19:52:00 +0000233 mHidUsageAccumulator.reset();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700234
235 resetLedState();
236
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700237 out += InputMapper::reset(when);
238 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700239}
240
Harry Cuttsa32a1192024-06-04 15:10:31 +0000241std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent& rawEvent) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700242 std::list<NotifyArgs> out;
Harry Cuttsa32a1192024-06-04 15:10:31 +0000243 mHidUsageAccumulator.process(rawEvent);
244 switch (rawEvent.type) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700245 case EV_KEY: {
Harry Cuttsa32a1192024-06-04 15:10:31 +0000246 int32_t scanCode = rawEvent.code;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700247
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000248 if (isSupportedScanCode(scanCode)) {
Harry Cuttsa32a1192024-06-04 15:10:31 +0000249 out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0,
Prabir Pradhan84395e62022-10-26 19:52:00 +0000250 scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700251 }
252 break;
253 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700254 }
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700255 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700256}
257
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700258std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down,
259 int32_t scanCode, int32_t usageCode) {
260 std::list<NotifyArgs> out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700261 int32_t keyCode;
262 int32_t keyMetaState;
263 uint32_t policyFlags;
Justin Chung71ddb432023-03-27 04:29:07 +0000264 int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700265
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800266 if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
267 &policyFlags)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700268 keyCode = AKEYCODE_UNKNOWN;
269 keyMetaState = mMetaState;
270 policyFlags = 0;
271 }
272
Arthur Hung2141d542022-08-23 07:45:21 +0000273 nsecs_t downTime = when;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000274 std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700275 if (down) {
276 // Rotate key codes according to orientation if needed.
277 if (mParameters.orientationAware) {
278 keyCode = rotateKeyCode(keyCode, getOrientation());
279 }
280
281 // Add key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000282 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700283 // key repeat, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000284 keyCode = mKeyDowns[*keyDownIndex].keyCode;
285 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000286 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700287 } else {
288 // key down
289 if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800290 getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700291 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700292 }
293 if (policyFlags & POLICY_FLAG_GESTURE) {
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700294 out += getDeviceContext().cancelTouch(when, readTime);
Justin Chung71ddb432023-03-27 04:29:07 +0000295 flags |= AKEY_EVENT_FLAG_KEEP_TOUCH_MODE;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700296 }
297
298 KeyDown keyDown;
299 keyDown.keyCode = keyCode;
300 keyDown.scanCode = scanCode;
Arthur Hung2141d542022-08-23 07:45:21 +0000301 keyDown.downTime = when;
Justin Chung71ddb432023-03-27 04:29:07 +0000302 keyDown.flags = flags;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700303 mKeyDowns.push_back(keyDown);
304 }
Arpit Singh82e413e2023-10-10 19:30:58 +0000305 onKeyDownProcessed(downTime);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700306 } else {
307 // Remove key down.
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000308 if (keyDownIndex) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700309 // key up, be sure to use same keycode as before in case of rotation
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000310 keyCode = mKeyDowns[*keyDownIndex].keyCode;
311 downTime = mKeyDowns[*keyDownIndex].downTime;
Justin Chung71ddb432023-03-27 04:29:07 +0000312 flags = mKeyDowns[*keyDownIndex].flags;
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000313 mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700314 } else {
315 // key was not actually down
316 ALOGI("Dropping key up from device %s because the key was not down. "
317 "keyCode=%d, scanCode=%d",
318 getDeviceName().c_str(), keyCode, scanCode);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700319 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700320 }
321 }
322
323 if (updateMetaStateIfNeeded(keyCode, down)) {
324 // If global meta state changed send it along with the key.
325 // If it has not changed then we'll use what keymap gave us,
326 // since key replacement logic might temporarily reset a few
327 // meta bits for given key.
328 keyMetaState = mMetaState;
329 }
330
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000331 DeviceId deviceId = getDeviceId();
332
333 // On first down: Process key for keyboard classification (will send reconfiguration if the
334 // keyboard type change)
335 if (down && !keyDownIndex) {
336 KeyboardClassifier& classifier = getDeviceContext().getContext()->getKeyboardClassifier();
337 classifier.processKey(deviceId, scanCode, keyMetaState);
338 getDeviceContext().setKeyboardType(classifier.getKeyboardType(deviceId));
339 }
340
341 KeyboardType keyboardType = getDeviceContext().getKeyboardType();
Vaibhav Devmurari16257862023-03-06 10:06:32 +0000342 // Any key down on an external keyboard should wake the device.
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700343 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
Powei Fengd041c5d2019-05-03 17:11:33 -0700344 // For internal keyboards and devices for which the default wake behavior is explicitly
345 // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
346 // wake key individually.
Vaibhav Devmurari2681a812024-01-11 00:15:35 +0000347 if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000348 !(keyboardType != KeyboardType::ALPHABETIC && isMediaKey(keyCode))) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700349 policyFlags |= POLICY_FLAG_WAKE;
350 }
351
352 if (mParameters.handlesKeyRepeat) {
353 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
354 }
355
Prabir Pradhan38636652024-07-23 21:59:36 +0000356 out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId,
357 getEventSource(), getDisplayId(), policyFlags,
Justin Chung71ddb432023-03-27 04:29:07 +0000358 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags,
359 keyCode, scanCode, keyMetaState, downTime));
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700360 return out;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700361}
362
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000363std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700364 size_t n = mKeyDowns.size();
365 for (size_t i = 0; i < n; i++) {
366 if (mKeyDowns[i].scanCode == scanCode) {
367 return i;
368 }
369 }
Prabir Pradhan2197cb42022-10-11 02:56:14 +0000370 return {};
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700371}
372
373int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800374 return getDeviceContext().getKeyCodeState(keyCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700375}
376
377int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800378 return getDeviceContext().getScanCodeState(scanCode);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700379}
380
Philip Junker4af3b3d2021-12-14 10:36:55 +0100381int32_t KeyboardInputMapper::getKeyCodeForKeyLocation(int32_t locationKeyCode) const {
382 return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
383}
384
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700385bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
386 const std::vector<int32_t>& keyCodes,
387 uint8_t* outFlags) {
388 return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700389}
390
391int32_t KeyboardInputMapper::getMetaState() {
392 return mMetaState;
393}
394
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700395bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
396 int32_t oldMetaState = mMetaState;
397 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
arthurhungc903df12020-08-11 15:08:42 +0800398 int32_t metaStateChanged = oldMetaState ^ newMetaState;
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700399 if (metaStateChanged) {
400 mMetaState = newMetaState;
arthurhungc903df12020-08-11 15:08:42 +0800401 constexpr int32_t allLedMetaState =
402 AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
403 if ((metaStateChanged & allLedMetaState) != 0) {
404 getContext()->updateLedMetaState(newMetaState & allLedMetaState);
405 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700406 getContext()->updateGlobalMetaState();
407 }
408
409 return metaStateChanged;
410}
411
412void KeyboardInputMapper::resetLedState() {
413 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
414 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
415 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
416
417 updateLedState(true);
418}
419
420void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800421 ledState.avail = getDeviceContext().hasLed(led);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700422 ledState.on = false;
423}
424
425void KeyboardInputMapper::updateLedState(bool reset) {
Arthur Hungfb3cc112022-04-13 07:39:50 +0000426 // Clear the local led state then union the global led state.
427 mMetaState &= ~(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON);
arthurhungc903df12020-08-11 15:08:42 +0800428 mMetaState |= getContext()->getLedMetaState();
Chris Yea52ade12020-08-27 16:49:20 -0700429
Vaibhav Devmurari5c4f7982024-10-07 09:41:23 +0000430 std::vector<int32_t> keyCodesToCheck{AKEYCODE_NUM_LOCK, AKEYCODE_SCROLL_LOCK};
431 std::vector<int32_t> metaCodes{AMETA_NUM_LOCK_ON, AMETA_SCROLL_LOCK_ON};
432 // Check for physical CapsLock key only for non-alphabetic keyboards. For Alphabetic
433 // keyboards, we will allow Caps Lock even if there is no physical CapsLock key.
434 if (getDeviceContext().getKeyboardType() != KeyboardType::ALPHABETIC) {
435 keyCodesToCheck.push_back(AKEYCODE_CAPS_LOCK);
436 metaCodes.push_back(AMETA_CAPS_LOCK_ON);
437 }
438 size_t size = keyCodesToCheck.size();
439 std::vector<uint8_t> flags(size, 0);
440 bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodesToCheck, flags.data());
Chris Yea52ade12020-08-27 16:49:20 -0700441 // If the device doesn't have the physical meta key it shouldn't generate the corresponding
442 // meta state.
443 if (hasKeyLayout) {
Vaibhav Devmurari5c4f7982024-10-07 09:41:23 +0000444 for (size_t i = 0; i < size; i++) {
Chris Yea52ade12020-08-27 16:49:20 -0700445 if (!flags[i]) {
446 mMetaState &= ~metaCodes[i];
447 }
448 }
449 }
450
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700451 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
452 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
453 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
454}
455
456void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
457 int32_t modifier, bool reset) {
458 if (ledState.avail) {
459 bool desiredState = (mMetaState & modifier) != 0;
460 if (reset || ledState.on != desiredState) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800461 getDeviceContext().setLedState(led, desiredState);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700462 ledState.on = desiredState;
463 }
464 }
465}
466
Linnan Li13bf76a2024-05-05 19:18:02 +0800467std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700468 if (mViewport) {
469 return std::make_optional(mViewport->displayId);
470 }
471 return std::nullopt;
472}
473
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700474std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) {
475 std::list<NotifyArgs> out;
Arthur Hung2141d542022-08-23 07:45:21 +0000476 size_t n = mKeyDowns.size();
477 for (size_t i = 0; i < n; i++) {
Prabir Pradhan38636652024-07-23 21:59:36 +0000478 out.emplace_back(
479 NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC),
480 getDeviceId(), getEventSource(), getDisplayId(), /*policyFlags=*/0,
481 AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED,
482 mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE,
483 mKeyDowns[i].downTime));
Arthur Hung2141d542022-08-23 07:45:21 +0000484 }
485 mKeyDowns.clear();
486 mMetaState = AMETA_NONE;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700487 return out;
Arthur Hung2141d542022-08-23 07:45:21 +0000488}
489
Arpit Singh82e413e2023-10-10 19:30:58 +0000490void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
Arpit Singha5ea7c12023-07-05 15:39:25 +0000491 InputReaderContext& context = *getContext();
Arpit Singh82e413e2023-10-10 19:30:58 +0000492 context.setLastKeyDownTimestamp(downTime);
Arpit Singhb3b3f732023-07-04 14:30:05 +0000493}
494
Prabir Pradhan38636652024-07-23 21:59:36 +0000495uint32_t KeyboardInputMapper::getEventSource() const {
496 // For all input events generated by this mapper, use the source that's shared across all
497 // KeyboardInputMappers for this device in case there are more than one.
498 static constexpr auto ALL_KEYBOARD_SOURCES =
499 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD;
500 const auto deviceSources = getDeviceContext().getDeviceSources();
501 LOG_ALWAYS_FATAL_IF((deviceSources & mMapperSource) != mMapperSource);
502 return deviceSources & ALL_KEYBOARD_SOURCES;
503}
504
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700505} // namespace android