Skip to content

Commit 7238239

Browse files
prabirmspAndroid (Google) Code Review
authored andcommitted
Merge changes from topic "getSysfsRootPath" into main
* changes: EventHub: Re-open Devices serially when AssociatedDevice changes InputReader: Add getter API for the sysfs node path of an InputDevice
2 parents 026a167 + a8f8854 commit 7238239

File tree

13 files changed

+170
-62
lines changed

13 files changed

+170
-62
lines changed

services/inputflinger/include/InputReaderBase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ class InputReaderInterface {
443443
/* Get the Bluetooth address of an input device, if known. */
444444
virtual std::optional<std::string> getBluetoothAddress(int32_t deviceId) const = 0;
445445

446+
/* Gets the sysfs root path for this device. Returns an empty path if there is none. */
447+
virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0;
448+
446449
/* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */
447450
virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
448451

services/inputflinger/reader/EventHub.cpp

Lines changed: 106 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ static nsecs_t processEventTimestamp(const struct input_event& event) {
246246
/**
247247
* Returns the sysfs root path of the input device.
248248
*/
249-
static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) {
249+
static std::optional<std::filesystem::path> getSysfsRootForEvdevDevicePath(const char* devicePath) {
250250
std::error_code errorCode;
251251

252252
// Stat the device path to get the major and minor number of the character file
@@ -1619,7 +1619,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
16191619
std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked(
16201620
const std::filesystem::path& devicePath, const std::shared_ptr<PropertyMap>& config) const {
16211621
const std::optional<std::filesystem::path> sysfsRootPathOpt =
1622-
getSysfsRootPath(devicePath.c_str());
1622+
getSysfsRootForEvdevDevicePath(devicePath.c_str());
16231623
if (!sysfsRootPathOpt) {
16241624
return nullptr;
16251625
}
@@ -1899,58 +1899,87 @@ std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
18991899

19001900
handleSysfsNodeChangeNotificationsLocked();
19011901

1902-
// Report any devices that had last been added/removed.
1903-
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
1904-
std::unique_ptr<Device> device = std::move(*it);
1905-
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
1906-
const int32_t deviceId = (device->id == mBuiltInKeyboardId)
1907-
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
1908-
: device->id;
1909-
events.push_back({
1910-
.when = now,
1911-
.deviceId = deviceId,
1912-
.type = DEVICE_REMOVED,
1913-
});
1914-
it = mClosingDevices.erase(it);
1915-
if (events.size() == EVENT_BUFFER_SIZE) {
1916-
break;
1902+
// Use a do-while loop to ensure that we drain the closing and opening devices loop
1903+
// at least once, even if there are no devices to re-open.
1904+
do {
1905+
if (!mDeviceIdsToReopen.empty()) {
1906+
// If there are devices that need to be re-opened, ensure that we re-open them
1907+
// one at a time to send the DEVICE_REMOVED and DEVICE_ADDED notifications for
1908+
// each before moving on to the next. This is to avoid notifying all device
1909+
// removals and additions in one batch, which could cause additional unnecessary
1910+
// device added/removed notifications for merged InputDevices from InputReader.
1911+
const int32_t deviceId = mDeviceIdsToReopen.back();
1912+
mDeviceIdsToReopen.erase(mDeviceIdsToReopen.end() - 1);
1913+
if (auto it = mDevices.find(deviceId); it != mDevices.end()) {
1914+
ALOGI("Reopening input device: id=%d, name=%s", it->second->id,
1915+
it->second->identifier.name.c_str());
1916+
const auto path = it->second->path;
1917+
closeDeviceLocked(*it->second);
1918+
openDeviceLocked(path);
1919+
}
19171920
}
1918-
}
19191921

1920-
if (mNeedToScanDevices) {
1921-
mNeedToScanDevices = false;
1922-
scanDevicesLocked();
1923-
}
1924-
1925-
while (!mOpeningDevices.empty()) {
1926-
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
1927-
mOpeningDevices.pop_back();
1928-
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
1929-
const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
1930-
events.push_back({
1931-
.when = now,
1932-
.deviceId = deviceId,
1933-
.type = DEVICE_ADDED,
1934-
});
1935-
1936-
// Try to find a matching video device by comparing device names
1937-
for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
1938-
it++) {
1939-
std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
1940-
if (tryAddVideoDeviceLocked(*device, videoDevice)) {
1941-
// videoDevice was transferred to 'device'
1942-
it = mUnattachedVideoDevices.erase(it);
1922+
// Report any devices that had last been added/removed.
1923+
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
1924+
std::unique_ptr<Device> device = std::move(*it);
1925+
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id,
1926+
device->path.c_str());
1927+
const int32_t deviceId = (device->id == mBuiltInKeyboardId)
1928+
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
1929+
: device->id;
1930+
events.push_back({
1931+
.when = now,
1932+
.deviceId = deviceId,
1933+
.type = DEVICE_REMOVED,
1934+
});
1935+
it = mClosingDevices.erase(it);
1936+
if (events.size() == EVENT_BUFFER_SIZE) {
19431937
break;
19441938
}
19451939
}
19461940

1947-
auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
1948-
if (!inserted) {
1949-
ALOGW("Device id %d exists, replaced.", device->id);
1941+
if (mNeedToScanDevices) {
1942+
mNeedToScanDevices = false;
1943+
scanDevicesLocked();
19501944
}
1951-
if (events.size() == EVENT_BUFFER_SIZE) {
1952-
break;
1945+
1946+
while (!mOpeningDevices.empty()) {
1947+
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
1948+
mOpeningDevices.pop_back();
1949+
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id,
1950+
device->path.c_str());
1951+
const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
1952+
events.push_back({
1953+
.when = now,
1954+
.deviceId = deviceId,
1955+
.type = DEVICE_ADDED,
1956+
});
1957+
1958+
// Try to find a matching video device by comparing device names
1959+
for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
1960+
it++) {
1961+
std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
1962+
if (tryAddVideoDeviceLocked(*device, videoDevice)) {
1963+
// videoDevice was transferred to 'device'
1964+
it = mUnattachedVideoDevices.erase(it);
1965+
break;
1966+
}
1967+
}
1968+
1969+
auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
1970+
if (!inserted) {
1971+
ALOGW("Device id %d exists, replaced.", device->id);
1972+
}
1973+
if (events.size() == EVENT_BUFFER_SIZE) {
1974+
break;
1975+
}
19531976
}
1977+
1978+
// Perform this loop of re-opening devices so that we re-open one device at a time.
1979+
} while (!mDeviceIdsToReopen.empty());
1980+
1981+
if (events.size() == EVENT_BUFFER_SIZE) {
1982+
break;
19541983
}
19551984

19561985
// Grab the next input event.
@@ -2666,6 +2695,18 @@ status_t EventHub::disableDevice(int32_t deviceId) {
26662695
return device->disable();
26672696
}
26682697

2698+
std::filesystem::path EventHub::getSysfsRootPath(int32_t deviceId) const {
2699+
std::scoped_lock _l(mLock);
2700+
Device* device = getDeviceLocked(deviceId);
2701+
if (device == nullptr) {
2702+
ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
2703+
return {};
2704+
}
2705+
2706+
return device->associatedDevice ? device->associatedDevice->sysfsRootPath
2707+
: std::filesystem::path{};
2708+
}
2709+
26692710
// TODO(b/274755573): Shift to uevent handling on native side and remove this method
26702711
// Currently using Java UEventObserver to trigger this which uses UEvent infrastructure that uses a
26712712
// NETLINK socket to observe UEvents. We can create similar infrastructure on Eventhub side to
@@ -2688,8 +2729,10 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {
26882729

26892730
// Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid
26902731
// testing the same node multiple times.
2732+
// TODO(b/281822656): Notify InputReader separately when an AssociatedDevice changes,
2733+
// instead of needing to re-open all of Devices that are associated with it.
26912734
std::map<std::shared_ptr<const AssociatedDevice>, bool /*changed*/> testedDevices;
2692-
auto isAssociatedDeviceChanged = [&testedDevices, &changedNodes](const Device& dev) {
2735+
auto shouldReopenDevice = [&testedDevices, &changedNodes](const Device& dev) {
26932736
if (!dev.associatedDevice) {
26942737
return false;
26952738
}
@@ -2710,31 +2753,33 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {
27102753
auto reloadedDevice = AssociatedDevice(dev.associatedDevice->sysfsRootPath,
27112754
dev.associatedDevice->baseDevConfig);
27122755
const bool changed = *dev.associatedDevice != reloadedDevice;
2756+
if (changed) {
2757+
ALOGI("sysfsNodeChanged: Identified change in sysfs nodes for device: %s",
2758+
dev.identifier.name.c_str());
2759+
}
27132760
testedDevices.emplace(dev.associatedDevice, changed);
27142761
return changed;
27152762
};
27162763

2717-
std::set<Device*> devicesToReopen;
2718-
2719-
// Check in opening devices.
2764+
// Check in opening devices. These can be re-opened directly because we have not yet notified
2765+
// the Reader about these devices.
27202766
for (const auto& dev : mOpeningDevices) {
2721-
if (isAssociatedDeviceChanged(*dev)) {
2722-
devicesToReopen.emplace(dev.get());
2767+
if (shouldReopenDevice(*dev)) {
2768+
ALOGI("Reopening input device from mOpeningDevices: id=%d, name=%s", dev->id,
2769+
dev->identifier.name.c_str());
2770+
const auto path = dev->path;
2771+
closeDeviceLocked(*dev); // The Device object is deleted by this function.
2772+
openDeviceLocked(path);
27232773
}
27242774
}
27252775

2726-
// Check in already added devices.
2776+
// Check in already added devices. Add them to the re-opening list so they can be
2777+
// re-opened serially.
27272778
for (const auto& [id, dev] : mDevices) {
2728-
if (isAssociatedDeviceChanged(*dev)) {
2729-
devicesToReopen.emplace(dev.get());
2779+
if (shouldReopenDevice(*dev)) {
2780+
mDeviceIdsToReopen.emplace_back(dev->id);
27302781
}
27312782
}
2732-
2733-
for (auto* device : devicesToReopen) {
2734-
const auto path = device->path;
2735-
closeDeviceLocked(*device); // The Device object is deleted by this function.
2736-
openDeviceLocked(path);
2737-
}
27382783
}
27392784

27402785
void EventHub::createVirtualKeyboardLocked() {

services/inputflinger/reader/InputDevice.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) {
136136
} else {
137137
dump += "<none>\n";
138138
}
139+
dump += StringPrintf(INDENT2 "SysfsRootPath: %s\n",
140+
mSysfsRootPath.empty() ? "<none>" : mSysfsRootPath.c_str());
139141
dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
140142
dump += StringPrintf(INDENT2 "Sources: %s\n",
141143
inputEventSourceToString(deviceInfo.getSources()).c_str());
@@ -195,6 +197,10 @@ void InputDevice::addEmptyEventHubDevice(int32_t eventHubId) {
195197
DevicePair& devicePair = mDevices[eventHubId];
196198
devicePair.second = createMappers(*devicePair.first, readerConfig);
197199

200+
if (mSysfsRootPath.empty()) {
201+
mSysfsRootPath = devicePair.first->getSysfsRootPath();
202+
}
203+
198204
// Must change generation to flag this device as changed
199205
bumpGeneration();
200206
return out;

services/inputflinger/reader/InputReader.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,16 @@ bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId di
917917
return *associatedDisplayId == displayId;
918918
}
919919

920+
std::filesystem::path InputReader::getSysfsRootPath(int32_t deviceId) const {
921+
std::scoped_lock _l(mLock);
922+
923+
const InputDevice* device = findInputDeviceLocked(deviceId);
924+
if (!device) {
925+
return {};
926+
}
927+
return device->getSysfsRootPath();
928+
}
929+
920930
void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) {
921931
mEventHub->sysfsNodeChanged(sysfsNodePath);
922932
mEventHub->wake();

services/inputflinger/reader/include/EventHub.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ class EventHubInterface {
399399
/* Disable an input device. Closes file descriptor to that device. */
400400
virtual status_t disableDevice(int32_t deviceId) = 0;
401401

402+
/* Gets the sysfs root path for this device. Returns an empty path if there is none. */
403+
virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0;
404+
402405
/* Sysfs node changed. Reopen the Eventhub device if any new Peripheral like Light, Battery,
403406
* etc. is detected. */
404407
virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
@@ -614,6 +617,8 @@ class EventHub : public EventHubInterface {
614617

615618
status_t disableDevice(int32_t deviceId) override final;
616619

620+
std::filesystem::path getSysfsRootPath(int32_t deviceId) const override final;
621+
617622
void sysfsNodeChanged(const std::string& sysfsNodePath) override final;
618623

619624
bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override final;
@@ -810,6 +815,7 @@ class EventHub : public EventHubInterface {
810815
bool mNeedToReopenDevices;
811816
bool mNeedToScanDevices;
812817
std::vector<std::string> mExcludedDevices;
818+
std::vector<int32_t> mDeviceIdsToReopen;
813819

814820
int mEpollFd;
815821
int mINotifyFd;

services/inputflinger/reader/include/InputDevice.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class InputDevice {
8181

8282
inline virtual KeyboardType getKeyboardType() const { return mKeyboardType; }
8383

84+
inline std::filesystem::path getSysfsRootPath() const { return mSysfsRootPath; }
85+
8486
bool isEnabled();
8587

8688
void dump(std::string& dump, const std::string& eventHubDevStr);
@@ -209,6 +211,7 @@ class InputDevice {
209211
bool mHasMic;
210212
bool mDropUntilNextSync;
211213
std::optional<bool> mShouldSmoothScroll;
214+
std::filesystem::path mSysfsRootPath;
212215

213216
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
214217
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
@@ -471,6 +474,9 @@ class InputDeviceContext {
471474
inline void setKeyboardType(KeyboardType keyboardType) {
472475
return mDevice.setKeyboardType(keyboardType);
473476
}
477+
inline std::filesystem::path getSysfsRootPath() const {
478+
return mEventHub->getSysfsRootPath(mId);
479+
}
474480
inline bool setKernelWakeEnabled(bool enabled) {
475481
return mEventHub->setKernelWakeEnabled(mId, enabled);
476482
}

services/inputflinger/reader/include/InputReader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class InputReader : public InputReaderInterface {
118118

119119
std::optional<std::string> getBluetoothAddress(int32_t deviceId) const override;
120120

121+
std::filesystem::path getSysfsRootPath(int32_t deviceId) const override;
122+
121123
void sysfsNodeChanged(const std::string& sysfsNodePath) override;
122124

123125
DeviceId getLastUsedInputDeviceId() override;

services/inputflinger/tests/FakeEventHub.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,14 @@ void FakeEventHub::setSysfsRootPath(int32_t deviceId, std::string sysfsRootPath)
627627
device->sysfsRootPath = sysfsRootPath;
628628
}
629629

630+
std::filesystem::path FakeEventHub::getSysfsRootPath(int32_t deviceId) const {
631+
Device* device = getDevice(deviceId);
632+
if (device == nullptr) {
633+
return {};
634+
}
635+
return device->sysfsRootPath;
636+
}
637+
630638
void FakeEventHub::sysfsNodeChanged(const std::string& sysfsNodePath) {
631639
int32_t foundDeviceId = -1;
632640
Device* foundDevice = nullptr;

services/inputflinger/tests/FakeEventHub.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class FakeEventHub : public EventHubInterface {
222222
std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override;
223223
std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
224224
int32_t deviceId, int32_t lightId) const override;
225+
std::filesystem::path getSysfsRootPath(int32_t deviceId) const override;
225226
void sysfsNodeChanged(const std::string& sysfsNodePath) override;
226227
void dump(std::string&) const override {}
227228
void monitor() const override {}

services/inputflinger/tests/InputReader_test.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,10 @@ class InputReaderTest : public testing::Test {
611611
}
612612

613613
void addDevice(int32_t eventHubId, const std::string& name,
614-
ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
614+
ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration,
615+
std::string sysfsRootPath = "") {
615616
mFakeEventHub->addDevice(eventHubId, name, classes);
617+
mFakeEventHub->setSysfsRootPath(eventHubId, sysfsRootPath);
616618

617619
if (configuration) {
618620
mFakeEventHub->addConfigurationMap(eventHubId, configuration);
@@ -664,6 +666,18 @@ TEST_F(InputReaderTest, PolicyGetInputDevices) {
664666
ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
665667
}
666668

669+
TEST_F(InputReaderTest, GetSysfsRootPath) {
670+
constexpr std::string SYSFS_ROOT = "xyz";
671+
ASSERT_NO_FATAL_FAILURE(
672+
addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr, SYSFS_ROOT));
673+
674+
// Should also have received a notification describing the new input device.
675+
ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
676+
InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
677+
678+
ASSERT_EQ(SYSFS_ROOT, mReader->getSysfsRootPath(inputDevice.getId()).string());
679+
}
680+
667681
TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
668682
ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
669683
mFakeEventHub->setSysfsRootPath(1, "xyz");

0 commit comments

Comments
 (0)