15912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown/*
25912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Copyright (C) 2010 The Android Open Source Project
35912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *
45912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
55912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * you may not use this file except in compliance with the License.
65912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * You may obtain a copy of the License at
75912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *
85912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
95912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *
105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Unless required by applicable law or agreed to in writing, software
115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * See the License for the specific language governing permissions and
145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * limitations under the License.
155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown */
165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define LOG_TAG "Keyboard"
185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <stdlib.h>
205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <unistd.h>
215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <limits.h>
225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/Keyboard.h>
24872db4f11e407accccba9d37c335ef7e3597eba4Michael Wright#include <input/InputEventLabels.h>
255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/KeyLayoutMap.h>
265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/KeyCharacterMap.h>
275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/InputDevice.h>
285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Errors.h>
295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Log.h>
305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownnamespace android {
325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyMap ---
345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyMap::KeyMap() {
365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyMap::~KeyMap() {
395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const PropertyMap* deviceConfiguration) {
435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // Use the configured key layout if available.
445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (deviceConfiguration) {
455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        String8 keyLayoutName;
465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                keyLayoutName)) {
485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            if (status == NAME_NOT_FOUND) {
505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                        "it was not found.",
525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                        deviceIdenfifier.name.string(), keyLayoutName.string());
535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            }
545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        }
555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        String8 keyCharacterMapName;
575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                keyCharacterMapName)) {
595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            if (status == NAME_NOT_FOUND) {
615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                ALOGE("Configuration for keyboard device '%s' requested keyboard character "
625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                        "map '%s' but it was not found.",
635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                        deviceIdenfifier.name.string(), keyLayoutName.string());
645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            }
655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        }
665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        if (isComplete()) {
685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            return OK;
695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        }
705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // Try searching by device identifier.
735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (probeKeyMap(deviceIdenfifier, String8::empty())) {
745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return OK;
755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // Fall back on the Generic key map.
785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // TODO Apply some additional heuristics here to figure out what kind of
795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    //      generic key map to use (US English, etc.) for typical external keyboards.
805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return OK;
825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // Try the Virtual key map as a last resort.
855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return OK;
875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    // Give up!
905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            deviceIdenfifier.name.string());
925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return NAME_NOT_FOUND;
935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const String8& keyMapName) {
975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (!haveKeyLayout()) {
985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        loadKeyLayout(deviceIdentifier, keyMapName);
995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (!haveKeyCharacterMap()) {
1015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        loadKeyCharacterMap(deviceIdentifier, keyMapName);
1025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return isComplete();
1045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
1055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
1075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const String8& name) {
1085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    String8 path(getPath(deviceIdentifier, name,
1095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
1105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (path.isEmpty()) {
1115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return NAME_NOT_FOUND;
1125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    status_t status = KeyLayoutMap::load(path, &keyLayoutMap);
1155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (status) {
1165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return status;
1175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    keyLayoutFile.setTo(path);
1205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return OK;
1215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
1225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
1245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const String8& name) {
1255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    String8 path(getPath(deviceIdentifier, name,
1265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
1275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (path.isEmpty()) {
1285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return NAME_NOT_FOUND;
1295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    status_t status = KeyCharacterMap::load(path,
1325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            KeyCharacterMap::FORMAT_BASE, &keyCharacterMap);
1335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (status) {
1345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return status;
1355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    keyCharacterMapFile.setTo(path);
1385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return OK;
1395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
1405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownString8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
1425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const String8& name, InputDeviceConfigurationFileType type) {
1435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return name.isEmpty()
1445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
1455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            : getInputDeviceConfigurationFilePathByName(name, type);
1465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
1475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- Global functions ---
1505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
1525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        const PropertyMap* deviceConfiguration, const KeyMap* keyMap) {
1535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (!keyMap->haveKeyCharacterMap()
1545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            || keyMap->keyCharacterMap->getKeyboardType()
1555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                    == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) {
1565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return false;
1575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (deviceConfiguration) {
1605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        bool builtIn = false;
1615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn)
1625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                && builtIn) {
1635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown            return true;
1645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        }
1655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return strstr(deviceIdentifier.name.string(), "-keypad");
1685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
1695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
1715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    int32_t newMetaState;
1725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (down) {
1735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState = oldMetaState | mask;
1745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    } else {
1755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState = oldMetaState &
1765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown                ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
1775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
179115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov    return normalizeMetaState(newMetaState);
180115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov}
181115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov
182115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhovint32_t normalizeMetaState(int32_t oldMetaState) {
183115f93eeebf7f33b56ed090de70d6e8c733e5d88Dmitry Torokhov    int32_t newMetaState = oldMetaState;
1845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
1855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState |= AMETA_ALT_ON;
1865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
1895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState |= AMETA_SHIFT_ON;
1905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
1935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState |= AMETA_CTRL_ON;
1945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
1965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
1975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        newMetaState |= AMETA_META_ON;
1985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
1995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    return newMetaState;
2005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
2015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
2025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) {
2035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    if (down) {
2045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return oldMetaState;
2055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    } else {
2065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return oldMetaState ^ mask;
2075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
2085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
2095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
2105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownint32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
2115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    int32_t mask;
2125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    switch (keyCode) {
2135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_ALT_LEFT:
2145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
2155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_ALT_RIGHT:
2165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
2175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SHIFT_LEFT:
2185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
2195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SHIFT_RIGHT:
2205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
2215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SYM:
2225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState);
2235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_FUNCTION:
2245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState);
2255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CTRL_LEFT:
2265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState);
2275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CTRL_RIGHT:
2285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState);
2295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_META_LEFT:
2305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState);
2315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_META_RIGHT:
2325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState);
2335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CAPS_LOCK:
2345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState);
2355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_NUM_LOCK:
2365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState);
2375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SCROLL_LOCK:
2385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState);
2395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    default:
2405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return oldMetaState;
2415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
2425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
2435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
2445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownbool isMetaKey(int32_t keyCode) {
2455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    switch (keyCode) {
2465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_ALT_LEFT:
2475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_ALT_RIGHT:
2485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SHIFT_LEFT:
2495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SHIFT_RIGHT:
2505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SYM:
2515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_FUNCTION:
2525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CTRL_LEFT:
2535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CTRL_RIGHT:
2545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_META_LEFT:
2555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_META_RIGHT:
2565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_CAPS_LOCK:
2575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_NUM_LOCK:
2585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    case AKEYCODE_SCROLL_LOCK:
2595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return true;
2605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    default:
2615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown        return false;
2625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown    }
2635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}
2645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
2655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown
2665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} // namespace android
267