diff options
Diffstat (limited to 'libs/input/KeyLayoutMap.cpp')
-rw-r--r-- | libs/input/KeyLayoutMap.cpp | 204 |
1 files changed, 175 insertions, 29 deletions
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index efca68d171..fa5a5412e6 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -20,12 +20,13 @@ #include <android/keycodes.h> #include <input/InputEventLabels.h> -#include <input/Keyboard.h> #include <input/KeyLayoutMap.h> -#include <utils/Log.h> +#include <input/Keyboard.h> +#include <input/NamedEnum.h> #include <utils/Errors.h> -#include <utils/Tokenizer.h> +#include <utils/Log.h> #include <utils/Timers.h> +#include <utils/Tokenizer.h> // Enables debug output for the parser. #define DEBUG_PARSER 0 @@ -41,6 +42,26 @@ namespace android { static const char* WHITESPACE = " \t\r"; +#define SENSOR_ENTRY(type) NamedEnum::string(type), type +static const std::unordered_map<std::string, InputDeviceSensorType> SENSOR_LIST = + {{SENSOR_ENTRY(InputDeviceSensorType::ACCELEROMETER)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD)}, + {SENSOR_ENTRY(InputDeviceSensorType::ORIENTATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE)}, + {SENSOR_ENTRY(InputDeviceSensorType::LIGHT)}, + {SENSOR_ENTRY(InputDeviceSensorType::PRESSURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::PROXIMITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::GRAVITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::LINEAR_ACCELERATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::RELATIVE_HUMIDITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::AMBIENT_TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::GAME_ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::SIGNIFICANT_MOTION)}}; + // --- KeyLayoutMap --- KeyLayoutMap::KeyLayoutMap() { @@ -49,37 +70,60 @@ KeyLayoutMap::KeyLayoutMap() { KeyLayoutMap::~KeyLayoutMap() { } -status_t KeyLayoutMap::load(const std::string& filename, sp<KeyLayoutMap>* outMap) { - outMap->clear(); +base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::loadContents(const std::string& filename, + const char* contents) { + Tokenizer* tokenizer; + status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer); + if (status) { + ALOGE("Error %d opening key layout map.", status); + return Errorf("Error {} opening key layout map file {}.", status, filename.c_str()); + } + std::unique_ptr<Tokenizer> t(tokenizer); + auto ret = load(t.get()); + if (ret.ok()) { + (*ret)->mLoadFileName = filename; + } + return ret; +} +base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(const std::string& filename) { Tokenizer* tokenizer; status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer); if (status) { ALOGE("Error %d opening key layout map file %s.", status, filename.c_str()); + return Errorf("Error {} opening key layout map file {}.", status, filename.c_str()); + } + std::unique_ptr<Tokenizer> t(tokenizer); + auto ret = load(t.get()); + if (ret.ok()) { + (*ret)->mLoadFileName = filename; + } + return ret; +} + +base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(Tokenizer* tokenizer) { + std::shared_ptr<KeyLayoutMap> map = std::shared_ptr<KeyLayoutMap>(new KeyLayoutMap()); + status_t status = OK; + if (!map.get()) { + ALOGE("Error allocating key layout map."); + return Errorf("Error allocating key layout map."); } else { - sp<KeyLayoutMap> map = new KeyLayoutMap(); - if (!map.get()) { - ALOGE("Error allocating key layout map."); - status = NO_MEMORY; - } else { #if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); #endif - Parser parser(map.get(), tokenizer); - status = parser.parse(); + Parser parser(map.get(), tokenizer); + status = parser.parse(); #if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); + nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; + ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.", + tokenizer->getFilename().string(), tokenizer->getLineNumber(), + elapsedTime / 1000000.0); #endif - if (!status) { - *outMap = map; - } + if (!status) { + return std::move(map); } - delete tokenizer; } - return status; + return Errorf("Load KeyLayoutMap failed {}.", status); } status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, @@ -104,6 +148,24 @@ status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, return NO_ERROR; } +// Return pair of sensor type and sensor data index, for the input device abs code +base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(int32_t absCode) { + auto it = mSensorsByAbsCode.find(absCode); + if (it == mSensorsByAbsCode.end()) { +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, ~ Failed.", absCode); +#endif + return Errorf("Can't find abs code {}.", absCode); + } + const Sensor& sensor = it->second; + +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, sensorType=0x%0x, sensorDataIndex=0x%x.", absCode, + NamedEnum::string(sensor.sensorType), sensor.sensorDataIndex); +#endif + return std::make_pair(sensor.sensorType, sensor.sensorDataIndex); +} + const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { if (usageCode) { ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); @@ -219,6 +281,10 @@ status_t KeyLayoutMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseLed(); if (status) return status; + } else if (keywordToken == "sensor") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseSensor(); + if (status) return status; } else { ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), keywordToken.string()); @@ -264,7 +330,7 @@ status_t KeyLayoutMap::Parser::parseKey() { mTokenizer->skipDelimiters(WHITESPACE); String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string()); if (!keyCode) { ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), keyCodeToken.string()); @@ -277,7 +343,7 @@ status_t KeyLayoutMap::Parser::parseKey() { if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break; String8 flagToken = mTokenizer->nextToken(WHITESPACE); - uint32_t flag = getKeyFlagByLabel(flagToken.string()); + uint32_t flag = InputEventLookup::getKeyFlagByLabel(flagToken.string()); if (!flag) { ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), flagToken.string()); @@ -326,7 +392,7 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 axisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(axisToken.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(axisToken.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected inverted axis label, got '%s'.", mTokenizer->getLocation().string(), axisToken.string()); @@ -346,7 +412,7 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(lowAxisToken.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(lowAxisToken.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected low axis label, got '%s'.", mTokenizer->getLocation().string(), lowAxisToken.string()); @@ -355,14 +421,14 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); + axisInfo.highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string()); if (axisInfo.highAxis < 0) { ALOGE("%s: Expected high axis label, got '%s'.", mTokenizer->getLocation().string(), highAxisToken.string()); return BAD_VALUE; } } else { - axisInfo.axis = getAxisByLabel(token.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(token.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", mTokenizer->getLocation().string(), token.string()); @@ -428,7 +494,7 @@ status_t KeyLayoutMap::Parser::parseLed() { mTokenizer->skipDelimiters(WHITESPACE); String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t ledCode = getLedByLabel(ledCodeToken.string()); + int32_t ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string()); if (ledCode < 0) { ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(), ledCodeToken.string()); @@ -445,4 +511,84 @@ status_t KeyLayoutMap::Parser::parseLed() { map.add(code, led); return NO_ERROR; } + +static std::optional<InputDeviceSensorType> getSensorType(const char* token) { + auto it = SENSOR_LIST.find(std::string(token)); + if (it == SENSOR_LIST.end()) { + return std::nullopt; + } + return it->second; +} + +static std::optional<int32_t> getSensorDataIndex(String8 token) { + std::string tokenStr(token.string()); + if (tokenStr == "X") { + return 0; + } else if (tokenStr == "Y") { + return 1; + } else if (tokenStr == "Z") { + return 2; + } + return std::nullopt; +} + +// Parse sensor type and data index mapping, as below format +// sensor <raw abs> <sensor type> <sensor data index> +// raw abs : the linux abs code of the axis +// sensor type : string name of InputDeviceSensorType +// sensor data index : the data index of sensor, out of [X, Y, Z] +// Examples: +// sensor 0x00 ACCELEROMETER X +// sensor 0x01 ACCELEROMETER Y +// sensor 0x02 ACCELEROMETER Z +// sensor 0x03 GYROSCOPE X +// sensor 0x04 GYROSCOPE Y +// sensor 0x05 GYROSCOPE Z +status_t KeyLayoutMap::Parser::parseSensor() { + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + char* end; + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); + if (*end) { + ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + std::unordered_map<int32_t, Sensor>& map = mMap->mSensorsByAbsCode; + if (map.find(code) != map.end()) { + ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorTypeToken = mTokenizer->nextToken(WHITESPACE); + std::optional<InputDeviceSensorType> typeOpt = getSensorType(sensorTypeToken.string()); + if (!typeOpt) { + ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().string(), + sensorTypeToken.string()); + return BAD_VALUE; + } + InputDeviceSensorType sensorType = typeOpt.value(); + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorDataIndexToken = mTokenizer->nextToken(WHITESPACE); + std::optional<int32_t> indexOpt = getSensorDataIndex(sensorDataIndexToken); + if (!indexOpt) { + ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().string(), + sensorDataIndexToken.string()); + return BAD_VALUE; + } + int32_t sensorDataIndex = indexOpt.value(); + +#if DEBUG_PARSER + ALOGD("Parsed sensor: abs code=%d, sensorType=%d, sensorDataIndex=%d.", code, + NamedEnum::string(sensorType).c_str(), sensorDataIndex); +#endif + + Sensor sensor; + sensor.sensorType = sensorType; + sensor.sensorDataIndex = sensorDataIndex; + map.emplace(code, sensor); + return NO_ERROR; +} }; |