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