Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43fc1939 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari Committed by Android (Google) Code Review
Browse files

Merge "Add API to support key remappings on native side"

parents abd856ff cbba14c5
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -125,14 +125,21 @@ public:
    bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
            Vector<KeyEvent>& outEvents) const;

    /* Maps an Android key code to another Android key code. This mapping is applied after scanCode
     * and usageCodes are mapped to corresponding Android Keycode */
    void addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode);

    /* Maps a scan code and usage code to a key code, in case this key map overrides
     * the mapping in some way. */
    status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const;

    /* Tries to find a replacement key code for a given key code and meta state
     * in character map. */
    void tryRemapKey(int32_t scanCode, int32_t metaState,
            int32_t* outKeyCode, int32_t* outMetaState) const;
    /* Returns keycode after applying Android key code remapping defined in mKeyRemapping */
    int32_t applyKeyRemapping(int32_t fromKeyCode) const;

    /* Returns the <keyCode, metaState> pair after applying key behavior defined in the kcm file,
     * that tries to find a replacement key code based on current meta state */
    std::pair<int32_t /*keyCode*/, int32_t /*metaState*/> applyKeyBehavior(int32_t keyCode,
                                                                           int32_t metaState) const;

#ifdef __linux__
    /* Reads a key map from a parcel. */
@@ -227,8 +234,9 @@ private:
    std::string mLoadFileName;
    bool mLayoutOverlayApplied;

    KeyedVector<int32_t, int32_t> mKeysByScanCode;
    KeyedVector<int32_t, int32_t> mKeysByUsageCode;
    std::map<int32_t /* fromAndroidKeyCode */, int32_t /* toAndroidKeyCode */> mKeyRemapping;
    std::map<int32_t /* fromScanCode */, int32_t /* toAndroidKeyCode */> mKeysByScanCode;
    std::map<int32_t /* fromHidUsageCode */, int32_t /* toAndroidKeyCode */> mKeysByUsageCode;

    KeyCharacterMap(const std::string& filename);

+91 −59
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@
// Enables debug output for mapping.
#define DEBUG_MAPPING 0


