/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "KeyLayoutMap"

#include <android-base/logging.h>
#include <android/keycodes.h>
#include <ftl/enum.h>
#include <input/InputEventLabels.h>
#include <input/KeyLayoutMap.h>
#include <input/Keyboard.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/Tokenizer.h>
#if defined(__ANDROID__)
#include <vintf/RuntimeInfo.h>
#include <vintf/VintfObject.h>
#endif

#include <cstdlib>
#include <string_view>
#include <unordered_map>

/**
 * Log debug output for the parser.
 * Enable this via "adb shell setprop log.tag.KeyLayoutMapParser DEBUG" (requires restart)
 */
const bool DEBUG_PARSER =
        __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Parser", ANDROID_LOG_INFO);

// Enables debug output for parser performance.
#define DEBUG_PARSER_PERFORMANCE 0

/**
 * Log debug output for mapping.
 * Enable this via "adb shell setprop log.tag.KeyLayoutMapMapping DEBUG" (requires restart)
 */
const bool DEBUG_MAPPING =
        __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Mapping", ANDROID_LOG_INFO);

namespace android {
namespace {

std::optional<int> parseInt(const char* str) {
    char* end;
    errno = 0;
    const int value = strtol(str, &end, 0);
    if (end == str) {
        LOG(ERROR) << "Could not parse " << str;
        return {};
    }
    if (errno == ERANGE) {
        LOG(ERROR) << "Out of bounds: " << str;
        return {};
    }
    return value;
}

constexpr const char* WHITESPACE = " \t\r";

template <InputDeviceSensorType S>
constexpr auto sensorPair() {
    return std::make_pair(ftl::enum_name<S>(), S);
}

static const std::unordered_map<std::string_view, InputDeviceSensorType> SENSOR_LIST =
        {sensorPair<InputDeviceSensorType::ACCELEROMETER>(),
         sensorPair<InputDeviceSensorType::MAGNETIC_FIELD>(),
         sensorPair<InputDeviceSensorType::ORIENTATION>(),
         sensorPair<InputDeviceSensorType::GYROSCOPE>(),
         sensorPair<InputDeviceSensorType::LIGHT>(),
         sensorPair<InputDeviceSensorType::PRESSURE>(),
         sensorPair<InputDeviceSensorType::TEMPERATURE>(),
         sensorPair<InputDeviceSensorType::PROXIMITY>(),
         sensorPair<InputDeviceSensorType::GRAVITY>(),
         sensorPair<InputDeviceSensorType::LINEAR_ACCELERATION>(),
         sensorPair<InputDeviceSensorType::ROTATION_VECTOR>(),
         sensorPair<InputDeviceSensorType::RELATIVE_HUMIDITY>(),
         sensorPair<InputDeviceSensorType::AMBIENT_TEMPERATURE>(),
         sensorPair<InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED>(),
         sensorPair<InputDeviceSensorType::GAME_ROTATION_VECTOR>(),
         sensorPair<InputDeviceSensorType::GYROSCOPE_UNCALIBRATED>(),
         sensorPair<InputDeviceSensorType::SIGNIFICANT_MOTION>()};

bool kernelConfigsArePresent(const std::set<std::string>& configs) {
#if defined(__ANDROID__)
    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;
#else
    (void)configs; // Suppress 'unused variable' warning
    return true;
#endif
}

} // namespace

KeyLayoutMap::KeyLayoutMap() = default;
KeyLayoutMap::~KeyLayoutMap() = default;

base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::loadContents(const std::string& filename,
                                                                       const char* contents) {
    return load(filename, contents);
}

base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(const std::string& filename,
                                                               const char* contents) {
    Tokenizer* 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()) {
        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;
}

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 {
#if DEBUG_PARSER_PERFORMANCE
        nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
#endif
        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);
#endif
        if (!status) {
            return std::move(map);
        }
    }
    return Errorf("Load KeyLayoutMap failed {}.", status);
}

