IMS添加实体按键流程 - Android14

IMS添加实体按键流程 - Android14

  • 1、实体按键信息(Mi 9 左侧实体按键)
  • 2、硬件添加
    • 2.1 内核添加设备节点
    • 2.2 Generic.kl映射文件
    • 2.3 映射文件文件加载loadKeyMapLocked
    • 2.4 addDeviceLocked 添加设备相关对象
  • 3、keycode对应scankode
  • 4、KeyEvent.java 添加对应keycode

InputReader线程获取输入事件-Android12


1、实体按键信息(Mi 9 左侧实体按键)

  1. getevent 获取按键节点/dev/input/event3,scancode对应0x02b1 (即底层硬件上报的对应scancode)
  2. dumpsys input 获取对应按键映射文件KeyLayoutFile: /system/usr/keylayout/gpio-keys.klKeyCharacterMapFile: /system/usr/keychars/Generic.kcm,对应Sources: 0x00000101
    在这里插入图片描述

一般默认在 frameworks/base/data/keyboards/Generic.kl
mk配置文件:frameworks/base/data/keyboards/common.mkframeworks/base/data/keyboards/Android.mk

getevent

cepheus:/ $ getevent
add device 1: /dev/input/event7name:     "sm8150-tavil-snd-card USB_3_5 Jack"
add device 2: /dev/input/event6name:     "sm8150-tavil-snd-card Button Jack"
add device 3: /dev/input/event5name:     "sm8150-tavil-snd-card Headset Jack"
add device 4: /dev/input/event3name:     "gpio-keys"
add device 5: /dev/input/event2name:     "uinput-goodix"
add device 6: /dev/input/event0name:     "qpnp_pon"
add device 7: /dev/input/event1name:     "qti-haptics"
add device 8: /dev/input/event4name:     "fts"/dev/input/event3: 0001 02b1 00000001
/dev/input/event3: 0000 0000 00000000
/dev/input/event3: 0001 02b1 00000000
/dev/input/event3: 0000 0000 00000000/dev/input/event3: 0001 0073 00000001
/dev/input/event3: 0000 0000 00000000
/dev/input/event3: 0001 0073 00000000
/dev/input/event3: 0000 0000 00000000
/dev/input/event0: 0001 0072 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0072 00000000
/dev/input/event0: 0000 0000 00000000/dev/input/event0: 0001 0074 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0074 00000000
/dev/input/event0: 0000 0000 00000000

adb shell dumpsys input > dumpsys_input.txt

    4: gpio-keysClasses: KEYBOARDPath: /dev/input/event3Enabled: trueDescriptor: 485d69228e24f5e46da1598745890b214130dbc4Location: gpio-keys/input0ControllerNumber: 0UniqueId: Identifier: bus=0x0019, vendor=0x0001, product=0x0001, version=0x0100KeyLayoutFile: /system/usr/keylayout/gpio-keys.klKeyCharacterMapFile: /system/usr/keychars/Generic.kcmConfigurationFile: VideoDevice: <none>Device 5: gpio-keysEventHub Devices: [ 4 ] Generation: 15IsExternal: falseAssociatedDisplayPort: <none>AssociatedDisplayUniqueId: <none>HasMic:     falseSources: 0x00000101KeyboardType: 1ControllerNum: 0Keyboard Input Mapper:Parameters:OrientationAware: falseHandlesKeyRepeat: falseKeyboardType: 1Orientation: 0KeyDowns: 0 keys currently downMetaState: 0x0DownTime: 0

2、硬件添加

2.1 内核添加设备节点

在Linux内核中提供了按键的驱动程序drivers/input/keyboard/gpio_keys.c解析,一般都是dts配置文件,scancode查看linux,code

  • POWER 按键:0074 /dev/input/event0: 0001 0074 00000001
  • 音量上下键:0073、0072 /dev/input/event3: 0001 0073 00000001 /dev/input/event0: 0001 0072 00000001
  • MI 9 左侧按键:02b1 /dev/input/event3: 0001 02b1 00000001
gpio-keys {compatible = "gpio-keys";input-name = "gpio-keys";pinctrl-names = "default";pinctrl-0 = <&gpio_keys_pin_a>;camera-snapshot {label = "camera_snapshot";gpios = <&pm8941_gpios 1 GPIO_ACTIVE_LOW>;linux,code = <KEY_CAMERA>;wakeup-source;debounce-interval = <15>;};volume-down {label = "volume_down";gpios = <&pm8941_gpios 2 GPIO_ACTIVE_LOW>;linux,code = <KEY_VOLUMEDOWN>;wakeup-source;debounce-interval = <15>;};volume-up {label = "volume_up";gpios = <&pm8941_gpios 5 GPIO_ACTIVE_LOW>;linux,code = <KEY_VOLUMEUP>;wakeup-source;debounce-interval = <15>;};
};

2.2 Generic.kl映射文件

系统提供了一个特殊的内置常规按键布局文件,名为 Generic.kl。此按键布局旨在支持各种标准外部键盘和操纵杆。请勿修改常规按键布局!

按键布局文件
按键字符映射文件
输入设备配置文件

2.3 映射文件文件加载loadKeyMapLocked

  • device->loadConfigurationLocked():这里导入kl配置文件,首先"Vendor_%04x_Product_%04x_Version_%04x%s",再次"Vendor_%04x_Product_%04x%s"。查看dumpsys input信息查看ConfigurationFile:一般为空。

  • loadKeyMapLocked 这里导入默认kl配置文件。这里左侧按键对应KeyLayoutFile: /system/usr/keylayout/gpio-keys.kl、power按键KeyLayoutFile: /system/usr/keylayout/Generic.kl
    在这里插入图片描述

frameworks/native/services/inputflinger/reader/EventHub.cpp

status_t EventHub::Device::loadKeyMapLocked() {return keyMap.load(identifier, configuration.get());
}void EventHub::openDeviceLocked(const std::string& devicePath) {// If an input device happens to register around the time when EventHub's constructor runs, it// is possible that the same input event node (for example, /dev/input/event3) will be noticed// in both 'inotify' callback and also in the 'scanDirLocked' pass. To prevent duplicate devices// from getting registered, ensure that this path is not already covered by an existing device.for (const auto& [deviceId, device] : mDevices) {if (device->path == devicePath) {return; // device was already registered}}char buffer[80];ALOGV("Opening device: %s", devicePath.c_str());int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);if (fd < 0) {ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));return;}InputDeviceIdentifier identifier;// Get device name.if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));} else {buffer[sizeof(buffer) - 1] = '\0';identifier.name = buffer;}// Check to see if the device is on our excluded listfor (size_t i = 0; i < mExcludedDevices.size(); i++) {const std::string& item = mExcludedDevices[i];if (identifier.name == item) {ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());close(fd);return;}}// Get device driver version.int driverVersion;if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));close(fd);return;}// Get device identifier.struct input_id inputId;if (ioctl(fd, EVIOCGID, &inputId)) {ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));close(fd);return;}identifier.bus = inputId.bustype;identifier.product = inputId.product;identifier.vendor = inputId.vendor;identifier.version = inputId.version;// Get device physical location.if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {// fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));} else {buffer[sizeof(buffer) - 1] = '\0';identifier.location = buffer;}// Get device unique id.if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {// fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));} else {buffer[sizeof(buffer) - 1] = '\0';identifier.uniqueId = buffer;}// Attempt to get the bluetooth address of an input device from the uniqueId.if (identifier.bus == BUS_BLUETOOTH &&std::regex_match(identifier.uniqueId,std::regex("^[A-Fa-f0-9]{2}(?::[A-Fa-f0-9]{2}){5}$"))) {identifier.bluetoothAddress = identifier.uniqueId;// The Bluetooth stack requires alphabetic characters to be uppercase in a valid address.for (auto& c : *identifier.bluetoothAddress) {c = ::toupper(c);}}// Fill in the descriptor.assignDescriptorLocked(identifier);// Allocate device.  (The device object takes ownership of the fd at this point.)int32_t deviceId = mNextDeviceId++;std::unique_ptr<Device> device =std::make_unique<Device>(fd, deviceId, devicePath, identifier,obtainAssociatedDeviceLocked(devicePath));ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());ALOGV("  bus:        %04x\n""  vendor      %04x\n""  product     %04x\n""  version     %04x\n",identifier.bus, identifier.vendor, identifier.product, identifier.version);ALOGV("  name:       \"%s\"\n", identifier.name.c_str());ALOGV("  location:   \"%s\"\n", identifier.location.c_str());ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.c_str());ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.c_str());ALOGV("  driver:     v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,driverVersion & 0xff);// Load the configuration file for the device.device->loadConfigurationLocked();// Figure out the kinds of events the device reports.device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask);device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask);// See if this is a device with keys. This could be full keyboard, or other devices like// gamepads, joysticks, and styluses with buttons that should generate key presses.bool haveKeyboardKeys =device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1);bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);bool haveStylusButtons = device->keyBitmask.test(BTN_STYLUS) ||device->keyBitmask.test(BTN_STYLUS2) || device->keyBitmask.test(BTN_STYLUS3);if (haveKeyboardKeys || haveGamepadButtons || haveStylusButtons) {device->classes |= InputDeviceClass::KEYBOARD;}// See if this is a cursor device such as a trackball or mouse.if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&device->relBitmask.test(REL_Y)) {device->classes |= InputDeviceClass::CURSOR;}// See if the device is specially configured to be of a certain type.if (device->configuration) {std::string deviceType = device->configuration->getString("device.type").value_or("");if (deviceType == "rotaryEncoder") {device->classes |= InputDeviceClass::ROTARY_ENCODER;} else if (deviceType == "externalStylus") {device->classes |= InputDeviceClass::EXTERNAL_STYLUS;}}// See if this is a touch pad.// Is this a new modern multi-touch driver?if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {// Some joysticks such as the PS3 controller report axes that conflict// with the ABS_MT range.  Try to confirm that the device really is// a touch screen.if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);if (device->propBitmask.test(INPUT_PROP_POINTER) &&!device->keyBitmask.any(BTN_TOOL_PEN, BTN_TOOL_FINGER) && !haveStylusButtons) {device->classes |= InputDeviceClass::TOUCHPAD;}}// Is this an old style single-touch driver?} else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&device->absBitmask.test(ABS_Y)) {device->classes |= InputDeviceClass::TOUCH;// Is this a stylus that reports contact/pressure independently of touch coordinates?} else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&!device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {device->classes |= InputDeviceClass::EXTERNAL_STYLUS;}// See if this device is a joystick.// Assumes that joysticks always have gamepad buttons in order to distinguish them// from other devices such as accelerometers that also have absolute axes.if (haveGamepadButtons) {auto assumedClasses = device->classes | InputDeviceClass::JOYSTICK;for (int i = 0; i <= ABS_MAX; i++) {if (device->absBitmask.test(i) &&(getAbsAxisUsage(i, assumedClasses).test(InputDeviceClass::JOYSTICK))) {device->classes = assumedClasses;break;}}}// Check whether this device is an accelerometer.if (device->propBitmask.test(INPUT_PROP_ACCELEROMETER)) {device->classes |= InputDeviceClass::SENSOR;}// Check whether this device has switches.for (int i = 0; i <= SW_MAX; i++) {if (device->swBitmask.test(i)) {device->classes |= InputDeviceClass::SWITCH;break;}}// Check whether this device supports the vibrator.if (device->ffBitmask.test(FF_RUMBLE)) {device->classes |= InputDeviceClass::VIBRATOR;}// Configure virtual keys.if ((device->classes.test(InputDeviceClass::TOUCH))) {// Load the virtual keys for the touch screen, if any.// We do this now so that we can make sure to load the keymap if necessary.bool success = device->loadVirtualKeyMapLocked();if (success) {device->classes |= InputDeviceClass::KEYBOARD;}}// Load the key map.// We need to do this for joysticks too because the key layout may specify axes, and for// sensor as well because the key layout may specify the axes to sensor data mapping.status_t keyMapStatus = NAME_NOT_FOUND;if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK |InputDeviceClass::SENSOR)) {// Load the keymap for the device.keyMapStatus = device->loadKeyMapLocked();}// Configure the keyboard, gamepad or virtual keyboard.if (device->classes.test(InputDeviceClass::KEYBOARD)) {// Register the keyboard as a built-in keyboard if it is eligible.if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&isEligibleBuiltInKeyboard(device->identifier, device->configuration.get(),&device->keyMap)) {mBuiltInKeyboardId = device->id;}// 'Q' key support = cheap test of whether this is an alpha-capable kbdif (device->hasKeycodeLocked(AKEYCODE_Q)) {device->classes |= InputDeviceClass::ALPHAKEY;}// See if this device has a DPAD.if (device->hasKeycodeLocked(AKEYCODE_DPAD_UP) &&device->hasKeycodeLocked(AKEYCODE_DPAD_DOWN) &&device->hasKeycodeLocked(AKEYCODE_DPAD_LEFT) &&device->hasKeycodeLocked(AKEYCODE_DPAD_RIGHT) &&device->hasKeycodeLocked(AKEYCODE_DPAD_CENTER)) {device->classes |= InputDeviceClass::DPAD;}// See if this device has a gamepad.for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) {device->classes |= InputDeviceClass::GAMEPAD;break;}}// See if this device has any stylus buttons that we would want to fuse with touch data.if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT)) {for (int32_t keycode : STYLUS_BUTTON_KEYCODES) {if (device->hasKeycodeLocked(keycode)) {device->classes |= InputDeviceClass::EXTERNAL_STYLUS;break;}}}}// If the device isn't recognized as something we handle, don't monitor it.if (device->classes == ftl::Flags<InputDeviceClass>(0)) {ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),device->identifier.name.c_str());return;}// Classify InputDeviceClass::BATTERY.if (device->associatedDevice && !device->associatedDevice->batteryInfos.empty()) {device->classes |= InputDeviceClass::BATTERY;}// Classify InputDeviceClass::LIGHT.if (device->associatedDevice && !device->associatedDevice->lightInfos.empty()) {device->classes |= InputDeviceClass::LIGHT;}// Determine whether the device has a mic.if (device->deviceHasMicLocked()) {device->classes |= InputDeviceClass::MIC;}// Determine whether the device is external or internal.if (device->isExternalDeviceLocked()) {device->classes |= InputDeviceClass::EXTERNAL;}if (device->classes.any(InputDeviceClass::JOYSTICK | InputDeviceClass::DPAD) &&device->classes.test(InputDeviceClass::GAMEPAD)) {device->controllerNumber = getNextControllerNumberLocked(device->identifier.name);device->setLedForControllerLocked();}if (registerDeviceForEpollLocked(*device) != OK) {return;}device->configureFd();ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, ""configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),device->classes.string().c_str(), device->configurationFile.c_str(),device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),toString(mBuiltInKeyboardId == deviceId));addDeviceLocked(std::move(device));
}

