Loading include/input/InputDevice.h +11 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,14 @@ struct InputDeviceLightInfo { int32_t ordinal; }; struct InputDeviceBatteryInfo { explicit InputDeviceBatteryInfo(std::string name, int32_t id) : name(name), id(id) {} // Name string of the battery. std::string name; // Battery id int32_t id; }; /* * Describes the characteristics and capabilities of an input device. */ Loading Loading @@ -219,6 +227,7 @@ public: float min, float max, float flat, float fuzz, float resolution); void addMotionRange(const MotionRange& range); void addSensorInfo(const InputDeviceSensorInfo& info); void addBatteryInfo(const InputDeviceBatteryInfo& info); void addLightInfo(const InputDeviceLightInfo& info); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } Loading Loading @@ -276,6 +285,8 @@ private: std::unordered_map<InputDeviceSensorType, InputDeviceSensorInfo> mSensors; /* Map from light ID to light info */ std::unordered_map<int32_t, InputDeviceLightInfo> mLights; /* Map from battery ID to battery info */ std::unordered_map<int32_t, InputDeviceBatteryInfo> mBatteries; }; /* Types of input device configuration files. */ Loading libs/input/InputDevice.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -231,6 +231,13 @@ void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) { mSensors.insert_or_assign(info.type, info); } void InputDeviceInfo::addBatteryInfo(const InputDeviceBatteryInfo& info) { if (mBatteries.find(info.id) != mBatteries.end()) { ALOGW("Battery id %d already exists, will be replaced by new battery added.", info.id); } mBatteries.insert_or_assign(info.id, info); } void InputDeviceInfo::addLightInfo(const InputDeviceLightInfo& info) { if (mLights.find(info.id) != mLights.end()) { ALOGW("Light id %d already exists, will be replaced by new light added.", info.id); Loading services/inputflinger/reader/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ package { cc_library_headers { name: "libinputreader_headers", export_include_dirs: [ "controller", "include", "mapper", "mapper/accumulator", Loading @@ -35,17 +36,16 @@ filegroup { srcs: [ "EventHub.cpp", "InputDevice.cpp", "controller/InputController.cpp", "mapper/accumulator/CursorButtonAccumulator.cpp", "mapper/accumulator/CursorScrollAccumulator.cpp", "mapper/accumulator/SingleTouchMotionAccumulator.cpp", "mapper/accumulator/TouchButtonAccumulator.cpp", "mapper/BatteryInputMapper.cpp", "mapper/CursorInputMapper.cpp", "mapper/ExternalStylusInputMapper.cpp", "mapper/InputMapper.cpp", "mapper/JoystickInputMapper.cpp", "mapper/KeyboardInputMapper.cpp", "mapper/LightInputMapper.cpp", "mapper/MultiTouchInputMapper.cpp", "mapper/RotaryEncoderInputMapper.cpp", "mapper/SensorInputMapper.cpp", Loading services/inputflinger/reader/EventHub.cpp +167 −86 Original line number Diff line number Diff line Loading @@ -70,6 +70,20 @@ static const char* VIDEO_DEVICE_PATH = "/dev"; static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0; static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1; // Mapping for input battery class node IDs lookup. // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt static const std::unordered_map<std::string, InputBatteryClass> BATTERY_CLASSES = {{"capacity", InputBatteryClass::CAPACITY}, {"capacity_level", InputBatteryClass::CAPACITY_LEVEL}, {"status", InputBatteryClass::STATUS}}; // Mapping for input battery class node names lookup. // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt static const std::unordered_map<InputBatteryClass, std::string> BATTERY_NODES = {{InputBatteryClass::CAPACITY, "capacity"}, {InputBatteryClass::CAPACITY_LEVEL, "capacity_level"}, {InputBatteryClass::STATUS, "status"}}; // must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c static const std::unordered_map<std::string, int32_t> BATTERY_STATUS = {{"Unknown", BATTERY_STATUS_UNKNOWN}, Loading Loading @@ -349,7 +363,7 @@ EventHub::Device::Device(int fd, int32_t id, const std::string& path, virtualKeyMap(nullptr), ffEffectPlaying(false), ffEffectId(-1), nextLightId(0), miscDevice(nullptr), controllerNumber(0), enabled(true), isVirtual(fd < 0) {} Loading Loading @@ -540,32 +554,36 @@ status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const { } // Check the sysfs path for any input device batteries, returns true if battery found. bool EventHub::Device::configureBatteryLocked() { if (!sysfsRootPath.has_value()) { return false; bool EventHub::MiscDevice::configureBatteryLocked() { nextBatteryId = 0; // Check if device has any battery. const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY); for (const auto& nodePath : paths) { RawBatteryInfo info; info.id = ++nextBatteryId; info.path = nodePath; info.name = nodePath.filename(); // Scan the path for all the files // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt const auto& files = allFilesInPath(nodePath); for (const auto& file : files) { const auto it = BATTERY_CLASSES.find(file.filename().string()); if (it != BATTERY_CLASSES.end()) { info.flags |= it->second; } // Check if device has any batteries. std::vector<std::filesystem::path> batteryPaths = findSysfsNodes(sysfsRootPath.value(), SysfsClass::POWER_SUPPLY); // We only support single battery for an input device, if multiple batteries exist only the // first one is supported. if (batteryPaths.empty()) { // Set path to be empty sysfsBatteryPath = std::nullopt; return false; } // If a battery exists sysfsBatteryPath = batteryPaths[0]; return true; batteryInfos.insert_or_assign(info.id, info); ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str()); } return !batteryInfos.empty(); } // Check the sysfs path for any input device lights, returns true if lights found. bool EventHub::Device::configureLightsLocked() { if (!sysfsRootPath.has_value()) { return false; } bool EventHub::MiscDevice::configureLightsLocked() { nextLightId = 0; // Check if device has any lights. const auto& paths = findSysfsNodes(sysfsRootPath.value(), SysfsClass::LEDS); const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS); for (const auto& nodePath : paths) { RawLightInfo info; info.id = ++nextLightId; Loading Loading @@ -599,6 +617,7 @@ bool EventHub::Device::configureLightsLocked() { } } lightInfos.insert_or_assign(info.id, info); ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str()); } return !lightInfos.empty(); } Loading Loading @@ -963,42 +982,92 @@ base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int3 return Errorf("Device not found or device has no key layout."); } const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { // Gets the battery info map from battery ID to RawBatteryInfo of the miscellaneous device // associated with the device ID. Returns an empty map if no miscellaneous device found. const std::unordered_map<int32_t, RawBatteryInfo>& EventHub::getBatteryInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawBatteryInfo> EMPTY_BATTERY_INFO = {}; Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return EMPTY_BATTERY_INFO; } auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { return EMPTY_BATTERY_INFO; } return it->second->batteryInfos; } const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) { std::scoped_lock _l(mLock); std::vector<int32_t> batteryIds; for (const auto [id, info] : getBatteryInfoLocked(deviceId)) { batteryIds.push_back(id); } return batteryIds; } std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, int32_t batteryId) { std::scoped_lock _l(mLock); const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it != infos.end()) { return it->second; } return std::nullopt; } // Gets the light info map from light ID to RawLightInfo of the miscellaneous device associated // with the deivice ID. Returns an empty map if no miscellaneous device found. const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {}; Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return EMPTY_LIGHT_INFO; } auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { return EMPTY_LIGHT_INFO; } return it->second->lightInfos; } const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { std::scoped_lock _l(mLock); std::vector<int32_t> lightIds; if (device != nullptr) { for (const auto [id, info] : device->lightInfos) { for (const auto [id, info] : getLightInfoLocked(deviceId)) { lightIds.push_back(id); } } return lightIds; } std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device != nullptr) { auto it = device->lightInfos.find(lightId); if (it != device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto it = infos.find(lightId); if (it != infos.end()) { return it->second; } } return std::nullopt; } std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return std::nullopt; } auto it = device->lightInfos.find(lightId); if (it == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto it = infos.find(lightId); if (it == infos.end()) { return std::nullopt; } std::string buffer; Loading @@ -1013,13 +1082,9 @@ std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensi int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return std::nullopt; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { return std::nullopt; } Loading Loading @@ -1056,14 +1121,10 @@ std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensi void EventHub::setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { ALOGE("Device Id %d does not exist", deviceId); return; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { ALOGE("Light Id %d does not exist.", lightId); const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { ALOGE("%s lightId %d not found ", __func__, lightId); return; } Loading @@ -1078,13 +1139,9 @@ void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map<LightColor, int32_t> intensities) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { ALOGE("Device Id %d does not exist", deviceId); return; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { ALOGE("Light Id %d does not exist.", lightId); return; } Loading Loading @@ -1352,51 +1409,56 @@ EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const { return nullptr; } std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const { std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId, int32_t batteryId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); std::string buffer; if (device == nullptr || !device->sysfsBatteryPath.has_value()) { const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it == infos.end()) { return std::nullopt; } std::string buffer; // Some devices report battery capacity as an integer through the "capacity" file if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity", &buffer)) { if (base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::CAPACITY), &buffer)) { return std::stoi(base::Trim(buffer)); } // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX // These values are taken from kernel source code include/linux/power_supply.h if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity_level", &buffer)) { if (base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::CAPACITY_LEVEL), &buffer)) { // Remove any white space such as trailing new line const auto it = BATTERY_LEVEL.find(base::Trim(buffer)); if (it != BATTERY_LEVEL.end()) { return it->second; const auto levelIt = BATTERY_LEVEL.find(base::Trim(buffer)); if (levelIt != BATTERY_LEVEL.end()) { return levelIt->second; } } return std::nullopt; } std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const { std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId, int32_t batteryId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); std::string buffer; if (device == nullptr || !device->sysfsBatteryPath.has_value()) { const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it == infos.end()) { return std::nullopt; } std::string buffer; if (!base::ReadFileToString(device->sysfsBatteryPath.value() / "status", &buffer)) { if (!base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::STATUS), &buffer)) { ALOGE("Failed to read sysfs battery info: %s", strerror(errno)); return std::nullopt; } // Remove white space like trailing new line const auto it = BATTERY_STATUS.find(base::Trim(buffer)); if (it != BATTERY_STATUS.end()) { return it->second; const auto statusIt = BATTERY_STATUS.find(base::Trim(buffer)); if (statusIt != BATTERY_STATUS.end()) { return statusIt->second; } return std::nullopt; Loading Loading @@ -1879,11 +1941,24 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { // Load the configuration file for the device. device->loadConfigurationLocked(); // Grab the device's sysfs path device->sysfsRootPath = getSysfsRootPath(devicePath.c_str()); // find related components bool hasBattery = device->configureBatteryLocked(); bool hasLights = device->configureLightsLocked(); bool hasBattery = false; bool hasLights = false; // Check the sysfs root path std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str()); if (sysfsRootPath.has_value()) { std::shared_ptr<MiscDevice> miscDevice; auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { miscDevice = std::make_shared<MiscDevice>(sysfsRootPath.value()); } else { miscDevice = it->second; } hasBattery = miscDevice->configureBatteryLocked(); hasLights = miscDevice->configureLightsLocked(); device->miscDevice = miscDevice; mMiscDevices.insert_or_assign(device->identifier.descriptor, std::move(miscDevice)); } // Figure out the kinds of events the device reports. device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask); Loading Loading @@ -2254,6 +2329,12 @@ void EventHub::closeDeviceLocked(Device& device) { mClosingDevices.push_back(std::move(mDevices[device.id])); mDevices.erase(device.id); // If all devices with the descriptor have been removed then the miscellaneous device should // be removed too. std::string descriptor = device.identifier.descriptor; if (getDeviceByDescriptorLocked(descriptor) == nullptr) { mMiscDevices.erase(descriptor); } } status_t EventHub::readNotifyLocked() { Loading services/inputflinger/reader/InputDevice.cpp +20 −35 Original line number Diff line number Diff line Loading @@ -21,13 +21,12 @@ #include <input/Flags.h> #include <algorithm> #include "BatteryInputMapper.h" #include "CursorInputMapper.h" #include "ExternalStylusInputMapper.h" #include "InputController.h" #include "InputReaderContext.h" #include "JoystickInputMapper.h" #include "KeyboardInputMapper.h" #include "LightInputMapper.h" #include "MultiTouchInputMapper.h" #include "RotaryEncoderInputMapper.h" #include "SensorInputMapper.h" Loading Loading @@ -131,6 +130,9 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) { } for_each_mapper([&dump](InputMapper& mapper) { mapper.dump(dump); }); if (mController) { mController->dump(dump); } } void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { Loading Loading @@ -162,22 +164,10 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr)); } // Battery-like devices. Only one battery mapper for each EventHub device. if (classes.test(InputDeviceClass::BATTERY)) { InputDeviceInfo deviceInfo; getDeviceInfo(&deviceInfo); if (!deviceInfo.hasBattery()) { mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr)); } } // Light-containing devices. Only one light mapper for each EventHub device. if (classes.test(InputDeviceClass::LIGHT)) { InputDeviceInfo deviceInfo; getDeviceInfo(&deviceInfo); if (deviceInfo.getLightIds().empty()) { mappers.push_back(std::make_unique<LightInputMapper>(*contextPtr)); } // Battery-like devices or light-containing devices. // InputController will be created with associated EventHub device. if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) { mController = std::make_unique<InputController>(*contextPtr); } // Keyboard-like devices. Loading Loading @@ -409,6 +399,10 @@ void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) { mHasMic); for_each_mapper( [outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(outDeviceInfo); }); if (mController) { mController->populateDeviceInfo(outDeviceInfo); } } int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { Loading Loading @@ -510,39 +504,30 @@ void InputDevice::cancelTouch(nsecs_t when, nsecs_t readTime) { for_each_mapper([when, readTime](InputMapper& mapper) { mapper.cancelTouch(when, readTime); }); } // TODO b/180733860 support multiple battery in API and remove this. constexpr int32_t DEFAULT_BATTERY_ID = 1; std::optional<int32_t> InputDevice::getBatteryCapacity() { return first_in_mappers<int32_t>( [](InputMapper& mapper) { return mapper.getBatteryCapacity(); }); return mController ? mController->getBatteryCapacity(DEFAULT_BATTERY_ID) : std::nullopt; } std::optional<int32_t> InputDevice::getBatteryStatus() { return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); }); return mController ? mController->getBatteryStatus(DEFAULT_BATTERY_ID) : std::nullopt; } bool InputDevice::setLightColor(int32_t lightId, int32_t color) { bool success = true; for_each_mapper([&success, lightId, color](InputMapper& mapper) { success &= mapper.setLightColor(lightId, color); }); return success; return mController ? mController->setLightColor(lightId, color) : false; } bool InputDevice::setLightPlayerId(int32_t lightId, int32_t playerId) { bool success = true; for_each_mapper([&success, lightId, playerId](InputMapper& mapper) { success &= mapper.setLightPlayerId(lightId, playerId); }); return success; return mController ? mController->setLightPlayerId(lightId, playerId) : false; } std::optional<int32_t> InputDevice::getLightColor(int32_t lightId) { return first_in_mappers<int32_t>( [lightId](InputMapper& mapper) { return mapper.getLightColor(lightId); }); return mController ? mController->getLightColor(lightId) : std::nullopt; } std::optional<int32_t> InputDevice::getLightPlayerId(int32_t lightId) { return first_in_mappers<int32_t>( [lightId](InputMapper& mapper) { return mapper.getLightPlayerId(lightId); }); return mController ? mController->getLightPlayerId(lightId) : std::nullopt; } int32_t InputDevice::getMetaState() { Loading Loading
include/input/InputDevice.h +11 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,14 @@ struct InputDeviceLightInfo { int32_t ordinal; }; struct InputDeviceBatteryInfo { explicit InputDeviceBatteryInfo(std::string name, int32_t id) : name(name), id(id) {} // Name string of the battery. std::string name; // Battery id int32_t id; }; /* * Describes the characteristics and capabilities of an input device. */ Loading Loading @@ -219,6 +227,7 @@ public: float min, float max, float flat, float fuzz, float resolution); void addMotionRange(const MotionRange& range); void addSensorInfo(const InputDeviceSensorInfo& info); void addBatteryInfo(const InputDeviceBatteryInfo& info); void addLightInfo(const InputDeviceLightInfo& info); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } Loading Loading @@ -276,6 +285,8 @@ private: std::unordered_map<InputDeviceSensorType, InputDeviceSensorInfo> mSensors; /* Map from light ID to light info */ std::unordered_map<int32_t, InputDeviceLightInfo> mLights; /* Map from battery ID to battery info */ std::unordered_map<int32_t, InputDeviceBatteryInfo> mBatteries; }; /* Types of input device configuration files. */ Loading
libs/input/InputDevice.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -231,6 +231,13 @@ void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) { mSensors.insert_or_assign(info.type, info); } void InputDeviceInfo::addBatteryInfo(const InputDeviceBatteryInfo& info) { if (mBatteries.find(info.id) != mBatteries.end()) { ALOGW("Battery id %d already exists, will be replaced by new battery added.", info.id); } mBatteries.insert_or_assign(info.id, info); } void InputDeviceInfo::addLightInfo(const InputDeviceLightInfo& info) { if (mLights.find(info.id) != mLights.end()) { ALOGW("Light id %d already exists, will be replaced by new light added.", info.id); Loading
services/inputflinger/reader/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ package { cc_library_headers { name: "libinputreader_headers", export_include_dirs: [ "controller", "include", "mapper", "mapper/accumulator", Loading @@ -35,17 +36,16 @@ filegroup { srcs: [ "EventHub.cpp", "InputDevice.cpp", "controller/InputController.cpp", "mapper/accumulator/CursorButtonAccumulator.cpp", "mapper/accumulator/CursorScrollAccumulator.cpp", "mapper/accumulator/SingleTouchMotionAccumulator.cpp", "mapper/accumulator/TouchButtonAccumulator.cpp", "mapper/BatteryInputMapper.cpp", "mapper/CursorInputMapper.cpp", "mapper/ExternalStylusInputMapper.cpp", "mapper/InputMapper.cpp", "mapper/JoystickInputMapper.cpp", "mapper/KeyboardInputMapper.cpp", "mapper/LightInputMapper.cpp", "mapper/MultiTouchInputMapper.cpp", "mapper/RotaryEncoderInputMapper.cpp", "mapper/SensorInputMapper.cpp", Loading
services/inputflinger/reader/EventHub.cpp +167 −86 Original line number Diff line number Diff line Loading @@ -70,6 +70,20 @@ static const char* VIDEO_DEVICE_PATH = "/dev"; static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0; static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1; // Mapping for input battery class node IDs lookup. // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt static const std::unordered_map<std::string, InputBatteryClass> BATTERY_CLASSES = {{"capacity", InputBatteryClass::CAPACITY}, {"capacity_level", InputBatteryClass::CAPACITY_LEVEL}, {"status", InputBatteryClass::STATUS}}; // Mapping for input battery class node names lookup. // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt static const std::unordered_map<InputBatteryClass, std::string> BATTERY_NODES = {{InputBatteryClass::CAPACITY, "capacity"}, {InputBatteryClass::CAPACITY_LEVEL, "capacity_level"}, {InputBatteryClass::STATUS, "status"}}; // must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c static const std::unordered_map<std::string, int32_t> BATTERY_STATUS = {{"Unknown", BATTERY_STATUS_UNKNOWN}, Loading Loading @@ -349,7 +363,7 @@ EventHub::Device::Device(int fd, int32_t id, const std::string& path, virtualKeyMap(nullptr), ffEffectPlaying(false), ffEffectId(-1), nextLightId(0), miscDevice(nullptr), controllerNumber(0), enabled(true), isVirtual(fd < 0) {} Loading Loading @@ -540,32 +554,36 @@ status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const { } // Check the sysfs path for any input device batteries, returns true if battery found. bool EventHub::Device::configureBatteryLocked() { if (!sysfsRootPath.has_value()) { return false; bool EventHub::MiscDevice::configureBatteryLocked() { nextBatteryId = 0; // Check if device has any battery. const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY); for (const auto& nodePath : paths) { RawBatteryInfo info; info.id = ++nextBatteryId; info.path = nodePath; info.name = nodePath.filename(); // Scan the path for all the files // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt const auto& files = allFilesInPath(nodePath); for (const auto& file : files) { const auto it = BATTERY_CLASSES.find(file.filename().string()); if (it != BATTERY_CLASSES.end()) { info.flags |= it->second; } // Check if device has any batteries. std::vector<std::filesystem::path> batteryPaths = findSysfsNodes(sysfsRootPath.value(), SysfsClass::POWER_SUPPLY); // We only support single battery for an input device, if multiple batteries exist only the // first one is supported. if (batteryPaths.empty()) { // Set path to be empty sysfsBatteryPath = std::nullopt; return false; } // If a battery exists sysfsBatteryPath = batteryPaths[0]; return true; batteryInfos.insert_or_assign(info.id, info); ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str()); } return !batteryInfos.empty(); } // Check the sysfs path for any input device lights, returns true if lights found. bool EventHub::Device::configureLightsLocked() { if (!sysfsRootPath.has_value()) { return false; } bool EventHub::MiscDevice::configureLightsLocked() { nextLightId = 0; // Check if device has any lights. const auto& paths = findSysfsNodes(sysfsRootPath.value(), SysfsClass::LEDS); const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS); for (const auto& nodePath : paths) { RawLightInfo info; info.id = ++nextLightId; Loading Loading @@ -599,6 +617,7 @@ bool EventHub::Device::configureLightsLocked() { } } lightInfos.insert_or_assign(info.id, info); ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str()); } return !lightInfos.empty(); } Loading Loading @@ -963,42 +982,92 @@ base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int3 return Errorf("Device not found or device has no key layout."); } const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { // Gets the battery info map from battery ID to RawBatteryInfo of the miscellaneous device // associated with the device ID. Returns an empty map if no miscellaneous device found. const std::unordered_map<int32_t, RawBatteryInfo>& EventHub::getBatteryInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawBatteryInfo> EMPTY_BATTERY_INFO = {}; Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return EMPTY_BATTERY_INFO; } auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { return EMPTY_BATTERY_INFO; } return it->second->batteryInfos; } const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) { std::scoped_lock _l(mLock); std::vector<int32_t> batteryIds; for (const auto [id, info] : getBatteryInfoLocked(deviceId)) { batteryIds.push_back(id); } return batteryIds; } std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, int32_t batteryId) { std::scoped_lock _l(mLock); const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it != infos.end()) { return it->second; } return std::nullopt; } // Gets the light info map from light ID to RawLightInfo of the miscellaneous device associated // with the deivice ID. Returns an empty map if no miscellaneous device found. const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {}; Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return EMPTY_LIGHT_INFO; } auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { return EMPTY_LIGHT_INFO; } return it->second->lightInfos; } const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { std::scoped_lock _l(mLock); std::vector<int32_t> lightIds; if (device != nullptr) { for (const auto [id, info] : device->lightInfos) { for (const auto [id, info] : getLightInfoLocked(deviceId)) { lightIds.push_back(id); } } return lightIds; } std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device != nullptr) { auto it = device->lightInfos.find(lightId); if (it != device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto it = infos.find(lightId); if (it != infos.end()) { return it->second; } } return std::nullopt; } std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return std::nullopt; } auto it = device->lightInfos.find(lightId); if (it == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto it = infos.find(lightId); if (it == infos.end()) { return std::nullopt; } std::string buffer; Loading @@ -1013,13 +1082,9 @@ std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensi int32_t deviceId, int32_t lightId) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { return std::nullopt; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { return std::nullopt; } Loading Loading @@ -1056,14 +1121,10 @@ std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensi void EventHub::setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { ALOGE("Device Id %d does not exist", deviceId); return; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { ALOGE("Light Id %d does not exist.", lightId); const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { ALOGE("%s lightId %d not found ", __func__, lightId); return; } Loading @@ -1078,13 +1139,9 @@ void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map<LightColor, int32_t> intensities) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { ALOGE("Device Id %d does not exist", deviceId); return; } auto lightIt = device->lightInfos.find(lightId); if (lightIt == device->lightInfos.end()) { const auto infos = getLightInfoLocked(deviceId); auto lightIt = infos.find(lightId); if (lightIt == infos.end()) { ALOGE("Light Id %d does not exist.", lightId); return; } Loading Loading @@ -1352,51 +1409,56 @@ EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const { return nullptr; } std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const { std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId, int32_t batteryId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); std::string buffer; if (device == nullptr || !device->sysfsBatteryPath.has_value()) { const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it == infos.end()) { return std::nullopt; } std::string buffer; // Some devices report battery capacity as an integer through the "capacity" file if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity", &buffer)) { if (base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::CAPACITY), &buffer)) { return std::stoi(base::Trim(buffer)); } // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX // These values are taken from kernel source code include/linux/power_supply.h if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity_level", &buffer)) { if (base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::CAPACITY_LEVEL), &buffer)) { // Remove any white space such as trailing new line const auto it = BATTERY_LEVEL.find(base::Trim(buffer)); if (it != BATTERY_LEVEL.end()) { return it->second; const auto levelIt = BATTERY_LEVEL.find(base::Trim(buffer)); if (levelIt != BATTERY_LEVEL.end()) { return levelIt->second; } } return std::nullopt; } std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const { std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId, int32_t batteryId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); std::string buffer; if (device == nullptr || !device->sysfsBatteryPath.has_value()) { const auto infos = getBatteryInfoLocked(deviceId); auto it = infos.find(batteryId); if (it == infos.end()) { return std::nullopt; } std::string buffer; if (!base::ReadFileToString(device->sysfsBatteryPath.value() / "status", &buffer)) { if (!base::ReadFileToString(it->second.path / BATTERY_NODES.at(InputBatteryClass::STATUS), &buffer)) { ALOGE("Failed to read sysfs battery info: %s", strerror(errno)); return std::nullopt; } // Remove white space like trailing new line const auto it = BATTERY_STATUS.find(base::Trim(buffer)); if (it != BATTERY_STATUS.end()) { return it->second; const auto statusIt = BATTERY_STATUS.find(base::Trim(buffer)); if (statusIt != BATTERY_STATUS.end()) { return statusIt->second; } return std::nullopt; Loading Loading @@ -1879,11 +1941,24 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { // Load the configuration file for the device. device->loadConfigurationLocked(); // Grab the device's sysfs path device->sysfsRootPath = getSysfsRootPath(devicePath.c_str()); // find related components bool hasBattery = device->configureBatteryLocked(); bool hasLights = device->configureLightsLocked(); bool hasBattery = false; bool hasLights = false; // Check the sysfs root path std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str()); if (sysfsRootPath.has_value()) { std::shared_ptr<MiscDevice> miscDevice; auto it = mMiscDevices.find(device->identifier.descriptor); if (it == mMiscDevices.end()) { miscDevice = std::make_shared<MiscDevice>(sysfsRootPath.value()); } else { miscDevice = it->second; } hasBattery = miscDevice->configureBatteryLocked(); hasLights = miscDevice->configureLightsLocked(); device->miscDevice = miscDevice; mMiscDevices.insert_or_assign(device->identifier.descriptor, std::move(miscDevice)); } // Figure out the kinds of events the device reports. device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask); Loading Loading @@ -2254,6 +2329,12 @@ void EventHub::closeDeviceLocked(Device& device) { mClosingDevices.push_back(std::move(mDevices[device.id])); mDevices.erase(device.id); // If all devices with the descriptor have been removed then the miscellaneous device should // be removed too. std::string descriptor = device.identifier.descriptor; if (getDeviceByDescriptorLocked(descriptor) == nullptr) { mMiscDevices.erase(descriptor); } } status_t EventHub::readNotifyLocked() { Loading
services/inputflinger/reader/InputDevice.cpp +20 −35 Original line number Diff line number Diff line Loading @@ -21,13 +21,12 @@ #include <input/Flags.h> #include <algorithm> #include "BatteryInputMapper.h" #include "CursorInputMapper.h" #include "ExternalStylusInputMapper.h" #include "InputController.h" #include "InputReaderContext.h" #include "JoystickInputMapper.h" #include "KeyboardInputMapper.h" #include "LightInputMapper.h" #include "MultiTouchInputMapper.h" #include "RotaryEncoderInputMapper.h" #include "SensorInputMapper.h" Loading Loading @@ -131,6 +130,9 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) { } for_each_mapper([&dump](InputMapper& mapper) { mapper.dump(dump); }); if (mController) { mController->dump(dump); } } void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { Loading Loading @@ -162,22 +164,10 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr)); } // Battery-like devices. Only one battery mapper for each EventHub device. if (classes.test(InputDeviceClass::BATTERY)) { InputDeviceInfo deviceInfo; getDeviceInfo(&deviceInfo); if (!deviceInfo.hasBattery()) { mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr)); } } // Light-containing devices. Only one light mapper for each EventHub device. if (classes.test(InputDeviceClass::LIGHT)) { InputDeviceInfo deviceInfo; getDeviceInfo(&deviceInfo); if (deviceInfo.getLightIds().empty()) { mappers.push_back(std::make_unique<LightInputMapper>(*contextPtr)); } // Battery-like devices or light-containing devices. // InputController will be created with associated EventHub device. if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) { mController = std::make_unique<InputController>(*contextPtr); } // Keyboard-like devices. Loading Loading @@ -409,6 +399,10 @@ void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) { mHasMic); for_each_mapper( [outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(outDeviceInfo); }); if (mController) { mController->populateDeviceInfo(outDeviceInfo); } } int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { Loading Loading @@ -510,39 +504,30 @@ void InputDevice::cancelTouch(nsecs_t when, nsecs_t readTime) { for_each_mapper([when, readTime](InputMapper& mapper) { mapper.cancelTouch(when, readTime); }); } // TODO b/180733860 support multiple battery in API and remove this. constexpr int32_t DEFAULT_BATTERY_ID = 1; std::optional<int32_t> InputDevice::getBatteryCapacity() { return first_in_mappers<int32_t>( [](InputMapper& mapper) { return mapper.getBatteryCapacity(); }); return mController ? mController->getBatteryCapacity(DEFAULT_BATTERY_ID) : std::nullopt; } std::optional<int32_t> InputDevice::getBatteryStatus() { return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); }); return mController ? mController->getBatteryStatus(DEFAULT_BATTERY_ID) : std::nullopt; } bool InputDevice::setLightColor(int32_t lightId, int32_t color) { bool success = true; for_each_mapper([&success, lightId, color](InputMapper& mapper) { success &= mapper.setLightColor(lightId, color); }); return success; return mController ? mController->setLightColor(lightId, color) : false; } bool InputDevice::setLightPlayerId(int32_t lightId, int32_t playerId) { bool success = true; for_each_mapper([&success, lightId, playerId](InputMapper& mapper) { success &= mapper.setLightPlayerId(lightId, playerId); }); return success; return mController ? mController->setLightPlayerId(lightId, playerId) : false; } std::optional<int32_t> InputDevice::getLightColor(int32_t lightId) { return first_in_mappers<int32_t>( [lightId](InputMapper& mapper) { return mapper.getLightColor(lightId); }); return mController ? mController->getLightColor(lightId) : std::nullopt; } std::optional<int32_t> InputDevice::getLightPlayerId(int32_t lightId) { return first_in_mappers<int32_t>( [lightId](InputMapper& mapper) { return mapper.getLightPlayerId(lightId); }); return mController ? mController->getLightPlayerId(lightId) : std::nullopt; } int32_t InputDevice::getMetaState() { Loading