1 /*
2 * Copyright (C) 2008 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
17 #define LOG_TAG "KeyCharacterMap"
18
19 #include <stdlib.h>
20 #include <string.h>
21
22 #ifdef __linux__
23 #include <binder/Parcel.h>
24 #endif
25 #include <android/keycodes.h>
26 #include <attestation/HmacKeyManager.h>
27 #include <input/InputEventLabels.h>
28 #include <input/KeyCharacterMap.h>
29 #include <input/Keyboard.h>
30
31 #include <gui/constants.h>
32 #include <utils/Errors.h>
33 #include <utils/Log.h>
34 #include <utils/Timers.h>
35 #include <utils/Tokenizer.h>
36
37 // Enables debug output for the parser.
38 #define DEBUG_PARSER 0
39
40 // Enables debug output for parser performance.
41 #define DEBUG_PARSER_PERFORMANCE 0
42
43 // Enables debug output for mapping.
44 #define DEBUG_MAPPING 0
45
46 namespace android {
47
48 static const char* WHITESPACE = " \t\r";
49 static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:";
50
51 struct Modifier {
52 const char* label;
53 int32_t metaState;
54 };
55 static const Modifier modifiers[] = {
56 { "shift", AMETA_SHIFT_ON },
57 { "lshift", AMETA_SHIFT_LEFT_ON },
58 { "rshift", AMETA_SHIFT_RIGHT_ON },
59 { "alt", AMETA_ALT_ON },
60 { "lalt", AMETA_ALT_LEFT_ON },
61 { "ralt", AMETA_ALT_RIGHT_ON },
62 { "ctrl", AMETA_CTRL_ON },
63 { "lctrl", AMETA_CTRL_LEFT_ON },
64 { "rctrl", AMETA_CTRL_RIGHT_ON },
65 { "meta", AMETA_META_ON },
66 { "lmeta", AMETA_META_LEFT_ON },
67 { "rmeta", AMETA_META_RIGHT_ON },
68 { "sym", AMETA_SYM_ON },
69 { "fn", AMETA_FUNCTION_ON },
70 { "capslock", AMETA_CAPS_LOCK_ON },
71 { "numlock", AMETA_NUM_LOCK_ON },
72 { "scrolllock", AMETA_SCROLL_LOCK_ON },
73 };
74
75 #if DEBUG_MAPPING
toString(const char16_t * chars,size_t numChars)76 static String8 toString(const char16_t* chars, size_t numChars) {
77 String8 result;
78 for (size_t i = 0; i < numChars; i++) {
79 result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]);
80 }
81 return result;
82 }
83 #endif
84
85
86 // --- KeyCharacterMap ---
87
KeyCharacterMap(const std::string & filename)88 KeyCharacterMap::KeyCharacterMap(const std::string& filename) : mLoadFileName(filename) {}
89
load(const std::string & filename,Format format)90 base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename,
91 Format format) {
92 Tokenizer* tokenizer;
93 status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
94 if (status) {
95 return Errorf("Error {} opening key character map file {}.", status, filename.c_str());
96 }
97 std::shared_ptr<KeyCharacterMap> map =
98 std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
99 if (!map.get()) {
100 ALOGE("Error allocating key character map.");
101 return Errorf("Error allocating key character map.");
102 }
103 std::unique_ptr<Tokenizer> t(tokenizer);
104 status = map->load(t.get(), format);
105 if (status == OK) {
106 return map;
107 }
108 return Errorf("Load KeyCharacterMap failed {}.", status);
109 }
110
loadContents(const std::string & filename,const char * contents,Format format)111 base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::loadContents(
112 const std::string& filename, const char* contents, Format format) {
113 Tokenizer* tokenizer;
114 status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer);
115 if (status) {
116 ALOGE("Error %d opening key character map.", status);
117 return Errorf("Error {} opening key character map.", status);
118 }
119 std::shared_ptr<KeyCharacterMap> map =
120 std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
121 if (!map.get()) {
122 ALOGE("Error allocating key character map.");
123 return Errorf("Error allocating key character map.");
124 }
125 std::unique_ptr<Tokenizer> t(tokenizer);
126 status = map->load(t.get(), format);
127 if (status == OK) {
128 return map;
129 }
130 return Errorf("Load KeyCharacterMap failed {}.", status);
131 }
132
load(Tokenizer * tokenizer,Format format)133 status_t KeyCharacterMap::load(Tokenizer* tokenizer, Format format) {
134 status_t status = OK;
135 #if DEBUG_PARSER_PERFORMANCE
136 nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
137 #endif
138 Parser parser(this, tokenizer, format);
139 status = parser.parse();
140 #if DEBUG_PARSER_PERFORMANCE
141 nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
142 ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
143 tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0);
144 #endif
145 if (status != OK) {
146 ALOGE("Loading KeyCharacterMap failed with status %s", statusToString(status).c_str());
147 }
148 return status;
149 }
150
clear()151 void KeyCharacterMap::clear() {
152 mKeysByScanCode.clear();
153 mKeysByUsageCode.clear();
154 mKeys.clear();
155 mLayoutOverlayApplied = false;
156 mType = KeyboardType::UNKNOWN;
157 }
158
reloadBaseFromFile()159 status_t KeyCharacterMap::reloadBaseFromFile() {
160 clear();
161 Tokenizer* tokenizer;
162 status_t status = Tokenizer::open(String8(mLoadFileName.c_str()), &tokenizer);
163 if (status) {
164 ALOGE("Error %s opening key character map file %s.", statusToString(status).c_str(),
165 mLoadFileName.c_str());
166 return status;
167 }
168 std::unique_ptr<Tokenizer> t(tokenizer);
169 return load(t.get(), KeyCharacterMap::Format::BASE);
170 }
171
combine(const KeyCharacterMap & overlay)172 void KeyCharacterMap::combine(const KeyCharacterMap& overlay) {
173 if (mLayoutOverlayApplied) {
174 reloadBaseFromFile();
175 }
176 for (const auto& [keyCode, key] : overlay.mKeys) {
177 mKeys.insert_or_assign(keyCode, key);
178 }
179
180 for (const auto& [fromScanCode, toAndroidKeyCode] : overlay.mKeysByScanCode) {
181 mKeysByScanCode.insert_or_assign(fromScanCode, toAndroidKeyCode);
182 }
183
184 for (const auto& [fromHidUsageCode, toAndroidKeyCode] : overlay.mKeysByUsageCode) {
185 mKeysByUsageCode.insert_or_assign(fromHidUsageCode, toAndroidKeyCode);
186 }
187 mLayoutOverlayApplied = true;
188 }
189
clearLayoutOverlay()190 void KeyCharacterMap::clearLayoutOverlay() {
191 if (mLayoutOverlayApplied) {
192 reloadBaseFromFile();
193 mLayoutOverlayApplied = false;
194 }
195 }
196
getKeyboardType() const197 KeyCharacterMap::KeyboardType KeyCharacterMap::getKeyboardType() const {
198 return mType;
199 }
200
getLoadFileName() const201 const std::string KeyCharacterMap::getLoadFileName() const {
202 return mLoadFileName;
203 }
204
getDisplayLabel(int32_t keyCode) const205 char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
206 char16_t result = 0;
207 const Key* key = getKey(keyCode);
208 if (key != nullptr) {
209 result = key->label;
210 }
211 #if DEBUG_MAPPING
212 ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result);
213 #endif
214 return result;
215 }
216
getNumber(int32_t keyCode) const217 char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
218 char16_t result = 0;
219 const Key* key = getKey(keyCode);
220 if (key != nullptr) {
221 result = key->number;
222 }
223 #if DEBUG_MAPPING
224 ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result);
225 #endif
226 return result;
227 }
228
getCharacter(int32_t keyCode,int32_t metaState) const229 char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
230 char16_t result = 0;
231 const Behavior* behavior = getKeyBehavior(keyCode, metaState);
232 if (behavior != nullptr) {
233 result = behavior->character;
234 }
235 #if DEBUG_MAPPING
236 ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
237 #endif
238 return result;
239 }
240
getFallbackAction(int32_t keyCode,int32_t metaState,FallbackAction * outFallbackAction) const241 bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
242 FallbackAction* outFallbackAction) const {
243 outFallbackAction->keyCode = 0;
244 outFallbackAction->metaState = 0;
245
246 bool result = false;
247 const Behavior* behavior = getKeyBehavior(keyCode, metaState);
248 if (behavior != nullptr) {
249 if (behavior->fallbackKeyCode) {
250 outFallbackAction->keyCode = behavior->fallbackKeyCode;
251 outFallbackAction->metaState = metaState & ~behavior->metaState;
252 result = true;
253 }
254 }
255 #if DEBUG_MAPPING
256 ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
257 "fallback keyCode=%d, fallback metaState=0x%08x.",
258 keyCode, metaState, result ? "true" : "false",
259 outFallbackAction->keyCode, outFallbackAction->metaState);
260 #endif
261 return result;
262 }
263
getMatch(int32_t keyCode,const char16_t * chars,size_t numChars,int32_t metaState) const264 char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
265 int32_t metaState) const {
266 char16_t result = 0;
267 const Key* key = getKey(keyCode);
268 if (key != nullptr) {
269 // Try to find the most general behavior that maps to this character.
270 // For example, the base key behavior will usually be last in the list.
271 // However, if we find a perfect meta state match for one behavior then use that one.
272 for (const Behavior& behavior : key->behaviors) {
273 if (behavior.character) {
274 for (size_t i = 0; i < numChars; i++) {
275 if (behavior.character == chars[i]) {
276 result = behavior.character;
277 if ((behavior.metaState & metaState) == behavior.metaState) {
278 // Found exact match!
279 return result;
280 }
281 break;
282 }
283 }
284 }
285 }
286 }
287 return result;
288 }
289
getEvents(int32_t deviceId,const char16_t * chars,size_t numChars,Vector<KeyEvent> & outEvents) const290 bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
291 Vector<KeyEvent>& outEvents) const {
292 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
293
294 for (size_t i = 0; i < numChars; i++) {
295 int32_t keyCode, metaState;
296 char16_t ch = chars[i];
297 if (!findKey(ch, &keyCode, &metaState)) {
298 #if DEBUG_MAPPING
299 ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.",
300 deviceId, toString(chars, numChars).string(), ch);
301 #endif
302 return false;
303 }
304
305 int32_t currentMetaState = 0;
306 addMetaKeys(outEvents, deviceId, metaState, true, now, ¤tMetaState);
307 addKey(outEvents, deviceId, keyCode, currentMetaState, true, now);
308 addKey(outEvents, deviceId, keyCode, currentMetaState, false, now);
309 addMetaKeys(outEvents, deviceId, metaState, false, now, ¤tMetaState);
310 }
311 #if DEBUG_MAPPING
312 ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
313 deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
314 for (size_t i = 0; i < outEvents.size(); i++) {
315 ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.",
316 outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
317 outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up");
318 }
319 #endif
320 return true;
321 }
322
addKeyRemapping(int32_t fromKeyCode,int32_t toKeyCode)323 void KeyCharacterMap::addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) {
324 if (fromKeyCode == toKeyCode) {
325 mKeyRemapping.erase(fromKeyCode);
326 #if DEBUG_MAPPING
327 ALOGD("addKeyRemapping: Cleared remapping forKeyCode=%d ~ Result Successful.", fromKeyCode);
328 #endif
329 return;
330 }
331 mKeyRemapping.insert_or_assign(fromKeyCode, toKeyCode);
332 #if DEBUG_MAPPING
333 ALOGD("addKeyRemapping: fromKeyCode=%d, toKeyCode=%d ~ Result Successful.", fromKeyCode,
334 toKeyCode);
335 #endif
336 }
337
mapKey(int32_t scanCode,int32_t usageCode,int32_t * outKeyCode) const338 status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
339 if (usageCode) {
340 const auto it = mKeysByUsageCode.find(usageCode);
341 if (it != mKeysByUsageCode.end()) {
342 *outKeyCode = it->second;
343 #if DEBUG_MAPPING
344 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
345 scanCode, usageCode, *outKeyCode);
346 #endif
347 return OK;
348 }
349 }
350 if (scanCode) {
351 const auto it = mKeysByScanCode.find(scanCode);
352 if (it != mKeysByScanCode.end()) {
353 *outKeyCode = it->second;
354 #if DEBUG_MAPPING
355 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
356 scanCode, usageCode, *outKeyCode);
357 #endif
358 return OK;
359 }
360 }
361
362 #if DEBUG_MAPPING
363 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
364 #endif
365 *outKeyCode = AKEYCODE_UNKNOWN;
366 return NAME_NOT_FOUND;
367 }
368
applyKeyRemapping(int32_t fromKeyCode) const369 int32_t KeyCharacterMap::applyKeyRemapping(int32_t fromKeyCode) const {
370 int32_t toKeyCode = fromKeyCode;
371
372 const auto it = mKeyRemapping.find(fromKeyCode);
373 if (it != mKeyRemapping.end()) {
374 toKeyCode = it->second;
375 }
376 #if DEBUG_MAPPING
377 ALOGD("applyKeyRemapping: keyCode=%d ~ replacement keyCode=%d.", fromKeyCode, toKeyCode);
378 #endif
379 return toKeyCode;
380 }
381
applyKeyBehavior(int32_t fromKeyCode,int32_t fromMetaState) const382 std::pair<int32_t, int32_t> KeyCharacterMap::applyKeyBehavior(int32_t fromKeyCode,
383 int32_t fromMetaState) const {
384 int32_t toKeyCode = fromKeyCode;
385 int32_t toMetaState = fromMetaState;
386
387 const Behavior* behavior = getKeyBehavior(fromKeyCode, fromMetaState);
388 if (behavior != nullptr) {
389 if (behavior->replacementKeyCode) {
390 toKeyCode = behavior->replacementKeyCode;
391 toMetaState = fromMetaState & ~behavior->metaState;
392 // Reset dependent meta states.
393 if (behavior->metaState & AMETA_ALT_ON) {
394 toMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
395 }
396 if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
397 toMetaState &= ~AMETA_ALT_ON;
398 }
399 if (behavior->metaState & AMETA_CTRL_ON) {
400 toMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
401 }
402 if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
403 toMetaState &= ~AMETA_CTRL_ON;
404 }
405 if (behavior->metaState & AMETA_SHIFT_ON) {
406 toMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
407 }
408 if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
409 toMetaState &= ~AMETA_SHIFT_ON;
410 }
411 // ... and put universal bits back if needed
412 toMetaState = normalizeMetaState(toMetaState);
413 }
414 }
415
416 #if DEBUG_MAPPING
417 ALOGD("applyKeyBehavior: keyCode=%d, metaState=0x%08x ~ "
418 "replacement keyCode=%d, replacement metaState=0x%08x.",
419 fromKeyCode, fromMetaState, toKeyCode, toMetaState);
420 #endif
421 return std::make_pair(toKeyCode, toMetaState);
422 }
423
getKey(int32_t keyCode) const424 const KeyCharacterMap::Key* KeyCharacterMap::getKey(int32_t keyCode) const {
425 auto it = mKeys.find(keyCode);
426 if (it != mKeys.end()) {
427 return &it->second;
428 }
429 return nullptr;
430 }
431
getKeyBehavior(int32_t keyCode,int32_t metaState) const432 const KeyCharacterMap::Behavior* KeyCharacterMap::getKeyBehavior(int32_t keyCode,
433 int32_t metaState) const {
434 const Key* key = getKey(keyCode);
435 if (key != nullptr) {
436 for (const Behavior& behavior : key->behaviors) {
437 if (matchesMetaState(metaState, behavior.metaState)) {
438 return &behavior;
439 }
440 }
441 }
442 return nullptr;
443 }
444
matchesMetaState(int32_t eventMetaState,int32_t behaviorMetaState)445 bool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) {
446 // Behavior must have at least the set of meta states specified.
447 // And if the key event has CTRL, ALT or META then the behavior must exactly
448 // match those, taking into account that a behavior can specify that it handles
449 // one, both or either of a left/right modifier pair.
450 if ((eventMetaState & behaviorMetaState) == behaviorMetaState) {
451 const int32_t EXACT_META_STATES =
452 AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON
453 | AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON
454 | AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON;
455 int32_t unmatchedMetaState = eventMetaState & ~behaviorMetaState & EXACT_META_STATES;
456 if (behaviorMetaState & AMETA_CTRL_ON) {
457 unmatchedMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
458 } else if (behaviorMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
459 unmatchedMetaState &= ~AMETA_CTRL_ON;
460 }
461 if (behaviorMetaState & AMETA_ALT_ON) {
462 unmatchedMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
463 } else if (behaviorMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
464 unmatchedMetaState &= ~AMETA_ALT_ON;
465 }
466 if (behaviorMetaState & AMETA_META_ON) {
467 unmatchedMetaState &= ~(AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
468 } else if (behaviorMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
469 unmatchedMetaState &= ~AMETA_META_ON;
470 }
471 return !unmatchedMetaState;
472 }
473 return false;
474 }
475
findKey(char16_t ch,int32_t * outKeyCode,int32_t * outMetaState) const476 bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
477 if (!ch) {
478 return false;
479 }
480
481 for (const auto& [keyCode, key] : mKeys) {
482 // Try to find the most general behavior that maps to this character.
483 // For example, the base key behavior will usually be last in the list.
484 const Behavior* found = nullptr;
485 for (const Behavior& behavior : key.behaviors) {
486 if (behavior.character == ch) {
487 found = &behavior;
488 }
489 }
490 if (found != nullptr) {
491 *outKeyCode = keyCode;
492 *outMetaState = found->metaState;
493 return true;
494 }
495 }
496 return false;
497 }
498
addKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t keyCode,int32_t metaState,bool down,nsecs_t time)499 void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents,
500 int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) {
501 outEvents.push();
502 KeyEvent& event = outEvents.editTop();
503 event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
504 INVALID_HMAC, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode,
505 0, metaState, 0, time, time);
506 }
507
addMetaKeys(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t * currentMetaState)508 void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents,
509 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
510 int32_t* currentMetaState) {
511 // Add and remove meta keys symmetrically.
512 if (down) {
513 addLockedMetaKey(outEvents, deviceId, metaState, time,
514 AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
515 addLockedMetaKey(outEvents, deviceId, metaState, time,
516 AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
517 addLockedMetaKey(outEvents, deviceId, metaState, time,
518 AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
519
520 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
521 AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
522 AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
523 AMETA_SHIFT_ON, currentMetaState);
524 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
525 AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
526 AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
527 AMETA_ALT_ON, currentMetaState);
528 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
529 AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
530 AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
531 AMETA_CTRL_ON, currentMetaState);
532 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
533 AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
534 AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
535 AMETA_META_ON, currentMetaState);
536
537 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
538 AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
539 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
540 AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
541 } else {
542 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
543 AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
544 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
545 AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
546
547 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
548 AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
549 AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
550 AMETA_META_ON, currentMetaState);
551 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
552 AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
553 AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
554 AMETA_CTRL_ON, currentMetaState);
555 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
556 AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
557 AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
558 AMETA_ALT_ON, currentMetaState);
559 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
560 AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
561 AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
562 AMETA_SHIFT_ON, currentMetaState);
563
564 addLockedMetaKey(outEvents, deviceId, metaState, time,
565 AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
566 addLockedMetaKey(outEvents, deviceId, metaState, time,
567 AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
568 addLockedMetaKey(outEvents, deviceId, metaState, time,
569 AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
570 }
571 }
572
addSingleEphemeralMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t keyCode,int32_t keyMetaState,int32_t * currentMetaState)573 bool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
574 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
575 int32_t keyCode, int32_t keyMetaState,
576 int32_t* currentMetaState) {
577 if ((metaState & keyMetaState) == keyMetaState) {
578 *currentMetaState = updateMetaState(keyCode, down, *currentMetaState);
579 addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time);
580 return true;
581 }
582 return false;
583 }
584
addDoubleEphemeralMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t leftKeyCode,int32_t leftKeyMetaState,int32_t rightKeyCode,int32_t rightKeyMetaState,int32_t eitherKeyMetaState,int32_t * currentMetaState)585 void KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
586 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
587 int32_t leftKeyCode, int32_t leftKeyMetaState,
588 int32_t rightKeyCode, int32_t rightKeyMetaState,
589 int32_t eitherKeyMetaState,
590 int32_t* currentMetaState) {
591 bool specific = false;
592 specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
593 leftKeyCode, leftKeyMetaState, currentMetaState);
594 specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
595 rightKeyCode, rightKeyMetaState, currentMetaState);
596
597 if (!specific) {
598 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
599 leftKeyCode, eitherKeyMetaState, currentMetaState);
600 }
601 }
602
addLockedMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,nsecs_t time,int32_t keyCode,int32_t keyMetaState,int32_t * currentMetaState)603 void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents,
604 int32_t deviceId, int32_t metaState, nsecs_t time,
605 int32_t keyCode, int32_t keyMetaState,
606 int32_t* currentMetaState) {
607 if ((metaState & keyMetaState) == keyMetaState) {
608 *currentMetaState = updateMetaState(keyCode, true, *currentMetaState);
609 addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time);
610 *currentMetaState = updateMetaState(keyCode, false, *currentMetaState);
611 addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time);
612 }
613 }
614
615 #ifdef __linux__
readFromParcel(Parcel * parcel)616 std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
617 if (parcel == nullptr) {
618 ALOGE("%s: Null parcel", __func__);
619 return nullptr;
620 }
621 std::string loadFileName = parcel->readCString();
622 std::shared_ptr<KeyCharacterMap> map =
623 std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(loadFileName));
624 map->mType = static_cast<KeyCharacterMap::KeyboardType>(parcel->readInt32());
625 map->mLayoutOverlayApplied = parcel->readBool();
626 size_t numKeys = parcel->readInt32();
627 if (parcel->errorCheck()) {
628 return nullptr;
629 }
630 if (numKeys > MAX_KEYS) {
631 ALOGE("Too many keys in KeyCharacterMap (%zu > %d)", numKeys, MAX_KEYS);
632 return nullptr;
633 }
634
635 for (size_t i = 0; i < numKeys; i++) {
636 int32_t keyCode = parcel->readInt32();
637 char16_t label = parcel->readInt32();
638 char16_t number = parcel->readInt32();
639 if (parcel->errorCheck()) {
640 return nullptr;
641 }
642
643 Key key{.label = label, .number = number};
644 while (parcel->readInt32()) {
645 int32_t metaState = parcel->readInt32();
646 char16_t character = parcel->readInt32();
647 int32_t fallbackKeyCode = parcel->readInt32();
648 int32_t replacementKeyCode = parcel->readInt32();
649 if (parcel->errorCheck()) {
650 return nullptr;
651 }
652
653 key.behaviors.push_back({
654 .metaState = metaState,
655 .character = character,
656 .fallbackKeyCode = fallbackKeyCode,
657 .replacementKeyCode = replacementKeyCode,
658 });
659 }
660 map->mKeys.emplace(keyCode, std::move(key));
661
662 if (parcel->errorCheck()) {
663 return nullptr;
664 }
665 }
666 size_t numKeyRemapping = parcel->readInt32();
667 if (parcel->errorCheck()) {
668 return nullptr;
669 }
670 for (size_t i = 0; i < numKeyRemapping; i++) {
671 int32_t key = parcel->readInt32();
672 int32_t value = parcel->readInt32();
673 map->mKeyRemapping.insert_or_assign(key, value);
674 if (parcel->errorCheck()) {
675 return nullptr;
676 }
677 }
678 size_t numKeysByScanCode = parcel->readInt32();
679 if (parcel->errorCheck()) {
680 return nullptr;
681 }
682 for (size_t i = 0; i < numKeysByScanCode; i++) {
683 int32_t key = parcel->readInt32();
684 int32_t value = parcel->readInt32();
685 map->mKeysByScanCode.insert_or_assign(key, value);
686 if (parcel->errorCheck()) {
687 return nullptr;
688 }
689 }
690 size_t numKeysByUsageCode = parcel->readInt32();
691 if (parcel->errorCheck()) {
692 return nullptr;
693 }
694 for (size_t i = 0; i < numKeysByUsageCode; i++) {
695 int32_t key = parcel->readInt32();
696 int32_t value = parcel->readInt32();
697 map->mKeysByUsageCode.insert_or_assign(key, value);
698 if (parcel->errorCheck()) {
699 return nullptr;
700 }
701 }
702 return map;
703 }
704
writeToParcel(Parcel * parcel) const705 void KeyCharacterMap::writeToParcel(Parcel* parcel) const {
706 if (parcel == nullptr) {
707 ALOGE("%s: Null parcel", __func__);
708 return;
709 }
710 parcel->writeCString(mLoadFileName.c_str());
711 parcel->writeInt32(static_cast<int32_t>(mType));
712 parcel->writeBool(mLayoutOverlayApplied);
713
714 size_t numKeys = mKeys.size();
715 parcel->writeInt32(numKeys);
716 for (const auto& [keyCode, key] : mKeys) {
717 parcel->writeInt32(keyCode);
718 parcel->writeInt32(key.label);
719 parcel->writeInt32(key.number);
720 for (const Behavior& behavior : key.behaviors) {
721 parcel->writeInt32(1);
722 parcel->writeInt32(behavior.metaState);
723 parcel->writeInt32(behavior.character);
724 parcel->writeInt32(behavior.fallbackKeyCode);
725 parcel->writeInt32(behavior.replacementKeyCode);
726 }
727 parcel->writeInt32(0);
728 }
729 size_t numKeyRemapping = mKeyRemapping.size();
730 parcel->writeInt32(numKeyRemapping);
731 for (auto const& [fromAndroidKeyCode, toAndroidKeyCode] : mKeyRemapping) {
732 parcel->writeInt32(fromAndroidKeyCode);
733 parcel->writeInt32(toAndroidKeyCode);
734 }
735 size_t numKeysByScanCode = mKeysByScanCode.size();
736 parcel->writeInt32(numKeysByScanCode);
737 for (auto const& [fromScanCode, toAndroidKeyCode] : mKeysByScanCode) {
738 parcel->writeInt32(fromScanCode);
739 parcel->writeInt32(toAndroidKeyCode);
740 }
741 size_t numKeysByUsageCode = mKeysByUsageCode.size();
742 parcel->writeInt32(numKeysByUsageCode);
743 for (auto const& [fromUsageCode, toAndroidKeyCode] : mKeysByUsageCode) {
744 parcel->writeInt32(fromUsageCode);
745 parcel->writeInt32(toAndroidKeyCode);
746 }
747 }
748 #endif // __linux__
749
750 // --- KeyCharacterMap::Parser ---
751
Parser(KeyCharacterMap * map,Tokenizer * tokenizer,Format format)752 KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) :
753 mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) {
754 }
755
parse()756 status_t KeyCharacterMap::Parser::parse() {
757 while (!mTokenizer->isEof()) {
758 #if DEBUG_PARSER
759 ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
760 mTokenizer->peekRemainderOfLine().string());
761 #endif
762
763 mTokenizer->skipDelimiters(WHITESPACE);
764
765 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
766 switch (mState) {
767 case STATE_TOP: {
768 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
769 if (keywordToken == "type") {
770 mTokenizer->skipDelimiters(WHITESPACE);
771 status_t status = parseType();
772 if (status) return status;
773 } else if (keywordToken == "map") {
774 mTokenizer->skipDelimiters(WHITESPACE);
775 status_t status = parseMap();
776 if (status) return status;
777 } else if (keywordToken == "key") {
778 mTokenizer->skipDelimiters(WHITESPACE);
779 status_t status = parseKey();
780 if (status) return status;
781 } else {
782 ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
783 keywordToken.string());
784 return BAD_VALUE;
785 }
786 break;
787 }
788
789 case STATE_KEY: {
790 status_t status = parseKeyProperty();
791 if (status) return status;
792 break;
793 }
794 }
795
796 mTokenizer->skipDelimiters(WHITESPACE);
797 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
798 ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
799 mTokenizer->getLocation().string(),
800 mTokenizer->peekRemainderOfLine().string());
801 return BAD_VALUE;
802 }
803 }
804
805 mTokenizer->nextLine();
806 }
807
808 if (mState != STATE_TOP) {
809 ALOGE("%s: Unterminated key description at end of file.",
810 mTokenizer->getLocation().string());
811 return BAD_VALUE;
812 }
813
814 if (mMap->mType == KeyboardType::UNKNOWN) {
815 ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.",
816 mTokenizer->getLocation().string());
817 return BAD_VALUE;
818 }
819
820 if (mFormat == Format::BASE) {
821 if (mMap->mType == KeyboardType::OVERLAY) {
822 ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.",
823 mTokenizer->getLocation().string());
824 return BAD_VALUE;
825 }
826 } else if (mFormat == Format::OVERLAY) {
827 if (mMap->mType != KeyboardType::OVERLAY) {
828 ALOGE("%s: Overlay keyboard layout missing required keyboard "
829 "'type OVERLAY' declaration.",
830 mTokenizer->getLocation().string());
831 return BAD_VALUE;
832 }
833 }
834
835 return NO_ERROR;
836 }
837
parseType()838 status_t KeyCharacterMap::Parser::parseType() {
839 if (mMap->mType != KeyboardType::UNKNOWN) {
840 ALOGE("%s: Duplicate keyboard 'type' declaration.",
841 mTokenizer->getLocation().string());
842 return BAD_VALUE;
843 }
844
845 KeyboardType type;
846 String8 typeToken = mTokenizer->nextToken(WHITESPACE);
847 if (typeToken == "NUMERIC") {
848 type = KeyboardType::NUMERIC;
849 } else if (typeToken == "PREDICTIVE") {
850 type = KeyboardType::PREDICTIVE;
851 } else if (typeToken == "ALPHA") {
852 type = KeyboardType::ALPHA;
853 } else if (typeToken == "FULL") {
854 type = KeyboardType::FULL;
855 } else if (typeToken == "SPECIAL_FUNCTION") {
856 ALOGW("The SPECIAL_FUNCTION type is now declared in the device's IDC file, please set "
857 "the property 'keyboard.specialFunction' to '1' there instead.");
858 // TODO: return BAD_VALUE here in Q
859 type = KeyboardType::SPECIAL_FUNCTION;
860 } else if (typeToken == "OVERLAY") {
861 type = KeyboardType::OVERLAY;
862 } else {
863 ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(),
864 typeToken.string());
865 return BAD_VALUE;
866 }
867
868 #if DEBUG_PARSER
869 ALOGD("Parsed type: type=%d.", type);
870 #endif
871 mMap->mType = type;
872 return NO_ERROR;
873 }
874
parseMap()875 status_t KeyCharacterMap::Parser::parseMap() {
876 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
877 if (keywordToken == "key") {
878 mTokenizer->skipDelimiters(WHITESPACE);
879 return parseMapKey();
880 }
881 ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
882 keywordToken.string());
883 return BAD_VALUE;
884 }
885
parseMapKey()886 status_t KeyCharacterMap::Parser::parseMapKey() {
887 String8 codeToken = mTokenizer->nextToken(WHITESPACE);
888 bool mapUsage = false;
889 if (codeToken == "usage") {
890 mapUsage = true;
891 mTokenizer->skipDelimiters(WHITESPACE);
892 codeToken = mTokenizer->nextToken(WHITESPACE);
893 }
894
895 char* end;
896 int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
897 if (*end) {
898 ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
899 mapUsage ? "usage" : "scan code", codeToken.string());
900 return BAD_VALUE;
901 }
902 std::map<int32_t, int32_t>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
903 const auto it = map.find(code);
904 if (it != map.end()) {
905 ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
906 mapUsage ? "usage" : "scan code", codeToken.string());
907 return BAD_VALUE;
908 }
909
910 mTokenizer->skipDelimiters(WHITESPACE);
911 String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
912 std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
913 if (!keyCode) {
914 ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
915 keyCodeToken.string());
916 return BAD_VALUE;
917 }
918
919 #if DEBUG_PARSER
920 ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
921 mapUsage ? "usage" : "scan code", code, keyCode);
922 #endif
923 map.insert_or_assign(code, *keyCode);
924 return NO_ERROR;
925 }
926
parseKey()927 status_t KeyCharacterMap::Parser::parseKey() {
928 String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
929 std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
930 if (!keyCode) {
931 ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
932 keyCodeToken.string());
933 return BAD_VALUE;
934 }
935 if (mMap->mKeys.find(*keyCode) != mMap->mKeys.end()) {
936 ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
937 keyCodeToken.string());
938 return BAD_VALUE;
939 }
940
941 mTokenizer->skipDelimiters(WHITESPACE);
942 String8 openBraceToken = mTokenizer->nextToken(WHITESPACE);
943 if (openBraceToken != "{") {
944 ALOGE("%s: Expected '{' after key code label, got '%s'.",
945 mTokenizer->getLocation().string(), openBraceToken.string());
946 return BAD_VALUE;
947 }
948
949 ALOGD_IF(DEBUG_PARSER, "Parsed beginning of key: keyCode=%d.", *keyCode);
950 mKeyCode = *keyCode;
951 mMap->mKeys.emplace(*keyCode, Key{});
952 mState = STATE_KEY;
953 return NO_ERROR;
954 }
955
parseKeyProperty()956 status_t KeyCharacterMap::Parser::parseKeyProperty() {
957 Key& key = mMap->mKeys[mKeyCode];
958 String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
959 if (token == "}") {
960 mState = STATE_TOP;
961 return finishKey(key);
962 }
963
964 std::vector<Property> properties;
965
966 // Parse all comma-delimited property names up to the first colon.
967 for (;;) {
968 if (token == "label") {
969 properties.emplace_back(PROPERTY_LABEL);
970 } else if (token == "number") {
971 properties.emplace_back(PROPERTY_NUMBER);
972 } else {
973 int32_t metaState;
974 status_t status = parseModifier(token.string(), &metaState);
975 if (status) {
976 ALOGE("%s: Expected a property name or modifier, got '%s'.",
977 mTokenizer->getLocation().string(), token.string());
978 return status;
979 }
980 properties.emplace_back(PROPERTY_META, metaState);
981 }
982
983 mTokenizer->skipDelimiters(WHITESPACE);
984 if (!mTokenizer->isEol()) {
985 char ch = mTokenizer->nextChar();
986 if (ch == ':') {
987 break;
988 } else if (ch == ',') {
989 mTokenizer->skipDelimiters(WHITESPACE);
990 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
991 continue;
992 }
993 }
994
995 ALOGE("%s: Expected ',' or ':' after property name.",
996 mTokenizer->getLocation().string());
997 return BAD_VALUE;
998 }
999
1000 // Parse behavior after the colon.
1001 mTokenizer->skipDelimiters(WHITESPACE);
1002
1003 Behavior behavior;
1004 bool haveCharacter = false;
1005 bool haveFallback = false;
1006 bool haveReplacement = false;
1007
1008 do {
1009 char ch = mTokenizer->peekChar();
1010 if (ch == '\'') {
1011 char16_t character;
1012 status_t status = parseCharacterLiteral(&character);
1013 if (status || !character) {
1014 ALOGE("%s: Invalid character literal for key.",
1015 mTokenizer->getLocation().string());
1016 return BAD_VALUE;
1017 }
1018 if (haveCharacter) {
1019 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
1020 mTokenizer->getLocation().string());
1021 return BAD_VALUE;
1022 }
1023 if (haveReplacement) {
1024 ALOGE("%s: Cannot combine character literal with replace action.",
1025 mTokenizer->getLocation().string());
1026 return BAD_VALUE;
1027 }
1028 behavior.character = character;
1029 haveCharacter = true;
1030 } else {
1031 token = mTokenizer->nextToken(WHITESPACE);
1032 if (token == "none") {
1033 if (haveCharacter) {
1034 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
1035 mTokenizer->getLocation().string());
1036 return BAD_VALUE;
1037 }
1038 if (haveReplacement) {
1039 ALOGE("%s: Cannot combine 'none' with replace action.",
1040 mTokenizer->getLocation().string());
1041 return BAD_VALUE;
1042 }
1043 haveCharacter = true;
1044 } else if (token == "fallback") {
1045 mTokenizer->skipDelimiters(WHITESPACE);
1046 token = mTokenizer->nextToken(WHITESPACE);
1047 std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
1048 if (!keyCode) {
1049 ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
1050 mTokenizer->getLocation().string(),
1051 token.string());
1052 return BAD_VALUE;
1053 }
1054 if (haveFallback || haveReplacement) {
1055 ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
1056 mTokenizer->getLocation().string());
1057 return BAD_VALUE;
1058 }
1059 behavior.fallbackKeyCode = *keyCode;
1060 haveFallback = true;
1061 } else if (token == "replace") {
1062 mTokenizer->skipDelimiters(WHITESPACE);
1063 token = mTokenizer->nextToken(WHITESPACE);
1064 std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
1065 if (!keyCode) {
1066 ALOGE("%s: Invalid key code label for replace, got '%s'.",
1067 mTokenizer->getLocation().string(),
1068 token.string());
1069 return BAD_VALUE;
1070 }
1071 if (haveCharacter) {
1072 ALOGE("%s: Cannot combine character literal with replace action.",
1073 mTokenizer->getLocation().string());
1074 return BAD_VALUE;
1075 }
1076 if (haveFallback || haveReplacement) {
1077 ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
1078 mTokenizer->getLocation().string());
1079 return BAD_VALUE;
1080 }
1081 behavior.replacementKeyCode = *keyCode;
1082 haveReplacement = true;
1083
1084 } else {
1085 ALOGE("%s: Expected a key behavior after ':'.",
1086 mTokenizer->getLocation().string());
1087 return BAD_VALUE;
1088 }
1089 }
1090
1091 mTokenizer->skipDelimiters(WHITESPACE);
1092 } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#');
1093
1094 // Add the behavior.
1095 for (const Property& property : properties) {
1096 switch (property.property) {
1097 case PROPERTY_LABEL:
1098 if (key.label) {
1099 ALOGE("%s: Duplicate label for key.", mTokenizer->getLocation().string());
1100 return BAD_VALUE;
1101 }
1102 key.label = behavior.character;
1103 #if DEBUG_PARSER
1104 ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key.label);
1105 #endif
1106 break;
1107 case PROPERTY_NUMBER:
1108 if (key.number) {
1109 ALOGE("%s: Duplicate number for key.", mTokenizer->getLocation().string());
1110 return BAD_VALUE;
1111 }
1112 key.number = behavior.character;
1113 #if DEBUG_PARSER
1114 ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key.number);
1115 #endif
1116 break;
1117 case PROPERTY_META: {
1118 for (const Behavior& b : key.behaviors) {
1119 if (b.metaState == property.metaState) {
1120 ALOGE("%s: Duplicate key behavior for modifier.",
1121 mTokenizer->getLocation().string());
1122 return BAD_VALUE;
1123 }
1124 }
1125 Behavior newBehavior = behavior;
1126 newBehavior.metaState = property.metaState;
1127 key.behaviors.push_front(newBehavior);
1128 ALOGD_IF(DEBUG_PARSER,
1129 "Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.",
1130 mKeyCode, key.behaviors.front().metaState, key.behaviors.front().character,
1131 key.behaviors.front().fallbackKeyCode,
1132 key.behaviors.front().replacementKeyCode);
1133 break;
1134 }
1135 }
1136 }
1137 return NO_ERROR;
1138 }
1139
finishKey(Key & key)1140 status_t KeyCharacterMap::Parser::finishKey(Key& key) {
1141 // Fill in default number property.
1142 if (!key.number) {
1143 char16_t digit = 0;
1144 char16_t symbol = 0;
1145 for (const Behavior& b : key.behaviors) {
1146 char16_t ch = b.character;
1147 if (ch) {
1148 if (ch >= '0' && ch <= '9') {
1149 digit = ch;
1150 } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*'
1151 || ch == '-' || ch == '+' || ch == ',' || ch == '.'
1152 || ch == '\'' || ch == ':' || ch == ';' || ch == '/') {
1153 symbol = ch;
1154 }
1155 }
1156 }
1157 key.number = digit ? digit : symbol;
1158 }
1159 return NO_ERROR;
1160 }
1161
parseModifier(const std::string & token,int32_t * outMetaState)1162 status_t KeyCharacterMap::Parser::parseModifier(const std::string& token, int32_t* outMetaState) {
1163 if (token == "base") {
1164 *outMetaState = 0;
1165 return NO_ERROR;
1166 }
1167
1168 int32_t combinedMeta = 0;
1169
1170 const char* str = token.c_str();
1171 const char* start = str;
1172 for (const char* cur = str; ; cur++) {
1173 char ch = *cur;
1174 if (ch == '+' || ch == '\0') {
1175 size_t len = cur - start;
1176 int32_t metaState = 0;
1177 for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) {
1178 if (strlen(modifiers[i].label) == len
1179 && strncmp(modifiers[i].label, start, len) == 0) {
1180 metaState = modifiers[i].metaState;
1181 break;
1182 }
1183 }
1184 if (!metaState) {
1185 return BAD_VALUE;
1186 }
1187 if (combinedMeta & metaState) {
1188 ALOGE("%s: Duplicate modifier combination '%s'.",
1189 mTokenizer->getLocation().string(), token.c_str());
1190 return BAD_VALUE;
1191 }
1192
1193 combinedMeta |= metaState;
1194 start = cur + 1;
1195
1196 if (ch == '\0') {
1197 break;
1198 }
1199 }
1200 }
1201 *outMetaState = combinedMeta;
1202 return NO_ERROR;
1203 }
1204
parseCharacterLiteral(char16_t * outCharacter)1205 status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) {
1206 char ch = mTokenizer->nextChar();
1207 if (ch != '\'') {
1208 goto Error;
1209 }
1210
1211 ch = mTokenizer->nextChar();
1212 if (ch == '\\') {
1213 // Escape sequence.
1214 ch = mTokenizer->nextChar();
1215 if (ch == 'n') {
1216 *outCharacter = '\n';
1217 } else if (ch == 't') {
1218 *outCharacter = '\t';
1219 } else if (ch == '\\') {
1220 *outCharacter = '\\';
1221 } else if (ch == '\'') {
1222 *outCharacter = '\'';
1223 } else if (ch == '"') {
1224 *outCharacter = '"';
1225 } else if (ch == 'u') {
1226 *outCharacter = 0;
1227 for (int i = 0; i < 4; i++) {
1228 ch = mTokenizer->nextChar();
1229 int digit;
1230 if (ch >= '0' && ch <= '9') {
1231 digit = ch - '0';
1232 } else if (ch >= 'A' && ch <= 'F') {
1233 digit = ch - 'A' + 10;
1234 } else if (ch >= 'a' && ch <= 'f') {
1235 digit = ch - 'a' + 10;
1236 } else {
1237 goto Error;
1238 }
1239 *outCharacter = (*outCharacter << 4) | digit;
1240 }
1241 } else {
1242 goto Error;
1243 }
1244 } else if (ch >= 32 && ch <= 126 && ch != '\'') {
1245 // ASCII literal character.
1246 *outCharacter = ch;
1247 } else {
1248 goto Error;
1249 }
1250
1251 ch = mTokenizer->nextChar();
1252 if (ch != '\'') {
1253 goto Error;
1254 }
1255
1256 // Ensure that we consumed the entire token.
1257 if (mTokenizer->nextToken(WHITESPACE).isEmpty()) {
1258 return NO_ERROR;
1259 }
1260
1261 Error:
1262 ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
1263 return BAD_VALUE;
1264 }
1265
1266 } // namespace android
1267