Loading system/btif/co/bta_hh_co.cc +81 −43 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 {}", Loading system/btif/src/btif_hh.cc +6 −6 Original line number Diff line number Diff line Loading @@ -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++) { Loading Loading
system/btif/co/bta_hh_co.cc +81 −43 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 {}", Loading
system/btif/src/btif_hh.cc +6 −6 Original line number Diff line number Diff line Loading @@ -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++) { Loading