namespace android {

static const char* WHITESPACE = " \t\r";
@@ -93,6 +92,7 @@ KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other)
      : mType(other.mType),
        mLoadFileName(other.mLoadFileName),
        mLayoutOverlayApplied(other.mLayoutOverlayApplied),
        mKeyRemapping(other.mKeyRemapping),
        mKeysByScanCode(other.mKeysByScanCode),
        mKeysByUsageCode(other.mKeysByUsageCode) {
    for (size_t i = 0; i < other.mKeys.size(); i++) {
@@ -114,7 +114,7 @@ bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const {
    if (mLayoutOverlayApplied != other.mLayoutOverlayApplied) {
        return false;
    }
    if (mKeys.size() != other.mKeys.size() ||
    if (mKeys.size() != other.mKeys.size() || mKeyRemapping.size() != other.mKeyRemapping.size() ||
        mKeysByScanCode.size() != other.mKeysByScanCode.size() ||
        mKeysByUsageCode.size() != other.mKeysByUsageCode.size()) {
        return false;
@@ -131,23 +131,10 @@ bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const {
        }
    }

    for (size_t i = 0; i < mKeysByScanCode.size(); i++) {
        if (mKeysByScanCode.keyAt(i) != other.mKeysByScanCode.keyAt(i)) {
            return false;
        }
        if (mKeysByScanCode.valueAt(i) != other.mKeysByScanCode.valueAt(i)) {
            return false;
        }
    }

    for (size_t i = 0; i < mKeysByUsageCode.size(); i++) {
        if (mKeysByUsageCode.keyAt(i) != other.mKeysByUsageCode.keyAt(i)) {
    if (mKeyRemapping != other.mKeyRemapping || mKeysByScanCode != other.mKeysByScanCode ||
        mKeysByUsageCode != other.mKeysByUsageCode) {
        return false;
    }
        if (mKeysByUsageCode.valueAt(i) != other.mKeysByUsageCode.valueAt(i)) {
            return false;
        }
    }

    return true;
}
@@ -258,14 +245,12 @@ void KeyCharacterMap::combine(const KeyCharacterMap& overlay) {
        }
    }

    for (size_t i = 0; i < overlay.mKeysByScanCode.size(); i++) {
        mKeysByScanCode.replaceValueFor(overlay.mKeysByScanCode.keyAt(i),
                                        overlay.mKeysByScanCode.valueAt(i));
    for (auto const& it : overlay.mKeysByScanCode) {
        mKeysByScanCode.insert_or_assign(it.first, it.second);
    }

    for (size_t i = 0; i < overlay.mKeysByUsageCode.size(); i++) {
        mKeysByUsageCode.replaceValueFor(overlay.mKeysByUsageCode.keyAt(i),
                                         overlay.mKeysByUsageCode.valueAt(i));
    for (auto const& it : overlay.mKeysByUsageCode) {
        mKeysByUsageCode.insert_or_assign(it.first, it.second);
    }
    mLayoutOverlayApplied = true;
}
@@ -400,11 +385,26 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t
    return true;
}

void KeyCharacterMap::addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) {
    if (fromKeyCode == toKeyCode) {
        mKeyRemapping.erase(fromKeyCode);
#if DEBUG_MAPPING
        ALOGD("addKeyRemapping: Cleared remapping forKeyCode=%d ~ Result Successful.", fromKeyCode);
#endif
        return;
    }
    mKeyRemapping.insert_or_assign(fromKeyCode, toKeyCode);
#if DEBUG_MAPPING
    ALOGD("addKeyRemapping: fromKeyCode=%d, toKeyCode=%d ~ Result Successful.", fromKeyCode,
          toKeyCode);
#endif
}

status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
    if (usageCode) {
        ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
        if (index >= 0) {
            *outKeyCode = mKeysByUsageCode.valueAt(index);
        const auto it = mKeysByUsageCode.find(usageCode);
        if (it != mKeysByUsageCode.end()) {
            *outKeyCode = it->second;
#if DEBUG_MAPPING
            ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
                    scanCode, usageCode, *outKeyCode);
@@ -413,9 +413,9 @@ status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* o
        }
    }
    if (scanCode) {
        ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
        if (index >= 0) {
            *outKeyCode = mKeysByScanCode.valueAt(index);
        const auto it = mKeysByScanCode.find(scanCode);
        if (it != mKeysByScanCode.end()) {
            *outKeyCode = it->second;
#if DEBUG_MAPPING
            ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
                    scanCode, usageCode, *outKeyCode);
@@ -431,45 +431,59 @@ status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* o
    return NAME_NOT_FOUND;
}

void KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState,
                                  int32_t *outKeyCode, int32_t *outMetaState) const {
    *outKeyCode = keyCode;
    *outMetaState = metaState;
int32_t KeyCharacterMap::applyKeyRemapping(int32_t fromKeyCode) const {
    int32_t toKeyCode = fromKeyCode;

    const Behavior* behavior = getKeyBehavior(keyCode, metaState);
    const auto it = mKeyRemapping.find(fromKeyCode);
    if (it != mKeyRemapping.end()) {
        toKeyCode = it->second;
    }
#if DEBUG_MAPPING
    ALOGD("applyKeyRemapping: keyCode=%d ~ replacement keyCode=%d.", fromKeyCode, toKeyCode);
#endif
    return toKeyCode;
}

std::pair<int32_t, int32_t> KeyCharacterMap::applyKeyBehavior(int32_t fromKeyCode,
                                                              int32_t fromMetaState) const {
    int32_t toKeyCode = fromKeyCode;
    int32_t toMetaState = fromMetaState;

    const Behavior* behavior = getKeyBehavior(fromKeyCode, fromMetaState);
    if (behavior != nullptr) {
        if (behavior->replacementKeyCode) {
            *outKeyCode = behavior->replacementKeyCode;
            int32_t newMetaState = metaState & ~behavior->metaState;
            toKeyCode = behavior->replacementKeyCode;
            toMetaState = fromMetaState & ~behavior->metaState;
            // Reset dependent meta states.
            if (behavior->metaState & AMETA_ALT_ON) {
                newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
                toMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
            }
            if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
                newMetaState &= ~AMETA_ALT_ON;
                toMetaState &= ~AMETA_ALT_ON;
            }
            if (behavior->metaState & AMETA_CTRL_ON) {
                newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
                toMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
            }
            if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
                newMetaState &= ~AMETA_CTRL_ON;
                toMetaState &= ~AMETA_CTRL_ON;
            }
            if (behavior->metaState & AMETA_SHIFT_ON) {
                newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
                toMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
            }
            if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
                newMetaState &= ~AMETA_SHIFT_ON;
                toMetaState &= ~AMETA_SHIFT_ON;
            }
            // ... and put universal bits back if needed
            *outMetaState = normalizeMetaState(newMetaState);
            toMetaState = normalizeMetaState(toMetaState);
        }
    }

#if DEBUG_MAPPING
    ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ "
    ALOGD("applyKeyBehavior: keyCode=%d, metaState=0x%08x ~ "
          "replacement keyCode=%d, replacement metaState=0x%08x.",
            keyCode, metaState, *outKeyCode, *outMetaState);
          fromKeyCode, fromMetaState, toKeyCode, toMetaState);
