VirtualKeyMap.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "VirtualKeyMap"
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <input/VirtualKeyMap.h>
  20. #include <utils/Log.h>
  21. #include <utils/Errors.h>
  22. #include <utils/Tokenizer.h>
  23. #include <utils/Timers.h>
  24. // Enables debug output for the parser.
  25. #define DEBUG_PARSER 0
  26. // Enables debug output for parser performance.
  27. #define DEBUG_PARSER_PERFORMANCE 0
  28. namespace android {
  29. static const char* WHITESPACE = " \t\r";
  30. static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:";
  31. // --- VirtualKeyMap ---
  32. VirtualKeyMap::VirtualKeyMap() {
  33. }
  34. VirtualKeyMap::~VirtualKeyMap() {
  35. }
  36. status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) {
  37. *outMap = NULL;
  38. Tokenizer* tokenizer;
  39. status_t status = Tokenizer::open(filename, &tokenizer);
  40. if (status) {
  41. ALOGE("Error %d opening virtual key map file %s.", status, filename.string());
  42. } else {
  43. VirtualKeyMap* map = new VirtualKeyMap();
  44. if (!map) {
  45. ALOGE("Error allocating virtual key map.");
  46. status = NO_MEMORY;
  47. } else {
  48. #if DEBUG_PARSER_PERFORMANCE
  49. nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
  50. #endif
  51. Parser parser(map, tokenizer);
  52. status = parser.parse();
  53. #if DEBUG_PARSER_PERFORMANCE
  54. nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
  55. ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
  56. tokenizer->getFilename().string(), tokenizer->getLineNumber(),
  57. elapsedTime / 1000000.0);
  58. #endif
  59. if (status) {
  60. delete map;
  61. } else {
  62. *outMap = map;
  63. }
  64. }
  65. delete tokenizer;
  66. }
  67. return status;
  68. }
  69. // --- VirtualKeyMap::Parser ---
  70. VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) :
  71. mMap(map), mTokenizer(tokenizer) {
  72. }
  73. VirtualKeyMap::Parser::~Parser() {
  74. }
  75. status_t VirtualKeyMap::Parser::parse() {
  76. while (!mTokenizer->isEof()) {
  77. #if DEBUG_PARSER
  78. ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
  79. mTokenizer->peekRemainderOfLine().string());
  80. #endif
  81. mTokenizer->skipDelimiters(WHITESPACE);
  82. if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
  83. // Multiple keys can appear on one line or they can be broken up across multiple lines.
  84. do {
  85. String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
  86. if (token != "0x01") {
  87. ALOGE("%s: Unknown virtual key type, expected 0x01.",
  88. mTokenizer->getLocation().string());
  89. return BAD_VALUE;
  90. }
  91. VirtualKeyDefinition defn;
  92. bool success = parseNextIntField(&defn.scanCode)
  93. && parseNextIntField(&defn.centerX)
  94. && parseNextIntField(&defn.centerY)
  95. && parseNextIntField(&defn.width)
  96. && parseNextIntField(&defn.height);
  97. if (!success) {
  98. ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.",
  99. mTokenizer->getLocation().string());
  100. return BAD_VALUE;
  101. }
  102. #if DEBUG_PARSER
  103. ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, "
  104. "width=%d, height=%d",
  105. defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height);
  106. #endif
  107. mMap->mVirtualKeys.push(defn);
  108. } while (consumeFieldDelimiterAndSkipWhitespace());
  109. if (!mTokenizer->isEol()) {
  110. ALOGE("%s: Expected end of line, got '%s'.",
  111. mTokenizer->getLocation().string(),
  112. mTokenizer->peekRemainderOfLine().string());
  113. return BAD_VALUE;
  114. }
  115. }
  116. mTokenizer->nextLine();
  117. }
  118. return NO_ERROR;
  119. }
  120. bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() {
  121. mTokenizer->skipDelimiters(WHITESPACE);
  122. if (mTokenizer->peekChar() == ':') {
  123. mTokenizer->nextChar();
  124. mTokenizer->skipDelimiters(WHITESPACE);
  125. return true;
  126. }
  127. return false;
  128. }
  129. bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) {
  130. if (!consumeFieldDelimiterAndSkipWhitespace()) {
  131. return false;
  132. }
  133. String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
  134. char* end;
  135. *outValue = strtol(token.string(), &end, 0);
  136. if (token.isEmpty() || *end != '\0') {
  137. ALOGE("Expected an integer, got '%s'.", token.string());
  138. return false;
  139. }
  140. return true;
  141. }
  142. } // namespace android