status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode,
        int32_t* outKeyCode, uint32_t* outFlags) const {
    const Key* key = getKey(scanCode, usageCode);
    if (!key) {
        ALOGD_IF(DEBUG_MAPPING, "mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode,
                 usageCode);
        *outKeyCode = AKEYCODE_UNKNOWN;
        *outFlags = 0;
        return NAME_NOT_FOUND;
    }

    *outKeyCode = key->keyCode;
    *outFlags = key->flags;

    ALOGD_IF(DEBUG_MAPPING,
             "mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.",
             scanCode, usageCode, *outKeyCode, *outFlags);
    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) const {
    auto it = mSensorsByAbsCode.find(absCode);
    if (it == mSensorsByAbsCode.end()) {
        ALOGD_IF(DEBUG_MAPPING, "mapSensor: absCode=%d, ~ Failed.", absCode);
        return Errorf("Can't find abs code {}.", absCode);
    }
    const Sensor& sensor = it->second;
    ALOGD_IF(DEBUG_MAPPING, "mapSensor: absCode=%d, sensorType=%s, sensorDataIndex=0x%x.", absCode,
             ftl::enum_string(sensor.sensorType).c_str(), sensor.sensorDataIndex);
    return std::make_pair(sensor.sensorType, sensor.sensorDataIndex);
}

const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const {
    if (usageCode) {
        auto it = mKeysByUsageCode.find(usageCode);
        if (it != mKeysByUsageCode.end()) {
            return &it->second;
        }
    }
    if (scanCode) {
        auto it = mKeysByScanCode.find(scanCode);
        if (it != mKeysByScanCode.end()) {
            return &it->second;
        }
    }
    return nullptr;
}

std::vector<int32_t> KeyLayoutMap::findScanCodesForKey(int32_t keyCode) const {
    std::vector<int32_t> scanCodes;
    for (const auto& [scanCode, key] : mKeysByScanCode) {
        if (keyCode == key.keyCode) {
            scanCodes.push_back(scanCode);
        }
    }
    return scanCodes;
}

std::optional<AxisInfo> KeyLayoutMap::mapAxis(int32_t scanCode) const {
    auto it = mAxes.find(scanCode);
    if (it == mAxes.end()) {
        ALOGD_IF(DEBUG_MAPPING, "mapAxis: scanCode=%d ~ Failed.", scanCode);
        return std::nullopt;
    }

    const AxisInfo& axisInfo = it->second;
    ALOGD_IF(DEBUG_MAPPING,
             "mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, "
             "splitValue=%d, flatOverride=%d.",
             scanCode, axisInfo.mode, axisInfo.axis, axisInfo.highAxis, axisInfo.splitValue,
             axisInfo.flatOverride);
    return axisInfo;
}

std::optional<int32_t> KeyLayoutMap::findScanCodeForLed(int32_t ledCode) const {
    for (const auto& [scanCode, led] : mLedsByScanCode) {
        if (led.ledCode == ledCode) {
            ALOGD_IF(DEBUG_MAPPING, "%s: ledCode=%d, scanCode=%d.", __func__, ledCode, scanCode);
            return scanCode;
        }
    }
    ALOGD_IF(DEBUG_MAPPING, "%s: ledCode=%d ~ Not found.", __func__, ledCode);
    return std::nullopt;
}

std::optional<int32_t> KeyLayoutMap::findUsageCodeForLed(int32_t ledCode) const {
    for (const auto& [usageCode, led] : mLedsByUsageCode) {
        if (led.ledCode == ledCode) {
            ALOGD_IF(DEBUG_MAPPING, "%s: ledCode=%d, usage=%x.", __func__, ledCode, usageCode);
            return usageCode;
        }
    }
    ALOGD_IF(DEBUG_MAPPING, "%s: ledCode=%d ~ Not found.", __func__, ledCode);
    return std::nullopt;
}

// --- KeyLayoutMap::Parser ---

KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) :
        mMap(map), mTokenizer(tokenizer) {
}

KeyLayoutMap::Parser::~Parser() {
}

