@@ -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.
@@ -2700,8 +2729,10 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {
27002729
27012730 // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid
27022731 // 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.
27032734 std::map<std::shared_ptr<const AssociatedDevice>, bool /* changed*/ > testedDevices;
2704- auto isAssociatedDeviceChanged = [&testedDevices, &changedNodes](const Device& dev) {
2735+ auto shouldReopenDevice = [&testedDevices, &changedNodes](const Device& dev) {
27052736 if (!dev.associatedDevice ) {
27062737 return false ;
27072738 }
@@ -2730,27 +2761,25 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {
27302761 return changed;
27312762 };
27322763
2733- std::set<Device*> devicesToReopen;
2734-
2735- // 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.
27362766 for (const auto & dev : mOpeningDevices ) {
2737- if (isAssociatedDeviceChanged (*dev)) {
2738- 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);
27392773 }
27402774 }
27412775
2742- // 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.
27432778 for (const auto & [id, dev] : mDevices ) {
2744- if (isAssociatedDeviceChanged (*dev)) {
2745- devicesToReopen. emplace (dev. get () );
2779+ if (shouldReopenDevice (*dev)) {
2780+ mDeviceIdsToReopen . emplace_back (dev-> id );
27462781 }
27472782 }
2748-
2749- for (auto * device : devicesToReopen) {
2750- const auto path = device->path ;
2751- closeDeviceLocked (*device); // The Device object is deleted by this function.
2752- openDeviceLocked (path);
2753- }
27542783}
27552784
27562785void EventHub::createVirtualKeyboardLocked () {
0 commit comments