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 #include "cutils_log.h"
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include "android_keycodes.h"
23 #include "Keyboard.h"
24 #include "KeyCharacterMap.h"
25 
26 #if HAVE_ANDROID_OS
27 #include <binder/Parcel.h>
28 #endif
29 
30 #include <utils/Errors.h>
31 #include "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 
44 namespace android {
45 
46 static const char* WHITESPACE = " \t\r";
47 static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:";
48 
49 struct Modifier {
50     const char* label;
51     int32_t metaState;
52 };
53 static 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
toString(const char16_t * chars,size_t numChars)74 static 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 
86 sp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap();
87 
KeyCharacterMap()88 KeyCharacterMap::KeyCharacterMap() :
89     mType(KEYBOARD_TYPE_UNKNOWN) {
90 }
91 
KeyCharacterMap(const KeyCharacterMap & other)92 KeyCharacterMap::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 
~KeyCharacterMap()100 KeyCharacterMap::~KeyCharacterMap() {
101     for (size_t i = 0; i < mKeys.size(); i++) {
102         Key* key = mKeys.editValueAt(i);
103         delete key;
104     }
105 }
106 
load(const String8 & filename,Format format,sp<KeyCharacterMap> * outMap)107 status_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 
loadContents(const String8 & filename,const char * contents,Format format,sp<KeyCharacterMap> * outMap)122 status_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 
load(Tokenizer * tokenizer,Format format,sp<KeyCharacterMap> * outMap)137 status_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 
combine(const sp<KeyCharacterMap> & base,const sp<KeyCharacterMap> & overlay)163 sp<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 
empty()197 sp<KeyCharacterMap> KeyCharacterMap::empty() {
198     return sEmpty;
199 }
200 
getKeyboardType() const201 int32_t KeyCharacterMap::getKeyboardType() const {
202     return mType;
203 }
204 
getDisplayLabel(int32_t keyCode) const205 char16_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 
getNumber(int32_t keyCode) const217 char16_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 
getCharacter(int32_t keyCode,int32_t metaState) const229 char16_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 
getFallbackAction(int32_t keyCode,int32_t metaState,FallbackAction * outFallbackAction) const242 bool 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 
getMatch(int32_t keyCode,const char16_t * chars,size_t numChars,int32_t metaState) const266 char16_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 
getEvents(int32_t deviceId,const char16_t * chars,size_t numChars,Vector<KeyEvent> & outEvents) const296 bool 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 
mapKey(int32_t scanCode,int32_t usageCode,int32_t * outKeyCode) const329 status_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 
getKey(int32_t keyCode,const Key ** outKey) const360 bool 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 
getKeyBehavior(int32_t keyCode,int32_t metaState,const Key ** outKey,const Behavior ** outBehavior) const369 bool 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 
matchesMetaState(int32_t eventMetaState,int32_t behaviorMetaState)386 bool 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 
findKey(char16_t ch,int32_t * outKeyCode,int32_t * outMetaState) const417 bool 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 
addKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t keyCode,int32_t metaState,bool down,nsecs_t time)442 void 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 
addMetaKeys(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t * currentMetaState)451 void 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 
addSingleEphemeralMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t keyCode,int32_t keyMetaState,int32_t * currentMetaState)516 bool 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 
addDoubleEphemeralMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,bool down,nsecs_t time,int32_t leftKeyCode,int32_t leftKeyMetaState,int32_t rightKeyCode,int32_t rightKeyMetaState,int32_t eitherKeyMetaState,int32_t * currentMetaState)528 void 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 
addLockedMetaKey(Vector<KeyEvent> & outEvents,int32_t deviceId,int32_t metaState,nsecs_t time,int32_t keyCode,int32_t keyMetaState,int32_t * currentMetaState)546 void 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
readFromParcel(Parcel * parcel)559 sp<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 
writeToParcel(Parcel * parcel) const608 void 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 
Key()634 KeyCharacterMap::Key::Key() :
635         label(0), number(0), firstBehavior(NULL) {
636 }
637 
Key(const Key & other)638 KeyCharacterMap::Key::Key(const Key& other) :
639         label(other.label), number(other.number),
640         firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : NULL) {
641 }
642 
~Key()643 KeyCharacterMap::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 
Behavior()655 KeyCharacterMap::Behavior::Behavior() :
656         next(NULL), metaState(0), character(0), fallbackKeyCode(0) {
657 }
658 
Behavior(const Behavior & other)659 KeyCharacterMap::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 
Parser(KeyCharacterMap * map,Tokenizer * tokenizer,Format format)668 KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) :
669         mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) {
670 }
671 
~Parser()672 KeyCharacterMap::Parser::~Parser() {
673 }
674 
parse()675 status_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 
parseType()757 status_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 
parseMap()791 status_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 
parseMapKey()802 status_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 
parseKey()843 status_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 
parseKeyProperty()874 status_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 
finishKey(Key * key)1027 status_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 
parseModifier(const String8 & token,int32_t * outMetaState)1049 status_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 
parseCharacterLiteral(char16_t * outCharacter)1092 status_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 
1148 Error:
1149     ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
1150     return BAD_VALUE;
1151 }
1152 
1153 } // namespace android
1154