frameworks/native/libs/input/Keyboard.cpp

static std::string getPath(const InputDeviceIdentifier& deviceIdentifier, const std::string& name,InputDeviceConfigurationFileType type) {return name.empty()? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type): getInputDeviceConfigurationFilePathByName(name, type);
}status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,const PropertyMap* deviceConfiguration) {// Use the configured key layout if available.if (deviceConfiguration) {std::optional<std::string> keyLayoutName =deviceConfiguration->getString("keyboard.layout");if (keyLayoutName.has_value()) {status_t status = loadKeyLayout(deviceIdentifier, *keyLayoutName);if (status == NAME_NOT_FOUND) {ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but ""it was not found.",deviceIdentifier.name.c_str(), keyLayoutName->c_str());}}std::optional<std::string> keyCharacterMapName =deviceConfiguration->getString("keyboard.characterMap");if (keyCharacterMapName.has_value()) {status_t status = loadKeyCharacterMap(deviceIdentifier, *keyCharacterMapName);if (status == NAME_NOT_FOUND) {ALOGE("Configuration for keyboard device '%s' requested keyboard character ""map '%s' but it was not found.",deviceIdentifier.name.c_str(), keyCharacterMapName->c_str());}}if (isComplete()) {return OK;}}// Try searching by device identifier.if (probeKeyMap(deviceIdentifier, "")) {return OK;}// Fall back on the Generic key map.// TODO Apply some additional heuristics here to figure out what kind of//      generic key map to use (US English, etc.) for typical external keyboards.if (probeKeyMap(deviceIdentifier, "Generic")) {return OK;}// Try the Virtual key map as a last resort.if (probeKeyMap(deviceIdentifier, "Virtual")) {return OK;}// Give up!ALOGE("Could not determine key map for device '%s' and no default key maps were found!",deviceIdentifier.name.c_str());return NAME_NOT_FOUND;
}bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,const std::string& keyMapName) {if (!haveKeyLayout()) {loadKeyLayout(deviceIdentifier, keyMapName);}if (!haveKeyCharacterMap()) {loadKeyCharacterMap(deviceIdentifier, keyMapName);}return isComplete();
}status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,const std::string& name) {std::string path(getPath(deviceIdentifier, name, InputDeviceConfigurationFileType::KEY_LAYOUT));if (path.empty()) {return NAME_NOT_FOUND;}base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(path);if (ret.ok()) {keyLayoutMap = *ret;keyLayoutFile = path;return OK;}// Try to load fallback layout if the regular layout could not be loaded due to missing// kernel modulesstd::string fallbackPath(getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier,InputDeviceConfigurationFileType::KEY_LAYOUT,"_fallback"));ret = KeyLayoutMap::load(fallbackPath);if (!ret.ok()) {return ret.error().code();}keyLayoutMap = *ret;keyLayoutFile = fallbackPath;return OK;
}

frameworks/native/libs/input/InputDevice.cpp

std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(const InputDeviceIdentifier& deviceIdentifier, InputDeviceConfigurationFileType type,const char* suffix) {if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {if (deviceIdentifier.version != 0) {// Try vendor product version.std::string versionPath =getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%""04x_Version_%04x%s",deviceIdentifier.vendor,deviceIdentifier.product,deviceIdentifier.version,suffix),type);if (!versionPath.empty()) {return versionPath;}}// Try vendor product.std::string productPath =getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%04x%s",deviceIdentifier.vendor,deviceIdentifier.product,suffix),type);if (!productPath.empty()) {return productPath;}}// Try device name.return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName() + suffix,type);
}std::string getInputDeviceConfigurationFilePathByName(const std::string& name, InputDeviceConfigurationFileType type) {// Search system repository.std::string path;// Treblized input device config files will be located /product/usr, /system_ext/usr,// /odm/usr or /vendor/usr.// These files may also be in the com.android.input.config APEX.const char* rootsForPartition[]{"/product","/system_ext","/odm","/vendor","/apex/com.android.input.config/etc",getenv("ANDROID_ROOT"),};for (size_t i = 0; i < size(rootsForPartition); i++) {if (rootsForPartition[i] == nullptr) {continue;}path = rootsForPartition[i];path += "/usr/";appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBEALOGD("Probing for system provided input device configuration file: path='%s'",path.c_str());
#endifif (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBEALOGD("Found");
#endifreturn path;}}// Search user repository.// TODO Should only look here if not in safe mode.path = "";char *androidData = getenv("ANDROID_DATA");if (androidData != nullptr) {path += androidData;}path += "/system/devices/";appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBEALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
#endifif (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBEALOGD("Found");
#endifreturn path;}// Not found.
#if DEBUG_PROBEALOGD("Probe failed to find input device configuration file: name='%s', type=%d",name.c_str(), type);
#endifreturn "";
}

2.4 addDeviceLocked 添加设备相关对象

addDeviceLocked 添加设备、IMS:EventHub 设备添加和InputDevice转化 其中EventHub::scanDevicesLocked()查询DEVICE_INPUT_PATH = "/dev/input"路径添加/dev/input/event3

  • InputDeviceIdentifier
  • Device
  • InputDevice
  • InputMapper: frameworks/native/services/inputflinger/reader/mapperClasses: KEYBOARD / Sources: 0x00000101 这里对应KeyboardInputMapper.cppAINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON
  • InputDeviceInfo

frameworks/native/services/inputflinger/reader/InputReader.cpp

void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {if (mDevices.find(eventHubId) != mDevices.end()) {ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);return;}InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);notifyAll(device->configure(when, mConfig, /*changes=*/{}));notifyAll(device->reset(when));if (device->isIgnored()) {ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' ""(ignored non-input device)",device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());} else {ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=%s",device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),inputEventSourceToString(device->getSources()).c_str());}mDevices.emplace(eventHubId, device);// Add device to device to EventHub ids map.const auto mapIt = mDeviceToEventHubIdsMap.find(device);if (mapIt == mDeviceToEventHubIdsMap.end()) {std::vector<int32_t> ids = {eventHubId};mDeviceToEventHubIdsMap.emplace(device, ids);} else {mapIt->second.push_back(eventHubId);}bumpGenerationLocked();if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {notifyExternalStylusPresenceChangedLocked();}// Sensor input device is noisy, to save power disable it by default.// Input device is classified as SENSOR when any sub device is a SENSOR device, check Eventhub// device class to disable SENSOR sub device only.if (mEventHub->getDeviceClasses(eventHubId).test(InputDeviceClass::SENSOR)) {mEventHub->disableDevice(eventHubId);}
}std::shared_ptr<InputDevice> InputReader::createDeviceLocked(int32_t eventHubId, const InputDeviceIdentifier& identifier) {auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {const InputDeviceIdentifier identifier2 =devicePair.second->getDeviceInfo().getIdentifier();return isSubDevice(identifier, identifier2);});std::shared_ptr<InputDevice> device;if (deviceIt != mDevices.end()) {device = deviceIt->second;} else {int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),identifier);}device->addEventHubDevice(eventHubId, mConfig);return device;
}

