VirtualKeyMap.cpp revision 5912f95d26f77d2b6df13e1f2672e48e3f9b871c
15912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown/* 25912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Copyright (C) 2010 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 "VirtualKeyMap" 185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <stdlib.h> 205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <string.h> 215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/VirtualKeyMap.h> 235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Log.h> 245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Errors.h> 255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Tokenizer.h> 265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Timers.h> 275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for the parser. 295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER 0 305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for parser performance. 325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER_PERFORMANCE 0 335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownnamespace android { 365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* WHITESPACE = " \t\r"; 385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:"; 395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- VirtualKeyMap --- 425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownVirtualKeyMap::VirtualKeyMap() { 445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownVirtualKeyMap::~VirtualKeyMap() { 475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { 505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMap = NULL; 515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Tokenizer* tokenizer; 535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = Tokenizer::open(filename, &tokenizer); 545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error %d opening virtual key map file %s.", status, filename.string()); 565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown VirtualKeyMap* map = new VirtualKeyMap(); 585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!map) { 595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error allocating virtual key map."); 605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = NO_MEMORY; 615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Parser parser(map, tokenizer); 665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = parser.parse(); 675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", 705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown tokenizer->getFilename().string(), tokenizer->getLineNumber(), 715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown elapsedTime / 1000000.0); 725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete map; 755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMap = map; 775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete tokenizer; 805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- VirtualKeyMap::Parser --- 865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownVirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) : 885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap(map), mTokenizer(tokenizer) { 895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownVirtualKeyMap::Parser::~Parser() { 925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t VirtualKeyMap::Parser::parse() { 955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (!mTokenizer->isEof()) { 965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 1045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Multiple keys can appear on one line or they can be broken up across multiple lines. 1055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown do { 1065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token != "0x01") { 1085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Unknown virtual key type, expected 0x01.", 1095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 1105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 1115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown VirtualKeyDefinition defn; 1145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool success = parseNextIntField(&defn.scanCode) 1155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown && parseNextIntField(&defn.centerX) 1165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown && parseNextIntField(&defn.centerY) 1175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown && parseNextIntField(&defn.width) 1185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown && parseNextIntField(&defn.height); 1195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!success) { 1205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.", 1215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string()); 1225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 1235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 1265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, " 1275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "width=%d, height=%d", 1285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height); 1295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap->mVirtualKeys.push(defn); 1315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } while (consumeFieldDelimiterAndSkipWhitespace()); 1325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol()) { 1345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected end of line, got '%s'.", 1355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), 1365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 1375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 1385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->nextLine(); 1425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 1455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() { 1485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mTokenizer->peekChar() == ':') { 1505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->nextChar(); 1515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 1535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 1555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) { 1585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!consumeFieldDelimiterAndSkipWhitespace()) { 1595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 1605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char* end; 1645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outValue = strtol(token.string(), &end, 0); 1655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token.isEmpty() || *end != '\0') { 1665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Expected an integer, got '%s'.", token.string()); 1675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return false; 1685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return true; 1705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} // namespace android 173