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         ALOGW("The SPECIAL_FUNCTION type is now declared in the device's IDC file, please set "
    828                 "the property 'keyboard.specialFunction' to '1' there instead.");
    829         // TODO: return BAD_VALUE here in Q
    830         type = KEYBOARD_TYPE_SPECIAL_FUNCTION;
    831     } else if (typeToken == "OVERLAY") {
    832         type = KEYBOARD_TYPE_OVERLAY;
    833     } else {
    834         ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(),
    835                 typeToken.string());
    836         return BAD_VALUE;
    837     }
    838 
    839 #if DEBUG_PARSER
    840     ALOGD("Parsed type: type=%d.", type);
    841 #endif
    842     mMap->mType = type;
    843     return NO_ERROR;
    844 }
    845 
    846 status_t KeyCharacterMap::Parser::parseMap() {
    847     String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
    848     if (keywordToken == "key") {
    849         mTokenizer->skipDelimiters(WHITESPACE);
    850         return parseMapKey();
    851     }
    852     ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
    853             keywordToken.string());
    854     return BAD_VALUE;
    855 }
    856 
    857 status_t KeyCharacterMap::Parser::parseMapKey() {
    858     String8 codeToken = mTokenizer->nextToken(WHITESPACE);
    859     bool mapUsage = false;
    860     if (codeToken == "usage") {
    861         mapUsage = true;
    862         mTokenizer->skipDelimiters(WHITESPACE);
    863         codeToken = mTokenizer->nextToken(WHITESPACE);
    864     }
    865 
    866     char* end;
    867     int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
    868     if (*end) {
    869         ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
    870                 mapUsage ? "usage" : "scan code", codeToken.string());
    871         return BAD_VALUE;
    872     }
    873     KeyedVector<int32_t, int32_t>& map =
    874             mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
    875     if (map.indexOfKey(code) >= 0) {
    876         ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
    877                 mapUsage ? "usage" : "scan code", codeToken.string());
    878         return BAD_VALUE;
    879     }
    880 
    881     mTokenizer->skipDelimiters(WHITESPACE);
    882     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
    883     int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
    884     if (!keyCode) {
    885         ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
    886                 keyCodeToken.string());
    887         return BAD_VALUE;
    888     }
    889 
    890 #if DEBUG_PARSER
    891     ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
    892             mapUsage ? "usage" : "scan code", code, keyCode);
    893 #endif
    894     map.add(code, keyCode);
    895     return NO_ERROR;
    896 }
    897 
    898 status_t KeyCharacterMap::Parser::parseKey() {
    899     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
    900     int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
    901     if (!keyCode) {
    902         ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
    903                 keyCodeToken.string());
    904         return BAD_VALUE;
    905     }
    906     if (mMap->mKeys.indexOfKey(keyCode) >= 0) {
    907         ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
    908                 keyCodeToken.string());
    909         return BAD_VALUE;
    910     }
    911 
    912     mTokenizer->skipDelimiters(WHITESPACE);
    913     String8 openBraceToken = mTokenizer->nextToken(WHITESPACE);
    914     if (openBraceToken != "{") {
    915         ALOGE("%s: Expected '{' after key code label, got '%s'.",
    916                 mTokenizer->getLocation().string(), openBraceToken.string());
    917         return BAD_VALUE;
    918     }
    919 
    920 #if DEBUG_PARSER
    921     ALOGD("Parsed beginning of key: keyCode=%d.", keyCode);
    922 #endif
    923     mKeyCode = keyCode;
    924     mMap->mKeys.add(keyCode, new Key());
    925     mState = STATE_KEY;
    926     return NO_ERROR;
    927 }
    928 
    929 status_t KeyCharacterMap::Parser::parseKeyProperty() {
    930     Key* key = mMap->mKeys.valueFor(mKeyCode);
    931     String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
    932     if (token == "}") {
    933         mState = STATE_TOP;
    934         return finishKey(key);
    935     }
    936 
    937     Vector<Property> properties;
    938 
    939     // Parse all comma-delimited property names up to the first colon.
    940     for (;;) {
    941         if (token == "label") {
    942             properties.add(Property(PROPERTY_LABEL));
    943         } else if (token == "number") {
    944             properties.add(Property(PROPERTY_NUMBER));
    945         } else {
    946             int32_t metaState;
    947             status_t status = parseModifier(token, &metaState);
    948             if (status) {
    949                 ALOGE("%s: Expected a property name or modifier, got '%s'.",
    950                         mTokenizer->getLocation().string(), token.string());
    951                 return status;
    952             }
    953             properties.add(Property(PROPERTY_META, metaState));
    954         }
    955 
    956         mTokenizer->skipDelimiters(WHITESPACE);
    957         if (!mTokenizer->isEol()) {
    958             char ch = mTokenizer->nextChar();
    959             if (ch == ':') {
    960                 break;
    961             } else if (ch == ',') {
    962                 mTokenizer->skipDelimiters(WHITESPACE);
    963                 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
    964                 continue;
    965             }
    966         }
    967 
    968         ALOGE("%s: Expected ',' or ':' after property name.",
    969                 mTokenizer->getLocation().string());
    970         return BAD_VALUE;
    971     }
    972 
    973     // Parse behavior after the colon.
    974     mTokenizer->skipDelimiters(WHITESPACE);
    975 
    976     Behavior behavior;
    977     bool haveCharacter = false;
    978     bool haveFallback = false;
    979     bool haveReplacement = false;
    980 
    981     do {
    982         char ch = mTokenizer->peekChar();
    983         if (ch == '\'') {
    984             char16_t character;
    985             status_t status = parseCharacterLiteral(&character);
    986             if (status || !character) {
    987                 ALOGE("%s: Invalid character literal for key.",
    988                         mTokenizer->getLocation().string());
    989                 return BAD_VALUE;
    990             }
    991             if (haveCharacter) {
    992                 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
    993                         mTokenizer->getLocation().string());
    994                 return BAD_VALUE;
    995             }
    996             if (haveReplacement) {
    997                 ALOGE("%s: Cannot combine character literal with replace action.",
    998                         mTokenizer->getLocation().string());
    999                 return BAD_VALUE;
   1000             }
   1001             behavior.character = character;
   1002             haveCharacter = true;
   1003         } else {
   1004             token = mTokenizer->nextToken(WHITESPACE);
   1005             if (token == "none") {
   1006                 if (haveCharacter) {
   1007                     ALOGE("%s: Cannot combine multiple character literals or 'none'.",
   1008                             mTokenizer->getLocation().string());
   1009                     return BAD_VALUE;
   1010                 }
   1011                 if (haveReplacement) {
   1012                     ALOGE("%s: Cannot combine 'none' with replace action.",
   1013                             mTokenizer->getLocation().string());
   1014                     return BAD_VALUE;
   1015                 }
   1016                 haveCharacter = true;
   1017             } else if (token == "fallback") {
   1018                 mTokenizer->skipDelimiters(WHITESPACE);
   1019                 token = mTokenizer->nextToken(WHITESPACE);
   1020                 int32_t keyCode = getKeyCodeByLabel(token.string());
   1021                 if (!keyCode) {
   1022                     ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
   1023                             mTokenizer->getLocation().string(),
   1024                             token.string());
   1025                     return BAD_VALUE;
   1026                 }
   1027                 if (haveFallback || haveReplacement) {
   1028                     ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
   1029                             mTokenizer->getLocation().string());
   1030                     return BAD_VALUE;
   1031                 }
   1032                 behavior.fallbackKeyCode = keyCode;
   1033                 haveFallback = true;
   1034             } else if (token == "replace") {
   1035                 mTokenizer->skipDelimiters(WHITESPACE);
   1036                 token = mTokenizer->nextToken(WHITESPACE);
   1037                 int32_t keyCode = getKeyCodeByLabel(token.string());
   1038                 if (!keyCode) {
   1039                     ALOGE("%s: Invalid key code label for replace, got '%s'.",
   1040                             mTokenizer->getLocation().string(),
   1041                             token.string());
   1042                     return BAD_VALUE;
   1043                 }
   1044                 if (haveCharacter) {
   1045                     ALOGE("%s: Cannot combine character literal with replace action.",
   1046                             mTokenizer->getLocation().string());
   1047                     return BAD_VALUE;
   1048                 }
   1049                 if (haveFallback || haveReplacement) {
   1050                     ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
   1051                             mTokenizer->getLocation().string());
   1052                     return BAD_VALUE;
   1053                 }
   1054                 behavior.replacementKeyCode = keyCode;
   1055                 haveReplacement = true;
   1056 
   1057             } else {
   1058                 ALOGE("%s: Expected a key behavior after ':'.",
   1059                         mTokenizer->getLocation().string());
   1060                 return BAD_VALUE;
   1061             }
   1062         }
   1063 
   1064         mTokenizer->skipDelimiters(WHITESPACE);
   1065     } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#');
   1066 
   1067     // Add the behavior.
   1068     for (size_t i = 0; i < properties.size(); i++) {
   1069         const Property& property = properties.itemAt(i);
   1070         switch (property.property) {
   1071         case PROPERTY_LABEL:
   1072             if (key->label) {
   1073                 ALOGE("%s: Duplicate label for key.",
   1074                         mTokenizer->getLocation().string());
   1075                 return BAD_VALUE;
   1076             }
   1077             key->label = behavior.character;
   1078 #if DEBUG_PARSER
   1079             ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label);
   1080 #endif
   1081             break;
   1082         case PROPERTY_NUMBER:
   1083             if (key->number) {
   1084                 ALOGE("%s: Duplicate number for key.",
   1085                         mTokenizer->getLocation().string());
   1086                 return BAD_VALUE;
   1087             }
   1088             key->number = behavior.character;
   1089 #if DEBUG_PARSER
   1090             ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number);
   1091 #endif
   1092             break;
   1093         case PROPERTY_META: {
   1094             for (Behavior* b = key->firstBehavior; b; b = b->next) {
   1095                 if (b->metaState == property.metaState) {
   1096                     ALOGE("%s: Duplicate key behavior for modifier.",
   1097                             mTokenizer->getLocation().string());
   1098                     return BAD_VALUE;
   1099                 }
   1100             }
   1101             Behavior* newBehavior = new Behavior(behavior);
   1102             newBehavior->metaState = property.metaState;
   1103             newBehavior->next = key->firstBehavior;
   1104             key->firstBehavior = newBehavior;
   1105 #if DEBUG_PARSER
   1106             ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.",
   1107                     mKeyCode,
   1108                     newBehavior->metaState, newBehavior->character,
   1109                     newBehavior->fallbackKeyCode, newBehavior->replacementKeyCode);
   1110 #endif
   1111             break;
   1112         }
   1113         }
   1114     }
   1115     return NO_ERROR;
   1116 }
   1117 
   1118 status_t KeyCharacterMap::Parser::finishKey(Key* key) {
   1119     // Fill in default number property.
   1120     if (!key->number) {
   1121         char16_t digit = 0;
   1122         char16_t symbol = 0;
   1123         for (Behavior* b = key->firstBehavior; b; b = b->next) {
   1124             char16_t ch = b->character;
   1125             if (ch) {
   1126                 if (ch >= '0' && ch <= '9') {
   1127                     digit = ch;
   1128                 } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*'
   1129                         || ch == '-' || ch == '+' || ch == ',' || ch == '.'
   1130                         || ch == '\'' || ch == ':' || ch == ';' || ch == '/') {
   1131                     symbol = ch;
   1132                 }
   1133             }
   1134         }
   1135         key->number = digit ? digit : symbol;
   1136     }
   1137     return NO_ERROR;
   1138 }
   1139 
   1140 status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) {
   1141     if (token == "base") {
   1142         *outMetaState = 0;
   1143         return NO_ERROR;
   1144     }
   1145 
   1146     int32_t combinedMeta = 0;
   1147 
   1148     const char* str = token.string();
   1149     const char* start = str;
   1150     for (const char* cur = str; ; cur++) {
   1151         char ch = *cur;
   1152         if (ch == '+' || ch == '\0') {
   1153             size_t len = cur - start;
   1154             int32_t metaState = 0;
   1155             for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) {
   1156                 if (strlen(modifiers[i].label) == len
   1157                         && strncmp(modifiers[i].label, start, len) == 0) {
   1158                     metaState = modifiers[i].metaState;
   1159                     break;
   1160                 }
   1161             }
   1162             if (!metaState) {
   1163                 return BAD_VALUE;
   1164             }
   1165             if (combinedMeta & metaState) {
   1166                 ALOGE("%s: Duplicate modifier combination '%s'.",
   1167                         mTokenizer->getLocation().string(), token.string());
   1168                 return BAD_VALUE;
   1169             }
   1170 
   1171             combinedMeta |= metaState;
   1172             start = cur + 1;
   1173 
   1174             if (ch == '\0') {
   1175                 break;
   1176             }
   1177         }
   1178     }
   1179     *outMetaState = combinedMeta;
   1180     return NO_ERROR;
   1181 }
   1182 
   1183 status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) {
   1184     char ch = mTokenizer->nextChar();
   1185     if (ch != '\'') {
   1186         goto Error;
   1187     }
   1188 
   1189     ch = mTokenizer->nextChar();
   1190     if (ch == '\\') {
   1191         // Escape sequence.
   1192         ch = mTokenizer->nextChar();
   1193         if (ch == 'n') {
   1194             *outCharacter = '\n';
   1195         } else if (ch == 't') {
   1196             *outCharacter = '\t';
   1197         } else if (ch == '\\') {
   1198             *outCharacter = '\\';
   1199         } else if (ch == '\'') {
   1200             *outCharacter = '\'';
   1201         } else if (ch == '"') {
   1202             *outCharacter = '"';
   1203         } else if (ch == 'u') {
   1204             *outCharacter = 0;
   1205             for (int i = 0; i < 4; i++) {
   1206                 ch = mTokenizer->nextChar();
   1207                 int digit;
   1208                 if (ch >= '0' && ch <= '9') {
   1209                     digit = ch - '0';
   1210                 } else if (ch >= 'A' && ch <= 'F') {
   1211                     digit = ch - 'A' + 10;
   1212                 } else if (ch >= 'a' && ch <= 'f') {
   1213                     digit = ch - 'a' + 10;
   1214                 } else {
   1215                     goto Error;
   1216                 }
   1217                 *outCharacter = (*outCharacter << 4) | digit;
   1218             }
   1219         } else {
   1220             goto Error;
   1221         }
   1222     } else if (ch >= 32 && ch <= 126 && ch != '\'') {
   1223         // ASCII literal character.
   1224         *outCharacter = ch;
   1225     } else {
   1226         goto Error;
   1227     }
   1228 
   1229     ch = mTokenizer->nextChar();
   1230     if (ch != '\'') {
   1231         goto Error;
   1232     }
   1233 
   1234     // Ensure that we consumed the entire token.
   1235     if (mTokenizer->nextToken(WHITESPACE).isEmpty()) {
   1236         return NO_ERROR;
   1237     }
   1238 
   1239 Error:
   1240     ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
   1241     return BAD_VALUE;
   1242 }
   1243 
   1244 } // namespace android
   1245