#endif
    return std::make_pair(toKeyCode, toMetaState);
}

bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
@@ -720,6 +734,18 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel)
            return nullptr;
        }
    }
    size_t numKeyRemapping = parcel->readInt32();
    if (parcel->errorCheck()) {
        return nullptr;
    }
    for (size_t i = 0; i < numKeyRemapping; i++) {
        int32_t key = parcel->readInt32();
        int32_t value = parcel->readInt32();
        map->mKeyRemapping.insert_or_assign(key, value);
        if (parcel->errorCheck()) {
            return nullptr;
        }
    }
    size_t numKeysByScanCode = parcel->readInt32();
    if (parcel->errorCheck()) {
        return nullptr;
@@ -727,7 +753,7 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel)
    for (size_t i = 0; i < numKeysByScanCode; i++) {
        int32_t key = parcel->readInt32();
        int32_t value = parcel->readInt32();
        map->mKeysByScanCode.add(key, value);
        map->mKeysByScanCode.insert_or_assign(key, value);
        if (parcel->errorCheck()) {
            return nullptr;
        }
@@ -739,7 +765,7 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel)
    for (size_t i = 0; i < numKeysByUsageCode; i++) {
        int32_t key = parcel->readInt32();
        int32_t value = parcel->readInt32();
        map->mKeysByUsageCode.add(key, value);
        map->mKeysByUsageCode.insert_or_assign(key, value);
        if (parcel->errorCheck()) {
            return nullptr;
        }
@@ -773,17 +799,23 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const {
        }
        parcel->writeInt32(0);
    }
    size_t numKeyRemapping = mKeyRemapping.size();
    parcel->writeInt32(numKeyRemapping);
    for (auto const& [fromAndroidKeyCode, toAndroidKeyCode] : mKeyRemapping) {
        parcel->writeInt32(fromAndroidKeyCode);
        parcel->writeInt32(toAndroidKeyCode);
    }
    size_t numKeysByScanCode = mKeysByScanCode.size();
    parcel->writeInt32(numKeysByScanCode);
    for (size_t i = 0; i < numKeysByScanCode; i++) {
        parcel->writeInt32(mKeysByScanCode.keyAt(i));
        parcel->writeInt32(mKeysByScanCode.valueAt(i));
    for (auto const& [fromScanCode, toAndroidKeyCode] : mKeysByScanCode) {
        parcel->writeInt32(fromScanCode);
        parcel->writeInt32(toAndroidKeyCode);
    }
    size_t numKeysByUsageCode = mKeysByUsageCode.size();
    parcel->writeInt32(numKeysByUsageCode);
    for (size_t i = 0; i < numKeysByUsageCode; i++) {
        parcel->writeInt32(mKeysByUsageCode.keyAt(i));
        parcel->writeInt32(mKeysByUsageCode.valueAt(i));
    for (auto const& [fromUsageCode, toAndroidKeyCode] : mKeysByUsageCode) {
        parcel->writeInt32(fromUsageCode);
        parcel->writeInt32(toAndroidKeyCode);
    }
}
#endif // __linux__
@@ -950,9 +982,9 @@ status_t KeyCharacterMap::Parser::parseMapKey() {
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }
    KeyedVector<int32_t, int32_t>& map =
            mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
    if (map.indexOfKey(code) >= 0) {
    std::map<int32_t, int32_t>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
    const auto it = map.find(code);
    if (it != map.end()) {
        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
@@ -971,7 +1003,7 @@ status_t KeyCharacterMap::Parser::parseMapKey() {
    ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
            mapUsage ? "usage" : "scan code", code, keyCode);
#endif
    map.add(code, keyCode);
    map.insert_or_assign(code, keyCode);
    return NO_ERROR;
}

+3 −0
Original line number Diff line number Diff line
@@ -88,6 +88,9 @@ public:
    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
            int32_t sw) = 0;

    virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode,
                                 int32_t toKeyCode) const = 0;

    virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0;

    /* Toggle Caps Lock */