frameworks/native/services/inputflinger/reader/InputDevice.cpp

InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,const InputDeviceIdentifier& identifier): mContext(context),mId(id),mGeneration(generation),mControllerNumber(0),mIdentifier(identifier),mClasses(0),mSources(0),mIsExternal(false),mHasMic(false),mDropUntilNextSync(false) {}void InputDevice::addEventHubDevice(int32_t eventHubId,const InputReaderConfiguration& readerConfig) {if (mDevices.find(eventHubId) != mDevices.end()) {return;}std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));std::vector<std::unique_ptr<InputMapper>> mappers = createMappers(*contextPtr, readerConfig);// insert the context into the devices setmDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});// Must change generation to flag this device as changedbumpGeneration();
}std::vector<std::unique_ptr<InputMapper>> InputDevice::createMappers(InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig) {ftl::Flags<InputDeviceClass> classes = contextPtr.getDeviceClasses();std::vector<std::unique_ptr<InputMapper>> mappers;// Switch-like devices.if (classes.test(InputDeviceClass::SWITCH)) {mappers.push_back(createInputMapper<SwitchInputMapper>(contextPtr, readerConfig));}// Scroll wheel-like devices.if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {mappers.push_back(createInputMapper<RotaryEncoderInputMapper>(contextPtr, readerConfig));}// Vibrator-like devices.if (classes.test(InputDeviceClass::VIBRATOR)) {mappers.push_back(createInputMapper<VibratorInputMapper>(contextPtr, readerConfig));}// Battery-like devices or light-containing devices.// PeripheralController will be created with associated EventHub device.if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {mController = std::make_unique<PeripheralController>(contextPtr);}// Keyboard-like devices.uint32_t keyboardSource = 0;int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;if (classes.test(InputDeviceClass::KEYBOARD)) {keyboardSource |= AINPUT_SOURCE_KEYBOARD;}if (classes.test(InputDeviceClass::ALPHAKEY)) {keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;}if (classes.test(InputDeviceClass::DPAD)) {keyboardSource |= AINPUT_SOURCE_DPAD;}if (classes.test(InputDeviceClass::GAMEPAD)) {keyboardSource |= AINPUT_SOURCE_GAMEPAD;}if (keyboardSource != 0) {mappers.push_back(createInputMapper<KeyboardInputMapper>(contextPtr, readerConfig,keyboardSource, keyboardType));}// Cursor-like devices.if (classes.test(InputDeviceClass::CURSOR)) {mappers.push_back(createInputMapper<CursorInputMapper>(contextPtr, readerConfig));}// Touchscreens and touchpad devices.static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);// TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or// at least load this setting from the IDC file.const InputDeviceIdentifier identifier = contextPtr.getDeviceIdentifier();const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c &&(identifier.product == 0x05c4 || identifier.product == 0x09cc);if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));} else if (classes.test(InputDeviceClass::TOUCH_MT)) {mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig));} else if (classes.test(InputDeviceClass::TOUCH)) {mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig));}// Joystick-like devices.if (classes.test(InputDeviceClass::JOYSTICK)) {mappers.push_back(createInputMapper<JoystickInputMapper>(contextPtr, readerConfig));}// Motion sensor enabled devices.if (classes.test(InputDeviceClass::SENSOR)) {mappers.push_back(createInputMapper<SensorInputMapper>(contextPtr, readerConfig));}// External stylus-like devices.if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {mappers.push_back(createInputMapper<ExternalStylusInputMapper>(contextPtr, readerConfig));}return mappers;
}void InputDevice::addEventHubDevice(int32_t eventHubId,const InputReaderConfiguration& readerConfig) {if (mDevices.find(eventHubId) != mDevices.end()) {return;}std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));std::vector<std::unique_ptr<InputMapper>> mappers = createMappers(*contextPtr, readerConfig);// insert the context into the devices setmDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});// Must change generation to flag this device as changedbumpGeneration();
}

frameworks/native/include/input/InputDevice.h

inline uint32_t getSources() const { return mSources; }

frameworks/native/libs/input/InputDevice.cpp

void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,const InputDeviceIdentifier& identifier, const std::string& alias,bool isExternal, bool hasMic, int32_t associatedDisplayId) {mId = id;mGeneration = generation;mControllerNumber = controllerNumber;mIdentifier = identifier;mAlias = alias;mIsExternal = isExternal;mHasMic = hasMic;mSources = 0;mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;mAssociatedDisplayId = associatedDisplayId;mHasVibrator = false;mHasBattery = false;mHasButtonUnderPad = false;mHasSensor = false;mUsiVersion.reset();mMotionRanges.clear();mSensors.clear();mLights.clear();
}void InputDeviceInfo::addSource(uint32_t source) {mSources |= source;
}

3、keycode对应scankode

2.3 映射文件文件加载loadKeyMapLocked加载 KeyLayoutMap::load(path) 时对应转换,对照kl文件解析,如POWER按键

key 114   VOLUME_DOWN
key 115   VOLUME_UP
key 116   POWER
  • keywordToken == "key":kl文件每行开头关键字key
  • parseKey() -> code = parseInt(codeToken.string()): kl文件关键字key之后的116,对应底层上报的scancode
  • keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string()):kl文件关键字key之后最后的关键字POWER转换keycode
  • DEFINE_KEYCODE(POWER):对应到 AKEYCODE_POWER = 26

frameworks/native/libs/input/KeyLayoutMap.cpp

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;
}

bionic/libc/kernel/uapi/linux/input-event-codes.h
frameworks/native/libs/input/InputEventLabels.cpp

