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