Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e38502d3 authored by Himanshu Rawat's avatar Himanshu Rawat
Browse files

Break from UHID polling early if HID host disconnects 

Bug: 309649833
Bug: 319846147
Test: manual | Connect/disconnect HID device from UI while continuously generating reports from the HID device
Test: m packages/modules/Bluetooth

Change-Id: I19103cf8312aa3b0082d076e6351ce14e44c38cb
parent 275e5735
Loading
Loading
Loading
Loading
+40 −14
Original line number Diff line number Diff line
@@ -297,6 +297,36 @@ static bool uhid_fd_open(btif_hh_device_t* p_dev) {
  return true;
}

static int uhid_fd_poll(btif_hh_device_t* p_dev,
                        std::array<struct pollfd, 1>& pfds) {
  int ret = 0;
  int counter = 0;

  do {
    if (IS_FLAG_ENABLED(break_uhid_polling_early) && !p_dev->hh_keep_polling) {
      log::debug("Polling stopped");
      return -1;
    }

    if (counter++ > BTA_HH_UHID_INTERRUPT_COUNT_MAX) {
      log::error("Polling interrupted consecutively {} times",
                 BTA_HH_UHID_INTERRUPT_COUNT_MAX);
      return -1;
    }

    ret = poll(pfds.data(), pfds.size(), BTA_HH_UHID_POLL_PERIOD_MS);
  } while (ret == -1 && errno == EINTR);

  if (!IS_FLAG_ENABLED(break_uhid_polling_early)) {
    if (ret == 0) {
      log::debug("Polling timed out, attempt to read (old behavior)");
      return 1;
    }
  }

  return ret;
}

/*******************************************************************************
 *
 * Function btif_hh_poll_event_thread
@@ -308,7 +338,7 @@ static bool uhid_fd_open(btif_hh_device_t* p_dev) {
 ******************************************************************************/
static void* btif_hh_poll_event_thread(void* arg) {
  btif_hh_device_t* p_dev = (btif_hh_device_t*)arg;
  struct pollfd pfds[1];
  std::array<struct pollfd, 1> pfds;
  pid_t pid = gettid();

  // This thread is created by bt_main_thread with RT priority. Lower the thread
@@ -334,26 +364,22 @@ static void* btif_hh_poll_event_thread(void* arg) {
  uhid_set_non_blocking(p_dev->fd);

  while (p_dev->hh_keep_polling) {
    int ret;
    int counter = 0;

    do {
      if (counter++ > BTA_HH_UHID_INTERRUPT_COUNT_MAX) {
        log::error("Polling interrupted");
        break;
      }
      ret = poll(pfds, 1, BTA_HH_UHID_POLL_PERIOD_MS);
    } while (ret == -1 && errno == EINTR);
    int ret = uhid_fd_poll(p_dev, pfds);

    if (ret < 0) {
      log::error("Cannot poll for fds: {}\n", strerror(errno));
      break;
    } else if (ret == 0) {
      /* Poll timeout, poll again */
      continue;
    }

    /* At least one of the fd is ready */
    if (pfds[0].revents & POLLIN) {
      log::verbose("POLLIN");
      ret = uhid_read_event(p_dev);
      if (ret != 0) {
        log::error("Unhandled UHID event");
      int result = uhid_read_event(p_dev);
      if (result != 0) {
        log::error("Unhandled UHID event, error: {}", result);
        break;
      }
    }