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