15912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown/* 25912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Copyright (C) 2008 The Android Open Source Project 35912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 45912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 55912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * you may not use this file except in compliance with the License. 65912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * You may obtain a copy of the License at 75912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 85912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 95912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Unless required by applicable law or agreed to in writing, software 115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * See the License for the specific language governing permissions and 145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * limitations under the License. 155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown */ 165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define LOG_TAG "KeyCharacterMap" 185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <stdlib.h> 205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <string.h> 215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 226071da7ef84c60645572654504813d492b8b21d5Elliott Hughes#ifdef __ANDROID__ 235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <binder/Parcel.h> 245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <android/keycodes.h> 27872db4f11e407accccba9d37c335ef7e3597eba4Michael Wright#include <input/InputEventLabels.h> 285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/Keyboard.h> 295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/KeyCharacterMap.h> 305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Log.h> 325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Errors.h> 335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Tokenizer.h> 345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Timers.h> 355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for the parser. 375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER 0 385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for parser performance. 405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER_PERFORMANCE 0 415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for mapping. 435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_MAPPING 0 445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownnamespace android { 475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* WHITESPACE = " \t\r"; 495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:"; 505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstruct Modifier { 525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const char* label; 535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t metaState; 545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}; 555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const Modifier modifiers[] = { 565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "shift", AMETA_SHIFT_ON }, 575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "lshift", AMETA_SHIFT_LEFT_ON }, 585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "rshift", AMETA_SHIFT_RIGHT_ON }, 595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "alt", AMETA_ALT_ON }, 605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "lalt", AMETA_ALT_LEFT_ON }, 615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "ralt", AMETA_ALT_RIGHT_ON }, 625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "ctrl", AMETA_CTRL_ON }, 635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "lctrl", AMETA_CTRL_LEFT_ON }, 645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "rctrl", AMETA_CTRL_RIGHT_ON }, 655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "meta", AMETA_META_ON }, 665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "lmeta", AMETA_META_LEFT_ON }, 675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "rmeta", AMETA_META_RIGHT_ON }, 685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "sym", AMETA_SYM_ON }, 695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "fn", AMETA_FUNCTION_ON }, 705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "capslock", AMETA_CAPS_LOCK_ON }, 715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "numlock", AMETA_NUM_LOCK_ON }, 725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown { "scrolllock", AMETA_SCROLL_LOCK_ON }, 735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}; 745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic String8 toString(const char16_t* chars, size_t numChars) { 775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 result; 785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numChars; i++) { 795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]); 805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyCharacterMap --- 875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownsp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap(); 895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::KeyCharacterMap() : 915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mType(KEYBOARD_TYPE_UNKNOWN) { 925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : 955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode), 965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mKeysByUsageCode(other.mKeysByUsageCode) { 975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < other.mKeys.size(); i++) { 985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i))); 995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::~KeyCharacterMap() { 1035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < mKeys.size(); i++) { 1045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Key* key = mKeys.editValueAt(i); 1055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete key; 1065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::load(const String8& filename, 1105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Format format, sp<KeyCharacterMap>* outMap) { 1115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outMap->clear(); 1125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Tokenizer* tokenizer; 1145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = Tokenizer::open(filename, &tokenizer); 1155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 1165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error %d opening key character map file %s.", status, filename.string()); 1175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 1185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = load(tokenizer, format, outMap); 1195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete tokenizer; 1205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 1225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::loadContents(const String8& filename, const char* contents, 1255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Format format, sp<KeyCharacterMap>* outMap) { 1265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outMap->clear(); 1275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Tokenizer* tokenizer; 1295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = Tokenizer::fromContents(filename, contents, &tokenizer); 1305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 1315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error %d opening key character map.", status); 1325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 1335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = load(tokenizer, format, outMap); 1345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete tokenizer; 1355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 1375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::load(Tokenizer* tokenizer, 1405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Format format, sp<KeyCharacterMap>* outMap) { 1415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = OK; 1425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown sp<KeyCharacterMap> map = new KeyCharacterMap(); 1435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!map.get()) { 1445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error allocating key character map."); 1455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = NO_MEMORY; 1465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 1475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 1485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 1495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Parser parser(map.get(), tokenizer, format); 1515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = parser.parse(); 1525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 1535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 1545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", 1555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown tokenizer->getFilename().string(), tokenizer->getLineNumber(), 1565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown elapsedTime / 1000000.0); 1575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!status) { 1595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMap = map; 1605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 1635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownsp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base, 1665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const sp<KeyCharacterMap>& overlay) { 1675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (overlay == NULL) { 1685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return base; 1695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (base == NULL) { 1715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return overlay; 1725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown sp<KeyCharacterMap> map = new KeyCharacterMap(*base.get()); 1755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < overlay->mKeys.size(); i++) { 1765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = overlay->mKeys.keyAt(i); 1775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Key* key = overlay->mKeys.valueAt(i); 1785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t oldIndex = map->mKeys.indexOfKey(keyCode); 1795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (oldIndex >= 0) { 1805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete map->mKeys.valueAt(oldIndex); 1815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mKeys.editValueAt(oldIndex) = new Key(*key); 1825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 1835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mKeys.add(keyCode, new Key(*key)); 1845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) { 1885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i), 1895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown overlay->mKeysByScanCode.valueAt(i)); 1905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) { 1935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i), 1945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown overlay->mKeysByUsageCode.valueAt(i)); 1955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return map; 1975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownsp<KeyCharacterMap> KeyCharacterMap::empty() { 2005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return sEmpty; 2015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownint32_t KeyCharacterMap::getKeyboardType() const { 2045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return mType; 2055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownchar16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { 2085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t result = 0; 2095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 2105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKey(keyCode, &key)) { 2115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result = key->label; 2125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 2145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result); 2155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 2175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownchar16_t KeyCharacterMap::getNumber(int32_t keyCode) const { 2205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t result = 0; 2215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 2225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKey(keyCode, &key)) { 2235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result = key->number; 2245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 2265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result); 2275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 2295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownchar16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const { 2325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t result = 0; 2335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 2345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Behavior* behavior; 2355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { 2365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result = behavior->character; 2375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 2395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result); 2405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 2425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState, 2455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown FallbackAction* outFallbackAction) const { 2465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outFallbackAction->keyCode = 0; 2475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outFallbackAction->metaState = 0; 2485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool result = false; 2505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 2515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Behavior* behavior; 2525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { 2535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behavior->fallbackKeyCode) { 2545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outFallbackAction->keyCode = behavior->fallbackKeyCode; 2555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outFallbackAction->metaState = metaState & ~behavior->metaState; 2565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result = true; 2575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 2605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, " 2615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "fallback keyCode=%d, fallback metaState=0x%08x.", 2625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCode, metaState, result ? "true" : "false", 2635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outFallbackAction->keyCode, outFallbackAction->metaState); 2645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 2665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownchar16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars, 2695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t metaState) const { 2705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t result = 0; 2715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 2725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKey(keyCode, &key)) { 2735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Try to find the most general behavior that maps to this character. 2745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // For example, the base key behavior will usually be last in the list. 2755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // However, if we find a perfect meta state match for one behavior then use that one. 2765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { 2775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behavior->character) { 2785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numChars; i++) { 2795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behavior->character == chars[i]) { 2805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown result = behavior->character; 2815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if ((behavior->metaState & metaState) == behavior->metaState) { 2825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto ExactMatch; 2835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 2855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ExactMatch: ; 2905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 2925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getMatch: keyCode=%d, chars=[%s], metaState=0x%08x ~ Result %d.", 2935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCode, toString(chars, numChars).string(), metaState, result); 2945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return result; 2965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, 2995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Vector<KeyEvent>& outEvents) const { 3005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 3015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numChars; i++) { 3035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode, metaState; 3045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t ch = chars[i]; 3055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!findKey(ch, &keyCode, &metaState)) { 3065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 3075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.", 3085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown deviceId, toString(chars, numChars).string(), ch); 3095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 3115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t currentMetaState = 0; 3145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addMetaKeys(outEvents, deviceId, metaState, true, now, ¤tMetaState); 3155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addKey(outEvents, deviceId, keyCode, currentMetaState, true, now); 3165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addKey(outEvents, deviceId, keyCode, currentMetaState, false, now); 3175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addMetaKeys(outEvents, deviceId, metaState, false, now, ¤tMetaState); 3185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 3205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.", 3215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown deviceId, toString(chars, numChars).string(), int32_t(outEvents.size())); 3225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < outEvents.size(); i++) { 3235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.", 3245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outEvents[i].getKeyCode(), outEvents[i].getMetaState(), 3255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up"); 3265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 3295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 3305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const { 3325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (usageCode) { 3335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); 3345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index >= 0) { 335115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outKeyCode = mKeysByUsageCode.valueAt(index); 3365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 337115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", 338115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov scanCode, usageCode, *outKeyCode); 3395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return OK; 3415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (scanCode) { 3445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mKeysByScanCode.indexOfKey(scanCode); 3455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index >= 0) { 346115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outKeyCode = mKeysByScanCode.valueAt(index); 3475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 348115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", 349115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov scanCode, usageCode, *outKeyCode); 3505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return OK; 3525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 356115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode); 3575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKeyCode = AKEYCODE_UNKNOWN; 3595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NAME_NOT_FOUND; 3605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 3615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 362115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhovvoid KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState, 363115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov int32_t *outKeyCode, int32_t *outMetaState) const { 364115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outKeyCode = keyCode; 365115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outMetaState = metaState; 366115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov 367115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov const Key* key; 368115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov const Behavior* behavior; 369115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { 370115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->replacementKeyCode) { 371115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outKeyCode = behavior->replacementKeyCode; 372115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov int32_t newMetaState = metaState & ~behavior->metaState; 373115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov // Reset dependent meta states. 374115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & AMETA_ALT_ON) { 375115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON); 376115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 377115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { 378115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~AMETA_ALT_ON; 379115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 380115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & AMETA_CTRL_ON) { 381115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON); 382115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 383115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { 384115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~AMETA_CTRL_ON; 385115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 386115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & AMETA_SHIFT_ON) { 387115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON); 388115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 389115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { 390115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newMetaState &= ~AMETA_SHIFT_ON; 391115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 392115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov // ... and put universal bits back if needed 393115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov *outMetaState = normalizeMetaState(newMetaState); 394115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 395115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 396115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov 397115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov#if DEBUG_MAPPING 398115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ " 399115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov "replacement keyCode=%d, replacement metaState=0x%08x.", 400115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov keyCode, metaState, *outKeyCode, *outMetaState); 401115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov#endif 402115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov} 403115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov 4045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { 4055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mKeys.indexOfKey(keyCode); 4065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index >= 0) { 4075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKey = mKeys.valueAt(index); 4085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 4095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 4115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 4125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState, 4145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key** outKey, const Behavior** outBehavior) const { 4155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key; 4165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (getKey(keyCode, &key)) { 4175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Behavior* behavior = key->firstBehavior; 4185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (behavior) { 4195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (matchesMetaState(metaState, behavior->metaState)) { 4205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKey = key; 4215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outBehavior = behavior; 4225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 4235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior = behavior->next; 4255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 4285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 4295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) { 4315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Behavior must have at least the set of meta states specified. 4325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // And if the key event has CTRL, ALT or META then the behavior must exactly 4335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // match those, taking into account that a behavior can specify that it handles 4345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // one, both or either of a left/right modifier pair. 4355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if ((eventMetaState & behaviorMetaState) == behaviorMetaState) { 4365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const int32_t EXACT_META_STATES = 4375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON 4385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown | AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON 4395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown | AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON; 4405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t unmatchedMetaState = eventMetaState & ~behaviorMetaState & EXACT_META_STATES; 4415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behaviorMetaState & AMETA_CTRL_ON) { 4425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON); 4435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (behaviorMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { 4445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~AMETA_CTRL_ON; 4455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behaviorMetaState & AMETA_ALT_ON) { 4475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON); 4485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (behaviorMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { 4495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~AMETA_ALT_ON; 4505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behaviorMetaState & AMETA_META_ON) { 4525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~(AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); 4535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (behaviorMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { 4545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown unmatchedMetaState &= ~AMETA_META_ON; 4555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return !unmatchedMetaState; 4575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 4595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 4605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const { 4625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!ch) { 4635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 4645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < mKeys.size(); i++) { 4675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key = mKeys.valueAt(i); 4685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Try to find the most general behavior that maps to this character. 4705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // For example, the base key behavior will usually be last in the list. 4715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Behavior* found = NULL; 4725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { 4735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (behavior->character == ch) { 4745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown found = behavior; 4755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (found) { 4785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKeyCode = mKeys.keyAt(i); 4795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMetaState = found->metaState; 4805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 4815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 4835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 4845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 4855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents, 4875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { 4885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outEvents.push(); 4895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown KeyEvent& event = outEvents.editTop(); 4905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, 4915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 4925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 0, keyCode, 0, metaState, 0, time, time); 4935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 4945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 4955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents, 4965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 4975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t* currentMetaState) { 4985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Add and remove meta keys symmetrically. 4995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (down) { 5005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); 5025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); 5045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); 5065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, 5095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, 5105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_SHIFT_ON, currentMetaState); 5115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, 5135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, 5145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_ALT_ON, currentMetaState); 5155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, 5175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, 5185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_CTRL_ON, currentMetaState); 5195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, 5215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, 5225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_META_ON, currentMetaState); 5235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); 5265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, 5275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); 5285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 5295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); 5315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); 5335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, 5365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, 5375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_META_ON, currentMetaState); 5385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, 5405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, 5415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_CTRL_ON, currentMetaState); 5425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, 5445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, 5455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_ALT_ON, currentMetaState); 5465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, 5475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, 5485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, 5495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AMETA_SHIFT_ON, currentMetaState); 5505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); 5535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); 5555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addLockedMetaKey(outEvents, deviceId, metaState, time, 5565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); 5575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 5585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 5595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents, 5615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 5625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode, int32_t keyMetaState, 5635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t* currentMetaState) { 5645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if ((metaState & keyMetaState) == keyMetaState) { 5655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *currentMetaState = updateMetaState(keyCode, down, *currentMetaState); 5665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time); 5675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 5685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 5695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 5705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 5715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents, 5735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 5745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t leftKeyCode, int32_t leftKeyMetaState, 5755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t rightKeyCode, int32_t rightKeyMetaState, 5765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t eitherKeyMetaState, 5775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t* currentMetaState) { 5785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool specific = false; 5795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, 5805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown leftKeyCode, leftKeyMetaState, currentMetaState); 5815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, 5825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown rightKeyCode, rightKeyMetaState, currentMetaState); 5835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!specific) { 5855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, 5865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown leftKeyCode, eitherKeyMetaState, currentMetaState); 5875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 5885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 5895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 5905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, 5915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t deviceId, int32_t metaState, nsecs_t time, 5925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode, int32_t keyMetaState, 5935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t* currentMetaState) { 5945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if ((metaState & keyMetaState) == keyMetaState) { 5955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *currentMetaState = updateMetaState(keyCode, true, *currentMetaState); 5965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time); 5975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *currentMetaState = updateMetaState(keyCode, false, *currentMetaState); 5985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time); 5995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 6015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6026071da7ef84c60645572654504813d492b8b21d5Elliott Hughes#ifdef __ANDROID__ 6035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownsp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { 6045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown sp<KeyCharacterMap> map = new KeyCharacterMap(); 6055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mType = parcel->readInt32(); 6065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown size_t numKeys = parcel->readInt32(); 6075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (parcel->errorCheck()) { 6085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 6095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6104c971c001f401d7742db326c8e5654693eb3687eMichael Wright if (numKeys > MAX_KEYS) { 611d57d9b900da83b1b5431d90e250f86c0047c618aIan Pedowitz ALOGE("Too many keys in KeyCharacterMap (%zu > %d)", numKeys, MAX_KEYS); 6124c971c001f401d7742db326c8e5654693eb3687eMichael Wright return NULL; 6134c971c001f401d7742db326c8e5654693eb3687eMichael Wright } 6145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numKeys; i++) { 6165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = parcel->readInt32(); 6175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t label = parcel->readInt32(); 6185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t number = parcel->readInt32(); 6195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (parcel->errorCheck()) { 6205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 6215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Key* key = new Key(); 6245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->label = label; 6255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->number = number; 6265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map->mKeys.add(keyCode, key); 6275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior* lastBehavior = NULL; 6295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (parcel->readInt32()) { 6305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t metaState = parcel->readInt32(); 6315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t character = parcel->readInt32(); 6325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t fallbackKeyCode = parcel->readInt32(); 633115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov int32_t replacementKeyCode = parcel->readInt32(); 6345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (parcel->errorCheck()) { 6355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 6365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior* behavior = new Behavior(); 6395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior->metaState = metaState; 6405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior->character = character; 6415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior->fallbackKeyCode = fallbackKeyCode; 642115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov behavior->replacementKeyCode = replacementKeyCode; 6435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (lastBehavior) { 6445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown lastBehavior->next = behavior; 6455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 6465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->firstBehavior = behavior; 6475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown lastBehavior = behavior; 6495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (parcel->errorCheck()) { 6525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 6535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return map; 6565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 6575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid KeyCharacterMap::writeToParcel(Parcel* parcel) const { 6595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(mType); 6605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown size_t numKeys = mKeys.size(); 6625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(numKeys); 6635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numKeys; i++) { 6645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = mKeys.keyAt(i); 6655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key = mKeys.valueAt(i); 6665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(keyCode); 6675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(key->label); 6685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(key->number); 6695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (const Behavior* behavior = key->firstBehavior; behavior != NULL; 6705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior = behavior->next) { 6715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(1); 6725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(behavior->metaState); 6735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(behavior->character); 6745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(behavior->fallbackKeyCode); 675115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov parcel->writeInt32(behavior->replacementKeyCode); 6765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown parcel->writeInt32(0); 6785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 6795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 6805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 6815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyCharacterMap::Key --- 6845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Key::Key() : 6865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown label(0), number(0), firstBehavior(NULL) { 6875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 6885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Key::Key(const Key& other) : 6905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown label(other.label), number(other.number), 6915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : NULL) { 6925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 6935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 6945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Key::~Key() { 6955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior* behavior = firstBehavior; 6965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (behavior) { 6975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior* next = behavior->next; 6985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete behavior; 6995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior = next; 7005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 7025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyCharacterMap::Behavior --- 7055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Behavior::Behavior() : 707115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov next(NULL), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) { 7085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 7095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Behavior::Behavior(const Behavior& other) : 7115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown next(other.next ? new Behavior(*other.next) : NULL), 7125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown metaState(other.metaState), character(other.character), 713115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov fallbackKeyCode(other.fallbackKeyCode), 714115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov replacementKeyCode(other.replacementKeyCode) { 7155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 7165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyCharacterMap::Parser --- 7195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) : 7215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) { 7225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 7235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyCharacterMap::Parser::~Parser() { 7255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 7265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parse() { 7285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (!mTokenizer->isEof()) { 7295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 7305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 7315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 7325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 7335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 7355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 7375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown switch (mState) { 7385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown case STATE_TOP: { 7395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keywordToken = mTokenizer->nextToken(WHITESPACE); 7405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (keywordToken == "type") { 7415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 7425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseType(); 7435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 7445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (keywordToken == "map") { 7455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 7465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseMap(); 7475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 7485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (keywordToken == "key") { 7495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 7505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseKey(); 7515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 7525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 7535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), 7545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keywordToken.string()); 7555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 7565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 7585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown case STATE_KEY: { 7615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseKeyProperty(); 7625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 7635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 7645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 7685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 7695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected end of line or trailing comment, got '%s'.", 7705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), 7715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 7725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 7735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->nextLine(); 7775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mState != STATE_TOP) { 7805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Unterminated key description at end of file.", 7815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 7825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 7835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) { 7865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.", 7875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 7885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 7895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 7915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mFormat == FORMAT_BASE) { 7925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mType == KEYBOARD_TYPE_OVERLAY) { 7935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.", 7945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 7955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 7965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 7975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (mFormat == FORMAT_OVERLAY) { 7985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mType != KEYBOARD_TYPE_OVERLAY) { 7995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Overlay keyboard layout missing required keyboard " 8005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "'type OVERLAY' declaration.", 8015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 8025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 8075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 8085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseType() { 8105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) { 8115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate keyboard 'type' declaration.", 8125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 8135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown KeyboardType type; 8175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 typeToken = mTokenizer->nextToken(WHITESPACE); 8185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (typeToken == "NUMERIC") { 8195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_NUMERIC; 8205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (typeToken == "PREDICTIVE") { 8215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_PREDICTIVE; 8225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (typeToken == "ALPHA") { 8235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_ALPHA; 8245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (typeToken == "FULL") { 8255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_FULL; 8265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (typeToken == "SPECIAL_FUNCTION") { 8275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_SPECIAL_FUNCTION; 8285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (typeToken == "OVERLAY") { 8295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type = KEYBOARD_TYPE_OVERLAY; 8305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 8315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(), 8325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown typeToken.string()); 8335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 8375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed type: type=%d.", type); 8385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 8395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap->mType = type; 8405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 8415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 8425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseMap() { 8445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keywordToken = mTokenizer->nextToken(WHITESPACE); 8455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (keywordToken == "key") { 8465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 8475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return parseMapKey(); 8485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(), 8505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keywordToken.string()); 8515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 8535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseMapKey() { 8555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 codeToken = mTokenizer->nextToken(WHITESPACE); 8565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool mapUsage = false; 8575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (codeToken == "usage") { 8585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage = true; 8595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 8605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown codeToken = mTokenizer->nextToken(WHITESPACE); 8615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char* end; 8645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); 8655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (*end) { 8665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), 8675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", codeToken.string()); 8685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown KeyedVector<int32_t, int32_t>& map = 8715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; 8725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (map.indexOfKey(code) >= 0) { 8735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), 8745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", codeToken.string()); 8755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 8795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); 8805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); 8815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!keyCode) { 8825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), 8835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCodeToken.string()); 8845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 8855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 8865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 8885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed map key %s: code=%d, keyCode=%d.", 8895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", code, keyCode); 8905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 8915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map.add(code, keyCode); 8925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 8935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 8945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 8955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseKey() { 8965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); 8975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); 8985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!keyCode) { 8995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), 9005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCodeToken.string()); 9015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mKeys.indexOfKey(keyCode) >= 0) { 9045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(), 9055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCodeToken.string()); 9065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 9105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 openBraceToken = mTokenizer->nextToken(WHITESPACE); 9115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (openBraceToken != "{") { 9125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected '{' after key code label, got '%s'.", 9135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), openBraceToken.string()); 9145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 9185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed beginning of key: keyCode=%d.", keyCode); 9195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 9205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mKeyCode = keyCode; 9215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap->mKeys.add(keyCode, new Key()); 9225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mState = STATE_KEY; 9235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 9245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 9255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseKeyProperty() { 9275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Key* key = mMap->mKeys.valueFor(mKeyCode); 9285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); 9295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token == "}") { 9305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mState = STATE_TOP; 9315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return finishKey(key); 9325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Vector<Property> properties; 9355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Parse all comma-delimited property names up to the first colon. 9375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (;;) { 9385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token == "label") { 9395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown properties.add(Property(PROPERTY_LABEL)); 9405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (token == "number") { 9415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown properties.add(Property(PROPERTY_NUMBER)); 9425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 9435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t metaState; 9445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseModifier(token, &metaState); 9455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 9465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected a property name or modifier, got '%s'.", 9475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), token.string()); 9485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 9495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown properties.add(Property(PROPERTY_META, metaState)); 9515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 9545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol()) { 9555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char ch = mTokenizer->nextChar(); 9565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == ':') { 9575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 9585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == ',') { 9595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 9605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); 9615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown continue; 9625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected ',' or ':' after property name.", 9665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 9675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Parse behavior after the colon. 9715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 9725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior behavior; 9745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool haveCharacter = false; 9755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool haveFallback = false; 976115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov bool haveReplacement = false; 9775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 9785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown do { 9795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char ch = mTokenizer->peekChar(); 9805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == '\'') { 9815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t character; 9825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseCharacterLiteral(&character); 9835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status || !character) { 9845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Invalid character literal for key.", 9855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 9865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 9885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (haveCharacter) { 9895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Cannot combine multiple character literals or 'none'.", 9905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 9915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 9925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 993115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (haveReplacement) { 994115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Cannot combine character literal with replace action.", 995115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->getLocation().string()); 996115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov return BAD_VALUE; 997115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 9985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior.character = character; 9995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown haveCharacter = true; 10005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 10015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown token = mTokenizer->nextToken(WHITESPACE); 10025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token == "none") { 10035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (haveCharacter) { 10045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Cannot combine multiple character literals or 'none'.", 10055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1008115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (haveReplacement) { 1009115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Cannot combine 'none' with replace action.", 1010115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->getLocation().string()); 1011115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov return BAD_VALUE; 1012115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 10135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown haveCharacter = true; 10145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (token == "fallback") { 10155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 10165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown token = mTokenizer->nextToken(WHITESPACE); 10175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = getKeyCodeByLabel(token.string()); 10185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!keyCode) { 10195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.", 10205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), 10215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown token.string()); 10225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1024115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (haveFallback || haveReplacement) { 1025115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Cannot combine multiple fallback/replacement key codes.", 10265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown behavior.fallbackKeyCode = keyCode; 10305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown haveFallback = true; 1031115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } else if (token == "replace") { 1032115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->skipDelimiters(WHITESPACE); 1033115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov token = mTokenizer->nextToken(WHITESPACE); 1034115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov int32_t keyCode = getKeyCodeByLabel(token.string()); 1035115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (!keyCode) { 1036115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Invalid key code label for replace, got '%s'.", 1037115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->getLocation().string(), 1038115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov token.string()); 1039115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov return BAD_VALUE; 1040115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 1041115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (haveCharacter) { 1042115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Cannot combine character literal with replace action.", 1043115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->getLocation().string()); 1044115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov return BAD_VALUE; 1045115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 1046115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov if (haveFallback || haveReplacement) { 1047115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGE("%s: Cannot combine multiple fallback/replacement key codes.", 1048115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mTokenizer->getLocation().string()); 1049115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov return BAD_VALUE; 1050115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov } 1051115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov behavior.replacementKeyCode = keyCode; 1052115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov haveReplacement = true; 1053115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov 10545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 10555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected a key behavior after ':'.", 10565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 10615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 10625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#'); 10635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 10645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Add the behavior. 10655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < properties.size(); i++) { 10665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Property& property = properties.itemAt(i); 10675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown switch (property.property) { 10685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown case PROPERTY_LABEL: 10695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (key->label) { 10705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate label for key.", 10715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->label = behavior.character; 10755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 10765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label); 10775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 10785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 10795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown case PROPERTY_NUMBER: 10805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (key->number) { 10815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate number for key.", 10825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->number = behavior.character; 10865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 10875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number); 10885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 10895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 10905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown case PROPERTY_META: { 10915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (Behavior* b = key->firstBehavior; b; b = b->next) { 10925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (b->metaState == property.metaState) { 10935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate key behavior for modifier.", 10945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 10955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 10965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 10985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Behavior* newBehavior = new Behavior(behavior); 10995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown newBehavior->metaState = property.metaState; 11005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown newBehavior->next = key->firstBehavior; 11015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->firstBehavior = newBehavior; 11025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 1103115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.", 1104115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov mKeyCode, 1105115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newBehavior->metaState, newBehavior->character, 1106115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov newBehavior->fallbackKeyCode, newBehavior->replacementKeyCode); 11075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 11085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 11095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 11135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 11145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::finishKey(Key* key) { 11165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Fill in default number property. 11175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!key->number) { 11185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t digit = 0; 11195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t symbol = 0; 11205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (Behavior* b = key->firstBehavior; b; b = b->next) { 11215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char16_t ch = b->character; 11225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch) { 11235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch >= '0' && ch <= '9') { 11245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown digit = ch; 11255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*' 11265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown || ch == '-' || ch == '+' || ch == ',' || ch == '.' 11275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown || ch == '\'' || ch == ':' || ch == ';' || ch == '/') { 11285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown symbol = ch; 11295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key->number = digit ? digit : symbol; 11335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 11355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 11365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) { 11385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token == "base") { 11395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMetaState = 0; 11405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 11415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t combinedMeta = 0; 11445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const char* str = token.string(); 11465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const char* start = str; 11475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (const char* cur = str; ; cur++) { 11485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char ch = *cur; 11495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == '+' || ch == '\0') { 11505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown size_t len = cur - start; 11515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t metaState = 0; 11525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) { 11535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (strlen(modifiers[i].label) == len 11545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown && strncmp(modifiers[i].label, start, len) == 0) { 11555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown metaState = modifiers[i].metaState; 11565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 11575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!metaState) { 11605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 11615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (combinedMeta & metaState) { 11635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate modifier combination '%s'.", 11645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), token.string()); 11655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 11665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown combinedMeta |= metaState; 11695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown start = cur + 1; 11705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == '\0') { 11725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 11735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMetaState = combinedMeta; 11775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 11785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 11795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) { 11815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char ch = mTokenizer->nextChar(); 11825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch != '\'') { 11835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto Error; 11845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 11855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 11865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ch = mTokenizer->nextChar(); 11875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == '\\') { 11885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Escape sequence. 11895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ch = mTokenizer->nextChar(); 11905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch == 'n') { 11915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = '\n'; 11925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == 't') { 11935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = '\t'; 11945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == '\\') { 11955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = '\\'; 11965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == '\'') { 11975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = '\''; 11985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == '"') { 11995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = '"'; 12005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch == 'u') { 12015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = 0; 12025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (int i = 0; i < 4; i++) { 12035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ch = mTokenizer->nextChar(); 12045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int digit; 12055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch >= '0' && ch <= '9') { 12065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown digit = ch - '0'; 12075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch >= 'A' && ch <= 'F') { 12085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown digit = ch - 'A' + 10; 12095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch >= 'a' && ch <= 'f') { 12105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown digit = ch - 'a' + 10; 12115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 12125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto Error; 12135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = (*outCharacter << 4) | digit; 12155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 12175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto Error; 12185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (ch >= 32 && ch <= 126 && ch != '\'') { 12205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // ASCII literal character. 12215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outCharacter = ch; 12225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 12235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto Error; 12245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 12265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ch = mTokenizer->nextChar(); 12275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (ch != '\'') { 12285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown goto Error; 12295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 12315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Ensure that we consumed the entire token. 12325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mTokenizer->nextToken(WHITESPACE).isEmpty()) { 12335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 12345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 12355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 12365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownError: 12375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string()); 12385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 12395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 12405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 12415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} // namespace android 1242