• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &currentMetaState);
307         addKey(outEvents, deviceId, keyCode, currentMetaState, true, now);
308         addKey(outEvents, deviceId, keyCode, currentMetaState, false, now);
309         addMetaKeys(outEvents, deviceId, metaState, false, now, &currentMetaState);
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