#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key }
// NOTE: If you add a new keycode here you must also add it to several other files.
//       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
#define KEYCODES_SEQUENCE \DEFINE_KEYCODE(UNKNOWN), \DEFINE_KEYCODE(SOFT_LEFT), \DEFINE_KEYCODE(SOFT_RIGHT), \DEFINE_KEYCODE(HOME), \DEFINE_KEYCODE(BACK), \DEFINE_KEYCODE(CALL), \DEFINE_KEYCODE(ENDCALL), \DEFINE_KEYCODE(0), \DEFINE_KEYCODE(1), \DEFINE_KEYCODE(2), \DEFINE_KEYCODE(3), \DEFINE_KEYCODE(4), \DEFINE_KEYCODE(5), \DEFINE_KEYCODE(6), \DEFINE_KEYCODE(7), \DEFINE_KEYCODE(8), \DEFINE_KEYCODE(9), \DEFINE_KEYCODE(STAR), \DEFINE_KEYCODE(POUND), \DEFINE_KEYCODE(DPAD_UP), \DEFINE_KEYCODE(DPAD_DOWN), \DEFINE_KEYCODE(DPAD_LEFT), \DEFINE_KEYCODE(DPAD_RIGHT), \DEFINE_KEYCODE(DPAD_CENTER), \DEFINE_KEYCODE(VOLUME_UP), \DEFINE_KEYCODE(VOLUME_DOWN), \DEFINE_KEYCODE(POWER), \DEFINE_KEYCODE(CAMERA), \DEFINE_KEYCODE(CLEAR), \DEFINE_KEYCODE(A), \DEFINE_KEYCODE(B), \DEFINE_KEYCODE(C), \DEFINE_KEYCODE(D), \DEFINE_KEYCODE(E), \DEFINE_KEYCODE(F), \DEFINE_KEYCODE(G), \DEFINE_KEYCODE(H), \DEFINE_KEYCODE(I), \DEFINE_KEYCODE(J), \DEFINE_KEYCODE(K), \DEFINE_KEYCODE(L), \DEFINE_KEYCODE(M), \DEFINE_KEYCODE(N), \DEFINE_KEYCODE(O), \DEFINE_KEYCODE(P), \DEFINE_KEYCODE(Q), \DEFINE_KEYCODE(R), \DEFINE_KEYCODE(S), \DEFINE_KEYCODE(T), \DEFINE_KEYCODE(U), \DEFINE_KEYCODE(V), \DEFINE_KEYCODE(W), \DEFINE_KEYCODE(X), \DEFINE_KEYCODE(Y), \DEFINE_KEYCODE(Z), \DEFINE_KEYCODE(COMMA), \DEFINE_KEYCODE(PERIOD), \DEFINE_KEYCODE(ALT_LEFT), \DEFINE_KEYCODE(ALT_RIGHT), \DEFINE_KEYCODE(SHIFT_LEFT), \DEFINE_KEYCODE(SHIFT_RIGHT), \DEFINE_KEYCODE(TAB), \DEFINE_KEYCODE(SPACE), \DEFINE_KEYCODE(SYM), \DEFINE_KEYCODE(EXPLORER), \DEFINE_KEYCODE(ENVELOPE), \DEFINE_KEYCODE(ENTER), \DEFINE_KEYCODE(DEL), \DEFINE_KEYCODE(GRAVE), \DEFINE_KEYCODE(MINUS), \DEFINE_KEYCODE(EQUALS), \DEFINE_KEYCODE(LEFT_BRACKET), \DEFINE_KEYCODE(RIGHT_BRACKET), \DEFINE_KEYCODE(BACKSLASH), \DEFINE_KEYCODE(SEMICOLON), \DEFINE_KEYCODE(APOSTROPHE), \DEFINE_KEYCODE(SLASH), \DEFINE_KEYCODE(AT), \DEFINE_KEYCODE(NUM), \DEFINE_KEYCODE(HEADSETHOOK), \DEFINE_KEYCODE(FOCUS), \DEFINE_KEYCODE(PLUS), \DEFINE_KEYCODE(MENU), \DEFINE_KEYCODE(NOTIFICATION), \DEFINE_KEYCODE(SEARCH), \DEFINE_KEYCODE(MEDIA_PLAY_PAUSE), \DEFINE_KEYCODE(MEDIA_STOP), \DEFINE_KEYCODE(MEDIA_NEXT), \DEFINE_KEYCODE(MEDIA_PREVIOUS), \DEFINE_KEYCODE(MEDIA_REWIND), \DEFINE_KEYCODE(MEDIA_FAST_FORWARD), \DEFINE_KEYCODE(MUTE), \DEFINE_KEYCODE(PAGE_UP), \DEFINE_KEYCODE(PAGE_DOWN), \DEFINE_KEYCODE(PICTSYMBOLS), \DEFINE_KEYCODE(SWITCH_CHARSET), \DEFINE_KEYCODE(BUTTON_A), \DEFINE_KEYCODE(BUTTON_B), \DEFINE_KEYCODE(BUTTON_C), \DEFINE_KEYCODE(BUTTON_X), \DEFINE_KEYCODE(BUTTON_Y), \DEFINE_KEYCODE(BUTTON_Z), \DEFINE_KEYCODE(BUTTON_L1), \DEFINE_KEYCODE(BUTTON_R1), \DEFINE_KEYCODE(BUTTON_L2), \DEFINE_KEYCODE(BUTTON_R2), \DEFINE_KEYCODE(BUTTON_THUMBL), \DEFINE_KEYCODE(BUTTON_THUMBR), \DEFINE_KEYCODE(BUTTON_START), \DEFINE_KEYCODE(BUTTON_SELECT), \DEFINE_KEYCODE(BUTTON_MODE), \DEFINE_KEYCODE(ESCAPE), \DEFINE_KEYCODE(FORWARD_DEL), \DEFINE_KEYCODE(CTRL_LEFT), \DEFINE_KEYCODE(CTRL_RIGHT), \DEFINE_KEYCODE(CAPS_LOCK), \DEFINE_KEYCODE(SCROLL_LOCK), \DEFINE_KEYCODE(META_LEFT), \DEFINE_KEYCODE(META_RIGHT), \DEFINE_KEYCODE(FUNCTION), \DEFINE_KEYCODE(SYSRQ), \DEFINE_KEYCODE(BREAK), \DEFINE_KEYCODE(MOVE_HOME), \DEFINE_KEYCODE(MOVE_END), \DEFINE_KEYCODE(INSERT), \DEFINE_KEYCODE(FORWARD), \DEFINE_KEYCODE(MEDIA_PLAY), \DEFINE_KEYCODE(MEDIA_PAUSE), \DEFINE_KEYCODE(MEDIA_CLOSE), \DEFINE_KEYCODE(MEDIA_EJECT), \DEFINE_KEYCODE(MEDIA_RECORD), \DEFINE_KEYCODE(F1), \DEFINE_KEYCODE(F2), \DEFINE_KEYCODE(F3), \DEFINE_KEYCODE(F4), \DEFINE_KEYCODE(F5), \DEFINE_KEYCODE(F6), \DEFINE_KEYCODE(F7), \DEFINE_KEYCODE(F8), \DEFINE_KEYCODE(F9), \DEFINE_KEYCODE(F10), \DEFINE_KEYCODE(F11), \DEFINE_KEYCODE(F12), \DEFINE_KEYCODE(NUM_LOCK), \DEFINE_KEYCODE(NUMPAD_0), \DEFINE_KEYCODE(NUMPAD_1), \DEFINE_KEYCODE(NUMPAD_2), \DEFINE_KEYCODE(NUMPAD_3), \DEFINE_KEYCODE(NUMPAD_4), \DEFINE_KEYCODE(NUMPAD_5), \DEFINE_KEYCODE(NUMPAD_6), \DEFINE_KEYCODE(NUMPAD_7), \DEFINE_KEYCODE(NUMPAD_8), \DEFINE_KEYCODE(NUMPAD_9), \DEFINE_KEYCODE(NUMPAD_DIVIDE), \DEFINE_KEYCODE(NUMPAD_MULTIPLY), \DEFINE_KEYCODE(NUMPAD_SUBTRACT), \DEFINE_KEYCODE(NUMPAD_ADD), \DEFINE_KEYCODE(NUMPAD_DOT), \DEFINE_KEYCODE(NUMPAD_COMMA), \DEFINE_KEYCODE(NUMPAD_ENTER), \DEFINE_KEYCODE(NUMPAD_EQUALS), \DEFINE_KEYCODE(NUMPAD_LEFT_PAREN), \DEFINE_KEYCODE(NUMPAD_RIGHT_PAREN), \DEFINE_KEYCODE(VOLUME_MUTE), \DEFINE_KEYCODE(INFO), \DEFINE_KEYCODE(CHANNEL_UP), \DEFINE_KEYCODE(CHANNEL_DOWN), \DEFINE_KEYCODE(ZOOM_IN), \DEFINE_KEYCODE(ZOOM_OUT), \DEFINE_KEYCODE(TV), \DEFINE_KEYCODE(WINDOW), \DEFINE_KEYCODE(GUIDE), \DEFINE_KEYCODE(DVR), \DEFINE_KEYCODE(BOOKMARK), \DEFINE_KEYCODE(CAPTIONS), \DEFINE_KEYCODE(SETTINGS), \DEFINE_KEYCODE(TV_POWER), \DEFINE_KEYCODE(TV_INPUT), \DEFINE_KEYCODE(STB_POWER), \DEFINE_KEYCODE(STB_INPUT), \DEFINE_KEYCODE(AVR_POWER), \DEFINE_KEYCODE(AVR_INPUT), \DEFINE_KEYCODE(PROG_RED), \DEFINE_KEYCODE(PROG_GREEN), \DEFINE_KEYCODE(PROG_YELLOW), \DEFINE_KEYCODE(PROG_BLUE), \DEFINE_KEYCODE(APP_SWITCH), \DEFINE_KEYCODE(BUTTON_1), \DEFINE_KEYCODE(BUTTON_2), \DEFINE_KEYCODE(BUTTON_3), \DEFINE_KEYCODE(BUTTON_4), \DEFINE_KEYCODE(BUTTON_5), \DEFINE_KEYCODE(BUTTON_6), \DEFINE_KEYCODE(BUTTON_7), \DEFINE_KEYCODE(BUTTON_8), \DEFINE_KEYCODE(BUTTON_9), \DEFINE_KEYCODE(BUTTON_10), \DEFINE_KEYCODE(BUTTON_11), \DEFINE_KEYCODE(BUTTON_12), \DEFINE_KEYCODE(BUTTON_13), \DEFINE_KEYCODE(BUTTON_14), \DEFINE_KEYCODE(BUTTON_15), \DEFINE_KEYCODE(BUTTON_16), \DEFINE_KEYCODE(LANGUAGE_SWITCH), \DEFINE_KEYCODE(MANNER_MODE), \DEFINE_KEYCODE(3D_MODE), \DEFINE_KEYCODE(CONTACTS), \DEFINE_KEYCODE(CALENDAR), \DEFINE_KEYCODE(MUSIC), \DEFINE_KEYCODE(CALCULATOR), \DEFINE_KEYCODE(ZENKAKU_HANKAKU), \DEFINE_KEYCODE(EISU), \DEFINE_KEYCODE(MUHENKAN), \DEFINE_KEYCODE(HENKAN), \DEFINE_KEYCODE(KATAKANA_HIRAGANA), \DEFINE_KEYCODE(YEN), \DEFINE_KEYCODE(RO), \DEFINE_KEYCODE(KANA), \DEFINE_KEYCODE(ASSIST), \DEFINE_KEYCODE(BRIGHTNESS_DOWN), \DEFINE_KEYCODE(BRIGHTNESS_UP), \DEFINE_KEYCODE(MEDIA_AUDIO_TRACK), \DEFINE_KEYCODE(SLEEP), \DEFINE_KEYCODE(WAKEUP), \DEFINE_KEYCODE(PAIRING), \DEFINE_KEYCODE(MEDIA_TOP_MENU), \DEFINE_KEYCODE(11), \DEFINE_KEYCODE(12), \DEFINE_KEYCODE(LAST_CHANNEL), \DEFINE_KEYCODE(TV_DATA_SERVICE), \DEFINE_KEYCODE(VOICE_ASSIST), \DEFINE_KEYCODE(TV_RADIO_SERVICE), \DEFINE_KEYCODE(TV_TELETEXT), \DEFINE_KEYCODE(TV_NUMBER_ENTRY), \DEFINE_KEYCODE(TV_TERRESTRIAL_ANALOG), \DEFINE_KEYCODE(TV_TERRESTRIAL_DIGITAL), \DEFINE_KEYCODE(TV_SATELLITE), \DEFINE_KEYCODE(TV_SATELLITE_BS), \DEFINE_KEYCODE(TV_SATELLITE_CS), \DEFINE_KEYCODE(TV_SATELLITE_SERVICE), \DEFINE_KEYCODE(TV_NETWORK), \DEFINE_KEYCODE(TV_ANTENNA_CABLE), \DEFINE_KEYCODE(TV_INPUT_HDMI_1), \DEFINE_KEYCODE(TV_INPUT_HDMI_2), \DEFINE_KEYCODE(TV_INPUT_HDMI_3), \DEFINE_KEYCODE(TV_INPUT_HDMI_4), \DEFINE_KEYCODE(TV_INPUT_COMPOSITE_1), \DEFINE_KEYCODE(TV_INPUT_COMPOSITE_2), \DEFINE_KEYCODE(TV_INPUT_COMPONENT_1), \DEFINE_KEYCODE(TV_INPUT_COMPONENT_2), \DEFINE_KEYCODE(TV_INPUT_VGA_1), \DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION), \DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_UP), \DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_DOWN), \DEFINE_KEYCODE(TV_ZOOM_MODE), \DEFINE_KEYCODE(TV_CONTENTS_MENU), \DEFINE_KEYCODE(TV_MEDIA_CONTEXT_MENU), \DEFINE_KEYCODE(TV_TIMER_PROGRAMMING), \DEFINE_KEYCODE(HELP), \DEFINE_KEYCODE(NAVIGATE_PREVIOUS), \DEFINE_KEYCODE(NAVIGATE_NEXT), \DEFINE_KEYCODE(NAVIGATE_IN), \DEFINE_KEYCODE(NAVIGATE_OUT), \DEFINE_KEYCODE(STEM_PRIMARY), \DEFINE_KEYCODE(STEM_1), \DEFINE_KEYCODE(STEM_2), \DEFINE_KEYCODE(STEM_3), \DEFINE_KEYCODE(DPAD_UP_LEFT), \DEFINE_KEYCODE(DPAD_DOWN_LEFT), \DEFINE_KEYCODE(DPAD_UP_RIGHT), \DEFINE_KEYCODE(DPAD_DOWN_RIGHT), \DEFINE_KEYCODE(MEDIA_SKIP_FORWARD), \DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD), \DEFINE_KEYCODE(MEDIA_STEP_FORWARD), \DEFINE_KEYCODE(MEDIA_STEP_BACKWARD), \DEFINE_KEYCODE(SOFT_SLEEP), \DEFINE_KEYCODE(CUT), \DEFINE_KEYCODE(COPY), \DEFINE_KEYCODE(PASTE), \DEFINE_KEYCODE(SYSTEM_NAVIGATION_UP), \DEFINE_KEYCODE(SYSTEM_NAVIGATION_DOWN), \DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT), \DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT), \DEFINE_KEYCODE(ALL_APPS), \DEFINE_KEYCODE(REFRESH), \DEFINE_KEYCODE(THUMBS_UP), \DEFINE_KEYCODE(THUMBS_DOWN), \DEFINE_KEYCODE(PROFILE_SWITCH), \DEFINE_KEYCODE(VIDEO_APP_1), \DEFINE_KEYCODE(VIDEO_APP_2), \DEFINE_KEYCODE(VIDEO_APP_3), \DEFINE_KEYCODE(VIDEO_APP_4), \DEFINE_KEYCODE(VIDEO_APP_5), \DEFINE_KEYCODE(VIDEO_APP_6), \DEFINE_KEYCODE(VIDEO_APP_7), \DEFINE_KEYCODE(VIDEO_APP_8), \DEFINE_KEYCODE(FEATURED_APP_1), \DEFINE_KEYCODE(FEATURED_APP_2), \DEFINE_KEYCODE(FEATURED_APP_3), \DEFINE_KEYCODE(FEATURED_APP_4), \DEFINE_KEYCODE(DEMO_APP_1), \DEFINE_KEYCODE(DEMO_APP_2), \DEFINE_KEYCODE(DEMO_APP_3), \DEFINE_KEYCODE(DEMO_APP_4), \DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_DOWN), \DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_UP), \DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_TOGGLE), \DEFINE_KEYCODE(STYLUS_BUTTON_PRIMARY), \DEFINE_KEYCODE(STYLUS_BUTTON_SECONDARY), \DEFINE_KEYCODE(STYLUS_BUTTON_TERTIARY), \DEFINE_KEYCODE(STYLUS_BUTTON_TAIL), \DEFINE_KEYCODE(RECENT_APPS), \DEFINE_KEYCODE(MACRO_1), \DEFINE_KEYCODE(MACRO_2), \DEFINE_KEYCODE(MACRO_3), \DEFINE_KEYCODE(MACRO_4)const std::unordered_map<std::string, int> InputEventLookup::KEYCODES = {KEYCODES_SEQUENCE};
const std::vector<InputEventLabel> InputEventLookup::KEY_NAMES = {KEYCODES_SEQUENCE};std::optional<int> InputEventLookup::getKeyCodeByLabel(const char* label) {return lookupValueByLabel(KEYCODES, label);
}