+26 −4
Original line number Diff line number Diff line
@@ -952,15 +952,19 @@ int32_t EventHub::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKey
            device->getKeyCharacterMap()->mapKey(scanCodes[0], 0 /*usageCode*/, &outKeyCode);
    switch (mapKeyRes) {
        case OK:
            return outKeyCode;
            break;
        case NAME_NOT_FOUND:
            // key character map doesn't re-map this scanCode, hence the keyCode remains the same
            return locationKeyCode;
            outKeyCode = locationKeyCode;
            break;
        default:
            ALOGW("Failed to get key code for key location: Key character map returned error %s",
                  statusToString(mapKeyRes).c_str());
            return AKEYCODE_UNKNOWN;
            outKeyCode = AKEYCODE_UNKNOWN;
            break;
    }
    // Remap if there is a Key remapping added to the KCM and return the remapped key
    return device->getKeyCharacterMap()->applyKeyRemapping(outKeyCode);
}

int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
@@ -1023,6 +1027,18 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t
    return false;
}

void EventHub::addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const {
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        return;
    }
    const std::shared_ptr<KeyCharacterMap> kcm = device->getKeyCharacterMap();
    if (kcm) {
        kcm->addKeyRemapping(fromKeyCode, toKeyCode);
    }
}

status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
                          int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
    std::scoped_lock _l(mLock);
@@ -1048,7 +1064,13 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,

        if (status == NO_ERROR) {
            if (kcm) {
                kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState);
                // Remap keys based on user-defined key remappings and key behavior defined in the
                // corresponding kcm file
                *outKeycode = kcm->applyKeyRemapping(*outKeycode);

                // Remap keys based on Key behavior defined in KCM file
                std::tie(*outKeycode, *outMetaState) =
                        kcm->applyKeyBehavior(*outKeycode, metaState);
            } else {
                *outMetaState = metaState;
            }
+6 −0
Original line number Diff line number Diff line
@@ -631,6 +631,12 @@ void InputDevice::updateMetaState(int32_t keyCode) {
    });
}

void InputDevice::addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) {
    for_each_subdevice([fromKeyCode, toKeyCode](auto& context) {
        context.addKeyRemapping(fromKeyCode, toKeyCode);
    });
}

void InputDevice::bumpGeneration() {
    mGeneration = mContext->bumpGeneration();
}
Loading