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