diff options
Diffstat (limited to 'libs/input/KeyLayoutMap.cpp')
| -rw-r--r-- | libs/input/KeyLayoutMap.cpp | 82 | 
1 files changed, 66 insertions, 16 deletions
| diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index 17c3bb36e3..170e748ca6 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -25,6 +25,8 @@  #include <utils/Errors.h>  #include <utils/Timers.h>  #include <utils/Tokenizer.h> +#include <vintf/RuntimeInfo.h> +#include <vintf/VintfObject.h>  #include <cstdlib>  #include <string_view> @@ -76,6 +78,29 @@ static const std::unordered_map<std::string_view, InputDeviceSensorType> SENSOR_           sensorPair<InputDeviceSensorType::GYROSCOPE_UNCALIBRATED>(),           sensorPair<InputDeviceSensorType::SIGNIFICANT_MOTION>()}; +bool kernelConfigsArePresent(const std::set<std::string>& configs) { +    std::shared_ptr<const android::vintf::RuntimeInfo> runtimeInfo = +            android::vintf::VintfObject::GetInstance()->getRuntimeInfo( +                    vintf::RuntimeInfo::FetchFlag::CONFIG_GZ); +    LOG_ALWAYS_FATAL_IF(runtimeInfo == nullptr, "Kernel configs could not be fetched"); + +    const std::map<std::string, std::string>& kernelConfigs = runtimeInfo->kernelConfigs(); +    for (const std::string& requiredConfig : configs) { +        const auto configIt = kernelConfigs.find(requiredConfig); +        if (configIt == kernelConfigs.end()) { +            ALOGI("Required kernel config %s is not found", requiredConfig.c_str()); +            return false; +        } +        const std::string& option = configIt->second; +        if (option != "y" && option != "m") { +            ALOGI("Required kernel config %s has option %s", requiredConfig.c_str(), +                  option.c_str()); +            return false; +        } +    } +    return true; +} +  } // namespace  KeyLayoutMap::KeyLayoutMap() = default; @@ -83,32 +108,34 @@ KeyLayoutMap::~KeyLayoutMap() = default;  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; +    return load(filename, contents);  } -base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(const std::string& filename) { +base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(const std::string& filename, +                                                               const char* contents) {      Tokenizer* tokenizer; -    status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer); +    status_t status; +    if (contents == nullptr) { +        status = Tokenizer::open(String8(filename.c_str()), &tokenizer); +    } else { +        status = Tokenizer::fromContents(String8(filename.c_str()), contents, &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; +    if (!ret.ok()) { +        return ret; +    } +    const std::shared_ptr<KeyLayoutMap>& map = *ret; +    LOG_ALWAYS_FATAL_IF(map == nullptr, "Returned map should not be null if there's no error"); +    if (!kernelConfigsArePresent(map->mRequiredKernelConfigs)) { +        ALOGI("Not loading %s because the required kernel configs are not set", filename.c_str()); +        return Errorf("Missing kernel config");      } +    map->mLoadFileName = filename;      return ret;  } @@ -278,6 +305,10 @@ status_t KeyLayoutMap::Parser::parse() {                  mTokenizer->skipDelimiters(WHITESPACE);                  status_t status = parseSensor();                  if (status) return status; +            } else if (keywordToken == "requires_kernel_config") { +                mTokenizer->skipDelimiters(WHITESPACE); +                status_t status = parseRequiredKernelConfig(); +                if (status) return status;              } else {                  ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),                          keywordToken.string()); @@ -579,4 +610,23 @@ status_t KeyLayoutMap::Parser::parseSensor() {      return NO_ERROR;  } +// Parse the name of a required kernel config. +// The layout won't be used if the specified kernel config is not present +// Examples: +// requires_kernel_config CONFIG_HID_PLAYSTATION +status_t KeyLayoutMap::Parser::parseRequiredKernelConfig() { +    String8 codeToken = mTokenizer->nextToken(WHITESPACE); +    std::string configName = codeToken.string(); + +    const auto result = mMap->mRequiredKernelConfigs.emplace(configName); +    if (!result.second) { +        ALOGE("%s: Duplicate entry for required kernel config %s.", +              mTokenizer->getLocation().string(), configName.c_str()); +        return BAD_VALUE; +    } + +    ALOGD_IF(DEBUG_PARSER, "Parsed required kernel config: name=%s", configName.c_str()); +    return NO_ERROR; +} +  } // namespace android |