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