frameworks/native/include/android/keycodes.h

/*** Key codes.*/
enum {/** Unknown key code. */AKEYCODE_UNKNOWN         = 0,/** Soft Left key.* Usually situated below the display on phones and used as a multi-function* feature key for selecting a software defined function shown on the bottom left* of the display. */AKEYCODE_SOFT_LEFT       = 1,/** Soft Right key.* Usually situated below the display on phones and used as a multi-function* feature key for selecting a software defined function shown on the bottom right* of the display. */AKEYCODE_SOFT_RIGHT      = 2,/** Home key.* This key is handled by the framework and is never delivered to applications. */AKEYCODE_HOME            = 3,/** Back key. */AKEYCODE_BACK            = 4,/** Call key. */AKEYCODE_CALL            = 5,/** End Call key. */AKEYCODE_ENDCALL         = 6,/** '0' key. */AKEYCODE_0               = 7,/** '1' key. */AKEYCODE_1               = 8,/** '2' key. */AKEYCODE_2               = 9,/** '3' key. */AKEYCODE_3               = 10,/** '4' key. */AKEYCODE_4               = 11,/** '5' key. */AKEYCODE_5               = 12,/** '6' key. */AKEYCODE_6               = 13,/** '7' key. */AKEYCODE_7               = 14,/** '8' key. */AKEYCODE_8               = 15,/** '9' key. */AKEYCODE_9               = 16,/** '*' key. */AKEYCODE_STAR            = 17,/** '#' key. */AKEYCODE_POUND           = 18,/** Directional Pad Up key.* May also be synthesized from trackball motions. */AKEYCODE_DPAD_UP         = 19,/** Directional Pad Down key.* May also be synthesized from trackball motions. */AKEYCODE_DPAD_DOWN       = 20,/** Directional Pad Left key.* May also be synthesized from trackball motions. */AKEYCODE_DPAD_LEFT       = 21,/** Directional Pad Right key.* May also be synthesized from trackball motions. */AKEYCODE_DPAD_RIGHT      = 22,/** Directional Pad Center key.* May also be synthesized from trackball motions. */AKEYCODE_DPAD_CENTER     = 23,/** Volume Up key.* Adjusts the speaker volume up. */AKEYCODE_VOLUME_UP       = 24,/** Volume Down key.* Adjusts the speaker volume down. */AKEYCODE_VOLUME_DOWN     = 25,/** Power key. */AKEYCODE_POWER           = 26,/** Camera key.* Used to launch a camera application or take pictures. */AKEYCODE_CAMERA          = 27,/** Clear key. */AKEYCODE_CLEAR           = 28,/** 'A' key. */AKEYCODE_A               = 29,/** 'B' key. */AKEYCODE_B               = 30,/** 'C' key. */AKEYCODE_C               = 31,/** 'D' key. */AKEYCODE_D               = 32,/** 'E' key. */AKEYCODE_E               = 33,/** 'F' key. */AKEYCODE_F               = 34,/** 'G' key. */AKEYCODE_G               = 35,/** 'H' key. */AKEYCODE_H               = 36,/** 'I' key. */AKEYCODE_I               = 37,/** 'J' key. */AKEYCODE_J               = 38,/** 'K' key. */AKEYCODE_K               = 39,/** 'L' key. */AKEYCODE_L               = 40,/** 'M' key. */AKEYCODE_M               = 41,/** 'N' key. */AKEYCODE_N               = 42,/** 'O' key. */AKEYCODE_O               = 43,/** 'P' key. */AKEYCODE_P               = 44,/** 'Q' key. */AKEYCODE_Q               = 45,/** 'R' key. */AKEYCODE_R               = 46,/** 'S' key. */AKEYCODE_S               = 47,/** 'T' key. */AKEYCODE_T               = 48,/** 'U' key. */AKEYCODE_U               = 49,/** 'V' key. */AKEYCODE_V               = 50,/** 'W' key. */AKEYCODE_W               = 51,/** 'X' key. */AKEYCODE_X               = 52,/** 'Y' key. */AKEYCODE_Y               = 53,/** 'Z' key. */AKEYCODE_Z               = 54,/** ',' key. */AKEYCODE_COMMA           = 55,/** '.' key. */AKEYCODE_PERIOD          = 56,/** Left Alt modifier key. */AKEYCODE_ALT_LEFT        = 57,/** Right Alt modifier key. */AKEYCODE_ALT_RIGHT       = 58,/** Left Shift modifier key. */AKEYCODE_SHIFT_LEFT      = 59,/** Right Shift modifier key. */AKEYCODE_SHIFT_RIGHT     = 60,/** Tab key. */AKEYCODE_TAB             = 61,/** Space key. */AKEYCODE_SPACE           = 62,/** Symbol modifier key.* Used to enter alternate symbols. */AKEYCODE_SYM             = 63,/** Explorer special function key.* Used to launch a browser application. */AKEYCODE_EXPLORER        = 64,/** Envelope special function key.* Used to launch a mail application. */AKEYCODE_ENVELOPE        = 65,/** Enter key. */AKEYCODE_ENTER           = 66,/** Backspace key.* Deletes characters before the insertion point, unlike {@link AKEYCODE_FORWARD_DEL}. */AKEYCODE_DEL             = 67,/** '`' (backtick) key. */AKEYCODE_GRAVE           = 68,/** '-'. */AKEYCODE_MINUS           = 69,/** '=' key. */AKEYCODE_EQUALS          = 70,/** '[' key. */AKEYCODE_LEFT_BRACKET    = 71,/** ']' key. */AKEYCODE_RIGHT_BRACKET   = 72,/** '\' key. */AKEYCODE_BACKSLASH       = 73,/** ';' key. */AKEYCODE_SEMICOLON       = 74,/** ''' (apostrophe) key. */AKEYCODE_APOSTROPHE      = 75,/** '/' key. */AKEYCODE_SLASH           = 76,/** '@' key. */AKEYCODE_AT              = 77,/** Number modifier key.* Used to enter numeric symbols.* This key is not {@link AKEYCODE_NUM_LOCK}; it is more like {@link AKEYCODE_ALT_LEFT}. */AKEYCODE_NUM             = 78,/** Headset Hook key.* Used to hang up calls and stop media. */AKEYCODE_HEADSETHOOK     = 79,/** Camera Focus key.* Used to focus the camera. */AKEYCODE_FOCUS           = 80,/** '+' key. */AKEYCODE_PLUS            = 81,/** Menu key. */AKEYCODE_MENU            = 82,/** Notification key. */AKEYCODE_NOTIFICATION    = 83,/** Search key. */AKEYCODE_SEARCH          = 84,/** Play/Pause media key. */AKEYCODE_MEDIA_PLAY_PAUSE= 85,/** Stop media key. */AKEYCODE_MEDIA_STOP      = 86,/** Play Next media key. */AKEYCODE_MEDIA_NEXT      = 87,/** Play Previous media key. */AKEYCODE_MEDIA_PREVIOUS  = 88,/** Rewind media key. */AKEYCODE_MEDIA_REWIND    = 89,/** Fast Forward media key. */AKEYCODE_MEDIA_FAST_FORWARD = 90,/** Mute key.* Mutes the microphone, unlike {@link AKEYCODE_VOLUME_MUTE}. */AKEYCODE_MUTE            = 91,/** Page Up key. */AKEYCODE_PAGE_UP         = 92,/** Page Down key. */AKEYCODE_PAGE_DOWN       = 93,/** Picture Symbols modifier key.* Used to switch symbol sets (Emoji, Kao-moji). */AKEYCODE_PICTSYMBOLS     = 94,/** Switch Charset modifier key.* Used to switch character sets (Kanji, Katakana). */AKEYCODE_SWITCH_CHARSET  = 95,/** A Button key.* On a game controller, the A button should be either the button labeled A* or the first button on the bottom row of controller buttons. */AKEYCODE_BUTTON_A        = 96,/** B Button key.* On a game controller, the B button should be either the button labeled B* or the second button on the bottom row of controller buttons. */AKEYCODE_BUTTON_B        = 97,/** C Button key.* On a game controller, the C button should be either the button labeled C* or the third button on the bottom row of controller buttons. */AKEYCODE_BUTTON_C        = 98,/** X Button key.* On a game controller, the X button should be either the button labeled X* or the first button on the upper row of controller buttons. */AKEYCODE_BUTTON_X        = 99,/** Y Button key.* On a game controller, the Y button should be either the button labeled Y* or the second button on the upper row of controller buttons. */AKEYCODE_BUTTON_Y        = 100,/** Z Button key.* On a game controller, the Z button should be either the button labeled Z* or the third button on the upper row of controller buttons. */AKEYCODE_BUTTON_Z        = 101,/** L1 Button key.* On a game controller, the L1 button should be either the button labeled L1 (or L)* or the top left trigger button. */AKEYCODE_BUTTON_L1       = 102,/** R1 Button key.* On a game controller, the R1 button should be either the button labeled R1 (or R)* or the top right trigger button. */AKEYCODE_BUTTON_R1       = 103,/** L2 Button key.* On a game controller, the L2 button should be either the button labeled L2* or the bottom left trigger button. */AKEYCODE_BUTTON_L2       = 104,/** R2 Button key.* On a game controller, the R2 button should be either the button labeled R2* or the bottom right trigger button. */AKEYCODE_BUTTON_R2       = 105,/** Left Thumb Button key.* On a game controller, the left thumb button indicates that the left (or only)* joystick is pressed. */AKEYCODE_BUTTON_THUMBL   = 106,/** Right Thumb Button key.* On a game controller, the right thumb button indicates that the right* joystick is pressed. */AKEYCODE_BUTTON_THUMBR   = 107,/** Start Button key.* On a game controller, the button labeled Start. */AKEYCODE_BUTTON_START    = 108,/** Select Button key.* On a game controller, the button labeled Select. */AKEYCODE_BUTTON_SELECT   = 109,/** Mode Button key.* On a game controller, the button labeled Mode. */AKEYCODE_BUTTON_MODE     = 110,/** Escape key. */AKEYCODE_ESCAPE          = 111,/** Forward Delete key.* Deletes characters ahead of the insertion point, unlike {@link AKEYCODE_DEL}. */AKEYCODE_FORWARD_DEL     = 112,/** Left Control modifier key. */AKEYCODE_CTRL_LEFT       = 113,/** Right Control modifier key. */AKEYCODE_CTRL_RIGHT      = 114,/** Caps Lock key. */AKEYCODE_CAPS_LOCK       = 115,/** Scroll Lock key. */AKEYCODE_SCROLL_LOCK     = 116,/** Left Meta modifier key. */AKEYCODE_META_LEFT       = 117,/** Right Meta modifier key. */AKEYCODE_META_RIGHT      = 118,/** Function modifier key. */AKEYCODE_FUNCTION        = 119,/** System Request / Print Screen key. */AKEYCODE_SYSRQ           = 120,/** Break / Pause key. */AKEYCODE_BREAK           = 121,/** Home Movement key.* Used for scrolling or moving the cursor around to the start of a line* or to the top of a list. */AKEYCODE_MOVE_HOME       = 122,/** End Movement key.* Used for scrolling or moving the cursor around to the end of a line* or to the bottom of a list. */AKEYCODE_MOVE_END        = 123,/** Insert key.* Toggles insert / overwrite edit mode. */AKEYCODE_INSERT          = 124,/** Forward key.* Navigates forward in the history stack.  Complement of {@link AKEYCODE_BACK}. */AKEYCODE_FORWARD         = 125,/** Play media key. */AKEYCODE_MEDIA_PLAY      = 126,/** Pause media key. */AKEYCODE_MEDIA_PAUSE     = 127,/** Close media key.* May be used to close a CD tray, for example. */AKEYCODE_MEDIA_CLOSE     = 128,/** Eject media key.* May be used to eject a CD tray, for example. */AKEYCODE_MEDIA_EJECT     = 129,/** Record media key. */AKEYCODE_MEDIA_RECORD    = 130,/** F1 key. */AKEYCODE_F1              = 131,/** F2 key. */AKEYCODE_F2              = 132,/** F3 key. */AKEYCODE_F3              = 133,/** F4 key. */AKEYCODE_F4              = 134,/** F5 key. */AKEYCODE_F5              = 135,/** F6 key. */AKEYCODE_F6              = 136,/** F7 key. */AKEYCODE_F7              = 137,/** F8 key. */AKEYCODE_F8              = 138,/** F9 key. */AKEYCODE_F9              = 139,/** F10 key. */AKEYCODE_F10             = 140,/** F11 key. */AKEYCODE_F11             = 141,/** F12 key. */AKEYCODE_F12             = 142,/** Num Lock key.* This is the Num Lock key; it is different from {@link AKEYCODE_NUM}.* This key alters the behavior of other keys on the numeric keypad. */AKEYCODE_NUM_LOCK        = 143,/** Numeric keypad '0' key. */AKEYCODE_NUMPAD_0        = 144,/** Numeric keypad '1' key. */AKEYCODE_NUMPAD_1        = 145,/** Numeric keypad '2' key. */AKEYCODE_NUMPAD_2        = 146,/** Numeric keypad '3' key. */AKEYCODE_NUMPAD_3        = 147,/** Numeric keypad '4' key. */AKEYCODE_NUMPAD_4        = 148,/** Numeric keypad '5' key. */AKEYCODE_NUMPAD_5        = 149,/** Numeric keypad '6' key. */AKEYCODE_NUMPAD_6        = 150,/** Numeric keypad '7' key. */AKEYCODE_NUMPAD_7        = 151,/** Numeric keypad '8' key. */AKEYCODE_NUMPAD_8        = 152,/** Numeric keypad '9' key. */AKEYCODE_NUMPAD_9        = 153,/** Numeric keypad '/' key (for division). */AKEYCODE_NUMPAD_DIVIDE   = 154,/** Numeric keypad '*' key (for multiplication). */AKEYCODE_NUMPAD_MULTIPLY = 155,/** Numeric keypad '-' key (for subtraction). */AKEYCODE_NUMPAD_SUBTRACT = 156,/** Numeric keypad '+' key (for addition). */AKEYCODE_NUMPAD_ADD      = 157,/** Numeric keypad '.' key (for decimals or digit grouping). */AKEYCODE_NUMPAD_DOT      = 158,/** Numeric keypad ',' key (for decimals or digit grouping). */AKEYCODE_NUMPAD_COMMA    = 159,/** Numeric keypad Enter key. */AKEYCODE_NUMPAD_ENTER    = 160,/** Numeric keypad '=' key. */AKEYCODE_NUMPAD_EQUALS   = 161,/** Numeric keypad '(' key. */AKEYCODE_NUMPAD_LEFT_PAREN = 162,/** Numeric keypad ')' key. */AKEYCODE_NUMPAD_RIGHT_PAREN = 163,/** Volume Mute key.* Mutes the speaker, unlike {@link AKEYCODE_MUTE}.* This key should normally be implemented as a toggle such that the first press* mutes the speaker and the second press restores the original volume. */AKEYCODE_VOLUME_MUTE     = 164,/** Info key.* Common on TV remotes to show additional information related to what is* currently being viewed. */AKEYCODE_INFO            = 165,/** Channel up key.* On TV remotes, increments the television channel. */AKEYCODE_CHANNEL_UP      = 166,/** Channel down key.* On TV remotes, decrements the television channel. */AKEYCODE_CHANNEL_DOWN    = 167,/** Zoom in key. */AKEYCODE_ZOOM_IN         = 168,/** Zoom out key. */AKEYCODE_ZOOM_OUT        = 169,/** TV key.* On TV remotes, switches to viewing live TV. */AKEYCODE_TV              = 170,/** Window key.* On TV remotes, toggles picture-in-picture mode or other windowing functions. */AKEYCODE_WINDOW          = 171,/** Guide key.* On TV remotes, shows a programming guide. */AKEYCODE_GUIDE           = 172,/** DVR key.* On some TV remotes, switches to a DVR mode for recorded shows. */AKEYCODE_DVR             = 173,/** Bookmark key.* On some TV remotes, bookmarks content or web pages. */AKEYCODE_BOOKMARK        = 174,/** Toggle captions key.* Switches the mode for closed-captioning text, for example during television shows. */AKEYCODE_CAPTIONS        = 175,/** Settings key.* Starts the system settings activity. */AKEYCODE_SETTINGS        = 176,/** TV power key.* On TV remotes, toggles the power on a television screen. */AKEYCODE_TV_POWER        = 177,/** TV input key.* On TV remotes, switches the input on a television screen. */AKEYCODE_TV_INPUT        = 178,/** Set-top-box power key.* On TV remotes, toggles the power on an external Set-top-box. */AKEYCODE_STB_POWER       = 179,/** Set-top-box input key.* On TV remotes, switches the input mode on an external Set-top-box. */AKEYCODE_STB_INPUT       = 180,/** A/V Receiver power key.* On TV remotes, toggles the power on an external A/V Receiver. */AKEYCODE_AVR_POWER       = 181,/** A/V Receiver input key.* On TV remotes, switches the input mode on an external A/V Receiver. */AKEYCODE_AVR_INPUT       = 182,/** Red "programmable" key.* On TV remotes, acts as a contextual/programmable key. */AKEYCODE_PROG_RED        = 183,/** Green "programmable" key.* On TV remotes, actsas a contextual/programmable key. */AKEYCODE_PROG_GREEN      = 184,/** Yellow "programmable" key.* On TV remotes, acts as a contextual/programmable key. */AKEYCODE_PROG_YELLOW     = 185,/** Blue "programmable" key.* On TV remotes, acts as a contextual/programmable key. */AKEYCODE_PROG_BLUE       = 186,/** App switch key.* Should bring up the application switcher dialog. */AKEYCODE_APP_SWITCH      = 187,/** Generic Game Pad Button #1.*/AKEYCODE_BUTTON_1        = 188,/** Generic Game Pad Button #2.*/AKEYCODE_BUTTON_2        = 189,/** Generic Game Pad Button #3.*/AKEYCODE_BUTTON_3        = 190,/** Generic Game Pad Button #4.*/AKEYCODE_BUTTON_4        = 191,/** Generic Game Pad Button #5.*/AKEYCODE_BUTTON_5        = 192,/** Generic Game Pad Button #6.*/AKEYCODE_BUTTON_6        = 193,/** Generic Game Pad Button #7.*/AKEYCODE_BUTTON_7        = 194,/** Generic Game Pad Button #8.*/AKEYCODE_BUTTON_8        = 195,/** Generic Game Pad Button #9.*/AKEYCODE_BUTTON_9        = 196,/** Generic Game Pad Button #10.*/AKEYCODE_BUTTON_10       = 197,/** Generic Game Pad Button #11.*/AKEYCODE_BUTTON_11       = 198,/** Generic Game Pad Button #12.*/AKEYCODE_BUTTON_12       = 199,/** Generic Game Pad Button #13.*/AKEYCODE_BUTTON_13       = 200,/** Generic Game Pad Button #14.*/AKEYCODE_BUTTON_14       = 201,/** Generic Game Pad Button #15.*/AKEYCODE_BUTTON_15       = 202,/** Generic Game Pad Button #16.*/AKEYCODE_BUTTON_16       = 203,/** Language Switch key.* Toggles the current input language such as switching between English and Japanese on* a QWERTY keyboard.  On some devices, the same function may be performed by* pressing Shift+Spacebar. */AKEYCODE_LANGUAGE_SWITCH = 204,/** Manner Mode key.* Toggles silent or vibrate mode on and off to make the device behave more politely* in certain settings such as on a crowded train.  On some devices, the key may only* operate when long-pressed. */AKEYCODE_MANNER_MODE     = 205,/** 3D Mode key.* Toggles the display between 2D and 3D mode. */AKEYCODE_3D_MODE         = 206,/** Contacts special function key.* Used to launch an address book application. */AKEYCODE_CONTACTS        = 207,/** Calendar special function key.* Used to launch a calendar application. */AKEYCODE_CALENDAR        = 208,/** Music special function key.* Used to launch a music player application. */AKEYCODE_MUSIC           = 209,/** Calculator special function key.* Used to launch a calculator application. */AKEYCODE_CALCULATOR      = 210,/** Japanese full-width / half-width key. */AKEYCODE_ZENKAKU_HANKAKU = 211,/** Japanese alphanumeric key. */AKEYCODE_EISU            = 212,/** Japanese non-conversion key. */AKEYCODE_MUHENKAN        = 213,/** Japanese conversion key. */AKEYCODE_HENKAN          = 214,/** Japanese katakana / hiragana key. */AKEYCODE_KATAKANA_HIRAGANA = 215,/** Japanese Yen key. */AKEYCODE_YEN             = 216,/** Japanese Ro key. */AKEYCODE_RO              = 217,/** Japanese kana key. */AKEYCODE_KANA            = 218,/** Assist key.* Launches the global assist activity.  Not delivered to applications. */AKEYCODE_ASSIST          = 219,/** Brightness Down key.* Adjusts the screen brightness down. */AKEYCODE_BRIGHTNESS_DOWN = 220,/** Brightness Up key.* Adjusts the screen brightness up. */AKEYCODE_BRIGHTNESS_UP   = 221,/** Audio Track key.* Switches the audio tracks. */AKEYCODE_MEDIA_AUDIO_TRACK = 222,/** Sleep key.* Puts the device to sleep.  Behaves somewhat like {@link AKEYCODE_POWER} but it* has no effect if the device is already asleep. */AKEYCODE_SLEEP           = 223,/** Wakeup key.* Wakes up the device.  Behaves somewhat like {@link AKEYCODE_POWER} but it* has no effect if the device is already awake. */AKEYCODE_WAKEUP          = 224,/** Pairing key.* Initiates peripheral pairing mode. Useful for pairing remote control* devices or game controllers, especially if no other input mode is* available. */AKEYCODE_PAIRING         = 225,/** Media Top Menu key.* Goes to the top of media menu. */AKEYCODE_MEDIA_TOP_MENU  = 226,/** '11' key. */AKEYCODE_11              = 227,/** '12' key. */AKEYCODE_12              = 228,/** Last Channel key.* Goes to the last viewed channel. */AKEYCODE_LAST_CHANNEL    = 229,/** TV data service key.* Displays data services like weather, sports. */AKEYCODE_TV_DATA_SERVICE = 230,/** Voice Assist key.* Launches the global voice assist activity. Not delivered to applications. */AKEYCODE_VOICE_ASSIST    = 231,/** Radio key.* Toggles TV service / Radio service. */AKEYCODE_TV_RADIO_SERVICE = 232,/** Teletext key.* Displays Teletext service. */AKEYCODE_TV_TELETEXT     = 233,/** Number entry key.* Initiates to enter multi-digit channel nubmber when each digit key is assigned* for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC* User Control Code. */AKEYCODE_TV_NUMBER_ENTRY = 234,/** Analog Terrestrial key.* Switches to analog terrestrial broadcast service. */AKEYCODE_TV_TERRESTRIAL_ANALOG = 235,/** Digital Terrestrial key.* Switches to digital terrestrial broadcast service. */AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236,/** Satellite key.* Switches to digital satellite broadcast service. */AKEYCODE_TV_SATELLITE    = 237,/** BS key.* Switches to BS digital satellite broadcasting service available in Japan. */AKEYCODE_TV_SATELLITE_BS = 238,/** CS key.* Switches to CS digital satellite broadcasting service available in Japan. */AKEYCODE_TV_SATELLITE_CS = 239,/** BS/CS key.* Toggles between BS and CS digital satellite services. */AKEYCODE_TV_SATELLITE_SERVICE = 240,/** Toggle Network key.* Toggles selecting broacast services. */AKEYCODE_TV_NETWORK      = 241,/** Antenna/Cable key.* Toggles broadcast input source between antenna and cable. */AKEYCODE_TV_ANTENNA_CABLE = 242,/** HDMI #1 key.* Switches to HDMI input #1. */AKEYCODE_TV_INPUT_HDMI_1 = 243,/** HDMI #2 key.* Switches to HDMI input #2. */AKEYCODE_TV_INPUT_HDMI_2 = 244,/** HDMI #3 key.* Switches to HDMI input #3. */AKEYCODE_TV_INPUT_HDMI_3 = 245,/** HDMI #4 key.* Switches to HDMI input #4. */AKEYCODE_TV_INPUT_HDMI_4 = 246,/** Composite #1 key.* Switches to composite video input #1. */AKEYCODE_TV_INPUT_COMPOSITE_1 = 247,/** Composite #2 key.* Switches to composite video input #2. */AKEYCODE_TV_INPUT_COMPOSITE_2 = 248,/** Component #1 key.* Switches to component video input #1. */AKEYCODE_TV_INPUT_COMPONENT_1 = 249,/** Component #2 key.* Switches to component video input #2. */AKEYCODE_TV_INPUT_COMPONENT_2 = 250,/** VGA #1 key.* Switches to VGA (analog RGB) input #1. */AKEYCODE_TV_INPUT_VGA_1  = 251,/** Audio description key.* Toggles audio description off / on. */AKEYCODE_TV_AUDIO_DESCRIPTION = 252,/** Audio description mixing volume up key.* Louden audio description volume as compared with normal audio volume. */AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253,/** Audio description mixing volume down key.* Lessen audio description volume as compared with normal audio volume. */AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254,/** Zoom mode key.* Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */AKEYCODE_TV_ZOOM_MODE    = 255,/** Contents menu key.* Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control* Code */AKEYCODE_TV_CONTENTS_MENU = 256,/** Media context menu key.* Goes to the context menu of media contents. Corresponds to Media Context-sensitive* Menu (0x11) of CEC User Control Code. */AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257,/** Timer programming key.* Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of* CEC User Control Code. */AKEYCODE_TV_TIMER_PROGRAMMING = 258,/** Help key. */AKEYCODE_HELP            = 259,AKEYCODE_NAVIGATE_PREVIOUS = 260,AKEYCODE_NAVIGATE_NEXT   = 261,AKEYCODE_NAVIGATE_IN     = 262,AKEYCODE_NAVIGATE_OUT    = 263,/** Primary stem key for Wear* Main power/reset button on watch. */AKEYCODE_STEM_PRIMARY = 264,/** Generic stem key 1 for Wear */AKEYCODE_STEM_1 = 265,/** Generic stem key 2 for Wear */AKEYCODE_STEM_2 = 266,/** Generic stem key 3 for Wear */AKEYCODE_STEM_3 = 267,/** Directional Pad Up-Left */AKEYCODE_DPAD_UP_LEFT    = 268,/** Directional Pad Down-Left */AKEYCODE_DPAD_DOWN_LEFT  = 269,/** Directional Pad Up-Right */AKEYCODE_DPAD_UP_RIGHT   = 270,/** Directional Pad Down-Right */AKEYCODE_DPAD_DOWN_RIGHT = 271,/** Skip forward media key */AKEYCODE_MEDIA_SKIP_FORWARD = 272,/** Skip backward media key */AKEYCODE_MEDIA_SKIP_BACKWARD = 273,/** Step forward media key.* Steps media forward one from at a time. */AKEYCODE_MEDIA_STEP_FORWARD = 274,/** Step backward media key.* Steps media backward one from at a time. */AKEYCODE_MEDIA_STEP_BACKWARD = 275,/** Put device to sleep unless a wakelock is held. */AKEYCODE_SOFT_SLEEP = 276,/** Cut key. */AKEYCODE_CUT = 277,/** Copy key. */AKEYCODE_COPY = 278,/** Paste key. */AKEYCODE_PASTE = 279,/** fingerprint navigation key, up. */AKEYCODE_SYSTEM_NAVIGATION_UP = 280,/** fingerprint navigation key, down. */AKEYCODE_SYSTEM_NAVIGATION_DOWN = 281,/** fingerprint navigation key, left. */AKEYCODE_SYSTEM_NAVIGATION_LEFT = 282,/** fingerprint navigation key, right. */AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283,/** all apps */AKEYCODE_ALL_APPS = 284,/** refresh key */AKEYCODE_REFRESH = 285,/** Thumbs up key. Apps can use this to let user upvote content. */AKEYCODE_THUMBS_UP = 286,/** Thumbs down key. Apps can use this to let user downvote content. */AKEYCODE_THUMBS_DOWN = 287,/** Used to switch current account that is consuming content.* May be consumed by system to switch current viewer profile. */AKEYCODE_PROFILE_SWITCH = 288,/** Video Application key #1. */AKEYCODE_VIDEO_APP_1 = 289,/** Video Application key #2. */AKEYCODE_VIDEO_APP_2 = 290,/** Video Application key #3. */AKEYCODE_VIDEO_APP_3 = 291,/** Video Application key #4. */AKEYCODE_VIDEO_APP_4 = 292,/** Video Application key #5. */AKEYCODE_VIDEO_APP_5 = 293,/** Video Application key #6. */AKEYCODE_VIDEO_APP_6 = 294,/** Video Application key #7. */AKEYCODE_VIDEO_APP_7 = 295,/** Video Application key #8. */AKEYCODE_VIDEO_APP_8 = 296,/** Featured Application key #1. */AKEYCODE_FEATURED_APP_1 = 297,/** Featured Application key #2. */AKEYCODE_FEATURED_APP_2 = 298,/** Featured Application key #3. */AKEYCODE_FEATURED_APP_3 = 299,/** Featured Application key #4. */AKEYCODE_FEATURED_APP_4 = 300,/** Demo Application key #1. */AKEYCODE_DEMO_APP_1 = 301,/** Demo Application key #2. */AKEYCODE_DEMO_APP_2 = 302,/** Demo Application key #3. */AKEYCODE_DEMO_APP_3 = 303,/** Demo Application key #4. */AKEYCODE_DEMO_APP_4 = 304,/** Keyboard backlight Down key.* Adjusts the keyboard backlight brightness down. */AKEYCODE_KEYBOARD_BACKLIGHT_DOWN = 305,/** Keyboard backlight Up key.* Adjusts the keyboard backlight brightness up. */AKEYCODE_KEYBOARD_BACKLIGHT_UP = 306,/** Keyboard backlight Toggle key.* Toggles the keyboard backlight on/off. */AKEYCODE_KEYBOARD_BACKLIGHT_TOGGLE = 307,/** The primary button on the barrel of a stylus.* This is usually the button closest to the tip of the stylus. */AKEYCODE_STYLUS_BUTTON_PRIMARY = 308,/** The secondary button on the barrel of a stylus.* This is usually the second button from the tip of the stylus. */AKEYCODE_STYLUS_BUTTON_SECONDARY = 309,/** The tertiary button on the barrel of a stylus.* This is usually the third button from the tip of the stylus. */AKEYCODE_STYLUS_BUTTON_TERTIARY = 310,/** A button on the tail end of a stylus. */AKEYCODE_STYLUS_BUTTON_TAIL = 311,/** Key to open recent apps (a.k.a. Overview) */AKEYCODE_RECENT_APPS = 312,/** User customizable key #1. */AKEYCODE_MACRO_1 = 313,/** User customizable key #2. */AKEYCODE_MACRO_2 = 314,/** User customizable key #3. */AKEYCODE_MACRO_3 = 315,/** User customizable key #4. */AKEYCODE_MACRO_4 = 316,// NOTE: If you add a new keycode here you must also add it to several other files.//       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
};