status_t KeyLayoutMap::Parser::parse() {
    while (!mTokenizer->isEof()) {
        ALOGD_IF(DEBUG_PARSER, "Parsing %s: '%s'.", mTokenizer->getLocation().string(),
                 mTokenizer->peekRemainderOfLine().string());

        mTokenizer->skipDelimiters(WHITESPACE);

        if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
            String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
            if (keywordToken == "key") {
                mTokenizer->skipDelimiters(WHITESPACE);
                status_t status = parseKey();
                if (status) return status;
            } else if (keywordToken == "axis") {
                mTokenizer->skipDelimiters(WHITESPACE);
                status_t status = parseAxis();
                if (status) return status;
            } else if (keywordToken == "led") {
                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 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());
                return BAD_VALUE;
            }

            mTokenizer->skipDelimiters(WHITESPACE);
            if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
                ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
                        mTokenizer->getLocation().string(),
                        mTokenizer->peekRemainderOfLine().string());
                return BAD_VALUE;
            }
        }

        mTokenizer->nextLine();
    }
    return NO_ERROR;
}

status_t KeyLayoutMap::Parser::parseKey() {
    String8 codeToken = mTokenizer->nextToken(WHITESPACE);
    bool mapUsage = false;
    if (codeToken == "usage") {
        mapUsage = true;
        mTokenizer->skipDelimiters(WHITESPACE);
        codeToken = mTokenizer->nextToken(WHITESPACE);
    }

    std::optional<int> code = parseInt(codeToken.string());
    if (!code) {
        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }
    std::unordered_map<int32_t, Key>& map =
            mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
    if (map.find(*code) != map.end()) {
        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }

    mTokenizer->skipDelimiters(WHITESPACE);
    String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
    if (!keyCode) {
        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
                keyCodeToken.string());
        return BAD_VALUE;
    }

    uint32_t flags = 0;
    for (;;) {
        mTokenizer->skipDelimiters(WHITESPACE);
        if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;

        String8 flagToken = mTokenizer->nextToken(WHITESPACE);
        std::optional<int> flag = InputEventLookup::getKeyFlagByLabel(flagToken.string());
        if (!flag) {
            ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
                    flagToken.string());
            return BAD_VALUE;
        }
        if (flags & *flag) {
            ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
                    flagToken.string());
            return BAD_VALUE;
        }
        flags |= *flag;
    }

    ALOGD_IF(DEBUG_PARSER, "Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
             mapUsage ? "usage" : "scan code", *code, *keyCode, flags);

    Key key;
    key.keyCode = *keyCode;
    key.flags = flags;
    map.insert({*code, key});
    return NO_ERROR;
}

