19065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown/* 29065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * Copyright (C) 2010 The Android Open Source Project 39065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * 49065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 59065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * you may not use this file except in compliance with the License. 69065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * You may obtain a copy of the License at 79065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * 89065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 99065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * 109065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * Unless required by applicable law or agreed to in writing, software 119065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 129065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * See the License for the specific language governing permissions and 149065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown * limitations under the License. 159065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown */ 169065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 179065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#define LOG_TAG "VirtualKeyMap" 189065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 199065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <stdlib.h> 209065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <string.h> 21b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/VirtualKeyMap.h> 229065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <utils/Log.h> 239065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <utils/Errors.h> 249065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <utils/Tokenizer.h> 259065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <utils/Timers.h> 269065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 279065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// Enables debug output for the parser. 289065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#define DEBUG_PARSER 0 299065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 309065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// Enables debug output for parser performance. 319065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#define DEBUG_PARSER_PERFORMANCE 0 329065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 339065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 349065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownnamespace android { 359065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 369065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatic const char* WHITESPACE = " \t\r"; 379065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatic const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:"; 389065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 399065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 409065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// --- VirtualKeyMap --- 419065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 429065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownVirtualKeyMap::VirtualKeyMap() { 439065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 449065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 459065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownVirtualKeyMap::~VirtualKeyMap() { 469065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 479065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 489065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatus_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { 499065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown *outMap = NULL; 509065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 519065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown Tokenizer* tokenizer; 529065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown status_t status = Tokenizer::open(filename, &tokenizer); 539065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status) { 543762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error %d opening virtual key map file %s.", status, filename.string()); 559065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } else { 569065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown VirtualKeyMap* map = new VirtualKeyMap(); 579065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!map) { 583762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error allocating virtual key map."); 599065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown status = NO_MEMORY; 609065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } else { 619065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#if DEBUG_PARSER_PERFORMANCE 629065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 639065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#endif 649065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown Parser parser(map, tokenizer); 659065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown status = parser.parse(); 669065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#if DEBUG_PARSER_PERFORMANCE 679065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 685baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", 699065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown tokenizer->getFilename().string(), tokenizer->getLineNumber(), 709065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown elapsedTime / 1000000.0); 719065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#endif 729065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status) { 739065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown delete map; 749065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } else { 759065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown *outMap = map; 769065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 779065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 789065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown delete tokenizer; 799065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 809065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return status; 819065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 829065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 839065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 849065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// --- VirtualKeyMap::Parser --- 859065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 869065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownVirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) : 879065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mMap(map), mTokenizer(tokenizer) { 889065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 899065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 909065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownVirtualKeyMap::Parser::~Parser() { 919065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 929065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 939065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatus_t VirtualKeyMap::Parser::parse() { 949065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown while (!mTokenizer->isEof()) { 959065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#if DEBUG_PARSER 965baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 979065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->peekRemainderOfLine().string()); 989065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#endif 999065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1009065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1019065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1029065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 1039065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown // Multiple keys can appear on one line or they can be broken up across multiple lines. 1049065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown do { 1059065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1069065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (token != "0x01") { 1073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("%s: Unknown virtual key type, expected 0x01.", 1089065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->getLocation().string()); 1099065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return BAD_VALUE; 1109065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1119065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1129065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown VirtualKeyDefinition defn; 1139065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown bool success = parseNextIntField(&defn.scanCode) 1149065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown && parseNextIntField(&defn.centerX) 1159065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown && parseNextIntField(&defn.centerY) 1169065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown && parseNextIntField(&defn.width) 1179065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown && parseNextIntField(&defn.height); 1189065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!success) { 1193762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.", 1209065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->getLocation().string()); 1219065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return BAD_VALUE; 1229065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1239065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1249065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#if DEBUG_PARSER 1255baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, " 1269065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown "width=%d, height=%d", 1279065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height); 1289065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#endif 1299065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mMap->mVirtualKeys.push(defn); 1309065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } while (consumeFieldDelimiterAndSkipWhitespace()); 1319065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1329065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!mTokenizer->isEol()) { 1333762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("%s: Expected end of line, got '%s'.", 1349065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->getLocation().string(), 1359065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->peekRemainderOfLine().string()); 1369065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return BAD_VALUE; 1379065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1389065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1399065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1409065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->nextLine(); 1419065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1429065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1439065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return NO_ERROR; 1449065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1459065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1469065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownbool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() { 1479065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1489065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (mTokenizer->peekChar() == ':') { 1499065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->nextChar(); 1509065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1519065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return true; 1529065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1539065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return false; 1549065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1559065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1569065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownbool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) { 1579065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!consumeFieldDelimiterAndSkipWhitespace()) { 1589065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return false; 1599065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1609065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1619065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1629065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown char* end; 1639065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown *outValue = strtol(token.string(), &end, 0); 1649065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (token.isEmpty() || *end != '\0') { 1653762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Expected an integer, got '%s'.", token.string()); 1669065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return false; 1679065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1689065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return true; 1699065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1709065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1719065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} // namespace android 172