4、KeyEvent.java 添加对应keycode

frameworks/base/core/java/android/view/KeyEvent.java

    /*** Key code constant: A button whose usage can be customized by the user through*                    the system.* User customizable key #4.*/public static final int KEYCODE_MACRO_4 = 316;/*** Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent.* @hide*/@TestApipublic static final int LAST_KEYCODE = KEYCODE_MACRO_4;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/439562.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【星汇极客】手把手教学STM32 HAL库+FreeRTOS之创建工程(0)

前言 本人是一名嵌入式学习者&#xff0c;在大学期间也参加了不少的竞赛并获奖&#xff0c;包括但不限于&#xff1a;江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三。 后面会经常写一下博客&…

服务器conda环境安装rpy2

参考博客 https://stackoverflow.com/questions/68936589/how-to-select-r-installation-when-using-rpy2-on-conda 现在我遇到这样一个问题&#xff0c;服务器系统环境没有R(没有权限安装&#xff09;&#xff0c;我只能在minconda的conda环境中使用R, 使用方法如下 我现在…

(11)MATLAB莱斯(Rician)衰落信道仿真2

文章目录 前言一、莱斯衰落信道仿真模型二、仿真代码与结果1.仿真代码2.仿真结果画图 三、后续&#xff1a;四、参考文献&#xff1a; 前言 首先给出莱斯衰落信道仿真模型&#xff0c;该模型由直射路径分量和反射路径分量组成&#xff0c;其中反射路径分量由瑞利衰落信道模型构…