status_t KeyLayoutMap::Parser::parseAxis() {
    String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
    std::optional<int> scanCode = parseInt(scanCodeToken.string());
    if (!scanCode) {
        ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
                scanCodeToken.string());
        return BAD_VALUE;
    }
    if (mMap->mAxes.find(*scanCode) != mMap->mAxes.end()) {
        ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
                scanCodeToken.string());
        return BAD_VALUE;
    }

    AxisInfo axisInfo;

    mTokenizer->skipDelimiters(WHITESPACE);
    String8 token = mTokenizer->nextToken(WHITESPACE);
    if (token == "invert") {
        axisInfo.mode = AxisInfo::MODE_INVERT;

        mTokenizer->skipDelimiters(WHITESPACE);
        String8 axisToken = mTokenizer->nextToken(WHITESPACE);
        std::optional<int> axis = InputEventLookup::getAxisByLabel(axisToken.string());
        if (!axis) {
            ALOGE("%s: Expected inverted axis label, got '%s'.",
                    mTokenizer->getLocation().string(), axisToken.string());
            return BAD_VALUE;
        }
        axisInfo.axis = *axis;
    } else if (token == "split") {
        axisInfo.mode = AxisInfo::MODE_SPLIT;

        mTokenizer->skipDelimiters(WHITESPACE);
        String8 splitToken = mTokenizer->nextToken(WHITESPACE);
        std::optional<int> splitValue = parseInt(splitToken.string());
        if (!splitValue) {
            ALOGE("%s: Expected split value, got '%s'.",
                    mTokenizer->getLocation().string(), splitToken.string());
            return BAD_VALUE;
        }
        axisInfo.splitValue = *splitValue;

        mTokenizer->skipDelimiters(WHITESPACE);
        String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
        std::optional<int> axis = InputEventLookup::getAxisByLabel(lowAxisToken.string());
        if (!axis) {
            ALOGE("%s: Expected low axis label, got '%s'.",
                    mTokenizer->getLocation().string(), lowAxisToken.string());
            return BAD_VALUE;
        }
        axisInfo.axis = *axis;

        mTokenizer->skipDelimiters(WHITESPACE);
        String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
        std::optional<int> highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string());
        if (!highAxis) {
            ALOGE("%s: Expected high axis label, got '%s'.",
                    mTokenizer->getLocation().string(), highAxisToken.string());
            return BAD_VALUE;
        }
        axisInfo.highAxis = *highAxis;
    } else {
        std::optional<int> axis = InputEventLookup::getAxisByLabel(token.string());
        if (!axis) {
            ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
                    mTokenizer->getLocation().string(), token.string());
            return BAD_VALUE;
        }
        axisInfo.axis = *axis;
    }

    for (;;) {
        mTokenizer->skipDelimiters(WHITESPACE);
        if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') {
            break;
        }
        String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
        if (keywordToken == "flat") {
            mTokenizer->skipDelimiters(WHITESPACE);
            String8 flatToken = mTokenizer->nextToken(WHITESPACE);
            std::optional<int> flatOverride = parseInt(flatToken.string());
            if (!flatOverride) {
                ALOGE("%s: Expected flat value, got '%s'.",
                        mTokenizer->getLocation().string(), flatToken.string());
                return BAD_VALUE;
            }
            axisInfo.flatOverride = *flatOverride;
        } else {
            ALOGE("%s: Expected keyword 'flat', got '%s'.",
                    mTokenizer->getLocation().string(), keywordToken.string());
            return BAD_VALUE;
        }
    }

    ALOGD_IF(DEBUG_PARSER,
             "Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
             "splitValue=%d, flatOverride=%d.",
             *scanCode, axisInfo.mode, axisInfo.axis, axisInfo.highAxis, axisInfo.splitValue,
             axisInfo.flatOverride);
    mMap->mAxes.insert({*scanCode, axisInfo});
    return NO_ERROR;
}

status_t KeyLayoutMap::Parser::parseLed() {
    String8 codeToken = mTokenizer->nextToken(WHITESPACE);
    bool mapUsage = false;
    if (codeToken == "usage") {
        mapUsage = true;
        mTokenizer->skipDelimiters(WHITESPACE);
        codeToken = mTokenizer->nextToken(WHITESPACE);
    }
    std::optional<int> code = parseInt(codeToken.string());
    if (!code) {
        ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }

    std::unordered_map<int32_t, Led>& map =
            mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
    if (map.find(*code) != map.end()) {
        ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }

    mTokenizer->skipDelimiters(WHITESPACE);
    String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
    std::optional<int> ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string());
    if (!ledCode) {
        ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
                ledCodeToken.string());
        return BAD_VALUE;
    }

    ALOGD_IF(DEBUG_PARSER, "Parsed led %s: code=%d, ledCode=%d.", mapUsage ? "usage" : "scan code",
             *code, *ledCode);

    Led led;
    led.ledCode = *ledCode;
    map.insert({*code, led});
    return NO_ERROR;
}

static std::optional<InputDeviceSensorType> getSensorType(const char* token) {
    auto it = SENSOR_LIST.find(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);
    std::optional<int> code = parseInt(codeToken.string());
    if (!code) {
        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();

    ALOGD_IF(DEBUG_PARSER, "Parsed sensor: abs code=%d, sensorType=%s, sensorDataIndex=%d.", *code,
             ftl::enum_string(sensorType).c_str(), sensorDataIndex);

    Sensor sensor;
    sensor.sensorType = sensorType;
    sensor.sensorDataIndex = sensorDataIndex;
    map.emplace(*code, sensor);
    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
