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