Art. 1 | 信号、信息与消息的区别及其在通信中的应用

信号、信息与消息的区别及其在通信中的应用 通信技术是现代社会的基石&#xff0c;其广泛应用于日常生活的各个方面。从手机、互联网到企业信息管理&#xff0c;通信系统无处不在。在这一技术领域中&#xff0c;信号、信息和消息是三大基础概念&#xff0c;支撑着整个通信系统…

云计算Openstack Glance

OpenStack Glance&#xff08;或称为Glance&#xff0c;但通常OpenStack官方文档中使用的是“Glance”作为项目代号&#xff09;是OpenStack的镜像服务组件&#xff0c;为创建虚拟机提供镜像服务。以下是对OpenStack Glance的详细解析&#xff1a; 一、基本功能 Glance主要提…

【AI人工智能】文心智能体,双人冒险游戏智能体创作分享

背景 最近半年&#xff0c;“AI agent”&#xff08;智能体&#xff09;这一词汇变得非常热门。许多人以为创建自己的智能体会很复杂&#xff0c;实际上&#xff0c;现有的平台已经大大降低了操作门槛。只要有创意&#xff0c;几乎每个人都可以轻松创建属于自己的智能体。今天…

Linux下静态库与动态库制作及分文件编程

Linux下静态库与动态库制作及分文件编程 文章目录 Linux下静态库与动态库制作及分文件编程1.分文件编程1.1优点1.2操作逻辑1.3示例 2.Linux库的概念3.静态库的制作与使用3.1优缺点3.2命名规则3.3制作步骤3.4开始享用 4.动态库的制作与使用4.1优缺点4.2动态库命名规则4.3制作步骤…

