@@ -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) {
16191619std::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
27402785void EventHub::createVirtualKeyboardLocked () {
0 commit comments