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