Uniapp API

1.uni.showToast 显示消息提示框 unishowToast({ obj参数 }) 2.uni.showLoading 显示 loading 提示框, 需主动调用 uni.hideLoading 才能关闭提示框。 3.uni.showModal 显示模态弹窗&#xff0c;可以只有一个确定按钮&#xff0c;也可以同时有确定和取消按钮。类似于一个A…

VLAN:虚拟局域网

VLAN:虚拟局域网 交换机和路由器协同工作后&#xff0c;将原先的一个广播域&#xff0c;逻辑上&#xff0c;切分为多个广播域。 第一步:创建VLAN [SW1]dispaly vlan 查询vlan VID&#xff08;VLAN ID&#xff09;:用来区分和标定不同的vlan 由12位二进制构成 范围: 0-4…

算法笔记(十一)——优先级队列(堆)

文章目录 最后一块石头的重量数据流中的第 K 大元素前K个高频单词数据流的中位数 优先级队列是一种特殊的队列&#xff0c;元素按照优先级从高到低&#xff08;或从低到高&#xff09;排列&#xff0c;高优先级的元素先出队&#xff0c;可以用 堆来实现 堆是一种二叉树的结构&…

HTB:Preignition[WriteUP]

连接至HTB服务器并启动靶机 靶机IP&#xff1a;10.129.157.49 分配IP&#xff1a;10.10.16.12 1.Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (…

如何安全地大规模部署 GenAI 应用程序

大型语言模型和其他形式的生成式人工智能(GenAI) 的广泛使用带来了许多组织可能没有意识到的安全风险。幸运的是&#xff0c;网络和安全提供商正在寻找方法来应对这些前所未有的威胁。 随着人工智能越来越深入地融入日常业务流程&#xff0c;它面临着泄露专有信息、提供错误答…

2.创建第一个MySQL存储过程(2/10)

引言 在现代数据库管理中&#xff0c;存储过程扮演着至关重要的角色。它们是一组为了执行特定任务而编写的SQL语句集合&#xff0c;这些语句被保存在数据库中&#xff0c;并且可以被多次调用执行。存储过程不仅可以提高数据库操作的效率&#xff0c;还能增强数据的安全性和一致…

Docker 启动 Neo4j:详细配置指南和浏览器访问

Docker 启动 Neo4j&#xff1a;详细配置指南和浏览器访问 文章目录 Docker 启动 Neo4j&#xff1a;详细配置指南和浏览器访问一 Neo4j compose 得 yml 配置二 配置描述三 浏览器访问 这篇文章详细介绍了如何使用 Docker Compose 启动 Neo4j 数据库&#xff0c;包括 docker-com…

八大排序--01冒泡排序

假设有一组数据 arr[]{2&#xff0c;0&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;7} 方法&#xff1a;开辟两个指针&#xff0c;指向如图&#xff0c;前后两两进行比较&#xff0c;大数据向后冒泡传递&#xff0c;小数据换到前面。 一次冒泡后&#xff0c;数组中最大…

C++ | Leetcode C++题解之第459题重复的子字符串

题目&#xff1a; 题解&#xff1a; class Solution { public:bool kmp(const string& query, const string& pattern) {int n query.size();int m pattern.size();vector<int> fail(m, -1);for (int i 1; i < m; i) {int j fail[i - 1];while (j ! -1 &…

java基础_异常总结详解

1 列举一些列举常见的运行时异常 运行时异常都是 RuntimeException 子类异常 NullPointerException - 空指针异常 ClassCastException - 类转换异常 IndexOutOfBoundsException - 下标越界异常 ArithmeticException - 计算异常 IllegalArgumentException - 非法参数异常 Numb…

Elasticsearch:使用 LLM 实现传统搜索自动化

作者&#xff1a;来自 Elastic Han Xiang Choong 这篇简短的文章是关于将结构化数据上传到 Elastic 索引&#xff0c;然后将纯英语查询转换为查询 DSL 语句&#xff0c;以使用特定过滤器和范围搜索特定条件。完整代码位于此 Github repo 中。 首先&#xff0c;运行以下命令安装…

小阿轩yx-案例:jenkins部署Maven和NodeJS项目

小阿轩yx-案例&#xff1a;jenkins部署Maven和NodeJS项目 前言 在 Java 项目开发中&#xff0c;项目的编译、测试、打包等是比较繁琐的&#xff0c;属于重复劳动的工作&#xff0c;浪费人力和时间成本。以往开发项目时&#xff0c;程序员往往需要花较多的精力在引用 jar 包搭…

STM32的串行外设接口SPI

一、SPI简介 1.SPI总线特点 &#xff08;1&#xff09;四条通信线 SPI需要SCK、MISO、MOSI、NSS四条通信线来完成数据传输 &#xff0c;每增加一个从机&#xff0c;多一条NSS通信线。 &#xff08;2&#xff09;多主多从 SPI总线允许有多个主机和多个从机。 &#xff08;3&…