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

Commit c73a64d4 authored by Himanshu Rawat's avatar Himanshu Rawat Committed by Gerrit Code Review
Browse files

Merge changes I62b501ad,I19103cf8 into main

* changes:
  HidHost: Refactor uhid thread entry function
  Break from UHID polling early if HID host disconnects 
parents df63ea05 06071ced
Loading
Loading
Loading
Loading
+81 −43
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ const char* dev_path = "/dev/uhid";
static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
#define BTA_HH_CACHE_REPORT_VERSION 1
#define THREAD_NORMAL_PRIORITY 0
#define BT_HH_THREAD "bt_hh_thread"
#define BT_HH_THREAD_PREFIX "bt_hh_"
#define BTA_HH_UHID_POLL_PERIOD_MS 50
/* Max number of polling interrupt allowed */
#define BTA_HH_UHID_INTERRUPT_COUNT_MAX 100
@@ -295,67 +295,105 @@ static bool uhid_fd_open(btif_hh_device_t* p_dev) {
  return true;
}

/*******************************************************************************
 *
 * Function btif_hh_poll_event_thread
 *
 * Description the polling thread which polls for event from UHID driver
 *
 * Returns void
 *
 ******************************************************************************/
static void* btif_hh_poll_event_thread(void* arg) {
  btif_hh_device_t* p_dev = (btif_hh_device_t*)arg;
  struct pollfd pfds[1];
  pid_t pid = gettid();
static int uhid_fd_poll(btif_hh_device_t* p_dev,
                        std::array<struct pollfd, 1>& pfds) {
  int ret = 0;
  int counter = 0;

  // This thread is created by bt_main_thread with RT priority. Lower the thread
  // priority here since the tasks in this thread is not timing critical.
  struct sched_param sched_params;
  sched_params.sched_priority = THREAD_NORMAL_PRIORITY;
  if (sched_setscheduler(pid, SCHED_OTHER, &sched_params)) {
    log::error("Failed to set thread priority to normal: {}", strerror(errno));
    p_dev->hh_poll_thread_id = -1;
    p_dev->hh_keep_polling = 0;
    uhid_fd_close(p_dev);
    return 0;
  do {
    if (IS_FLAG_ENABLED(break_uhid_polling_early) && !p_dev->hh_keep_polling) {
      log::debug("Polling stopped");
      return -1;
    }

  pthread_setname_np(pthread_self(), BT_HH_THREAD);
  log::debug("Host hid polling thread created name:{} pid:{} fd:{}",
             BT_HH_THREAD, pid, p_dev->fd);
    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;
}

static void uhid_start_polling(btif_hh_device_t* p_dev) {
  std::array<struct pollfd, 1> pfds = {};
  pfds[0].fd = p_dev->fd;
  pfds[0].events = POLLIN;

  // Set the uhid fd as non-blocking to ensure we never block the BTU thread
  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;
      }
    }
  }
}

static bool uhid_configure_thread(btif_hh_device_t* p_dev) {
  pid_t pid = gettid();
  // This thread is created by bt_main_thread with RT priority. Lower the thread
  // priority here since the tasks in this thread is not timing critical.
  struct sched_param sched_params;
  sched_params.sched_priority = THREAD_NORMAL_PRIORITY;
  if (sched_setscheduler(pid, SCHED_OTHER, &sched_params)) {
    log::error("Failed to set thread priority to normal: {}", strerror(errno));
    return false;
  }

  // Change the name of thread
  char thread_name[16] = {};
  sprintf(thread_name, BT_HH_THREAD_PREFIX "%02x:%02x",
          p_dev->link_spec.addrt.bda.address[4],
          p_dev->link_spec.addrt.bda.address[5]);
  pthread_setname_np(pthread_self(), thread_name);
  log::debug("Host hid polling thread created name:{} pid:{} fd:{}",
             thread_name, pid, p_dev->fd);

  // Set the uhid fd as non-blocking to ensure we never block the BTU thread
  uhid_set_non_blocking(p_dev->fd);

  return true;
}

/*******************************************************************************
 *
 * Function btif_hh_poll_event_thread
 *
 * Description the polling thread which polls for event from UHID driver
 *
 * Returns void
 *
 ******************************************************************************/
static void* btif_hh_poll_event_thread(void* arg) {
  btif_hh_device_t* p_dev = (btif_hh_device_t*)arg;

  if (uhid_configure_thread(p_dev)) {
    uhid_start_polling(p_dev);
  }

  /* Todo: Disconnect if loop exited due to a failure */
  log::info("Polling thread stopped for device {}",
+6 −6
Original line number Diff line number Diff line
@@ -2181,12 +2181,12 @@ void DumpsysHid(int fd) {
  for (unsigned i = 0; i < BTIF_HH_MAX_HID; i++) {
    const btif_hh_device_t* p_dev = &btif_hh_cb.devices[i];
    if (p_dev->link_spec.addrt.bda != RawAddress::kEmpty) {
      LOG_DUMPSYS(fd, "  %u: addr:%s fd:%d state:%s ready:%s thread_id:%d", i,
                  p_dev->link_spec.ToRedactedStringForLogging().c_str(),
                  p_dev->fd,
      LOG_DUMPSYS(
          fd, "  %u: addr:%s fd:%d state:%s ready:%s thread_id:%d handle:%d", i,
          p_dev->link_spec.ToRedactedStringForLogging().c_str(), p_dev->fd,
          bthh_connection_state_text(p_dev->dev_status).c_str(),
          (p_dev->ready_for_data) ? ("T") : ("F"),
                  static_cast<int>(p_dev->hh_poll_thread_id));
          static_cast<int>(p_dev->hh_poll_thread_id), p_dev->dev_handle);
    }
  }
  for (unsigned i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {