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