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

Commit b19f11d0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ic4fcbb22,I1be8a18d

* changes:
  Bluetooth: Use AsyncFdWatcher for power management
  Bluetooth: AsyncFdWatcher: Refactor timeout lock
parents 559ae158 beb13b45
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -140,9 +140,15 @@ void AsyncFdWatcher::ThreadRoutine() {

    // Timeout.
    if (retval == 0) {
      // Allow the timeout callback to modify the timeout.
      TimeoutCallback saved_cb;
      {
        std::unique_lock<std::mutex> guard(timeout_mutex_);
      if (timeout_ms_ > std::chrono::milliseconds(0) && timeout_cb_)
        timeout_cb_();
        if (timeout_ms_ > std::chrono::milliseconds(0))
          saved_cb = timeout_cb_;
      }
      if (saved_cb != nullptr)
        saved_cb();
      continue;
    }

+49 −10
Original line number Diff line number Diff line
@@ -56,8 +56,7 @@ class AsyncFdWatcherSocketTest : public ::testing::Test {
    int reuse_flag = 1;
    EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag,
                            sizeof(reuse_flag)) < 0);
    EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) <
                 0);
    EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);

    ALOGD("%s before listen", __func__);
    listen(fd, 1);
@@ -81,12 +80,13 @@ class AsyncFdWatcherSocketTest : public ::testing::Test {
    int n = TEMP_FAILURE_RETRY(read(fd, server_buffer_, kBufferSize - 1));
    EXPECT_FALSE(n < 0);

    if (n == 0)  // got EOF
    if (n == 0) {  // got EOF
      ALOGD("%s: EOF", __func__);
    else
    } else {
      ALOGD("%s: Got something", __func__);
      n = write(fd, "1", 1);
    }
  }

  void SetUp() override {
    ALOGD("%s", __func__);
@@ -101,7 +101,10 @@ class AsyncFdWatcherSocketTest : public ::testing::Test {
      int connection_fd = AcceptConnection(fd);
      ALOGD("%s: Conn_watcher fd = %d", __func__, fd);

      conn_watcher_.ConfigureTimeout(std::chrono::seconds(0), [this]() { bool connection_timeout_cleared = false; ASSERT_TRUE(connection_timeout_cleared); });
      conn_watcher_.ConfigureTimeout(std::chrono::seconds(0), [this]() {
        bool connection_timeout_cleared = false;
        ASSERT_TRUE(connection_timeout_cleared);
      });

      ALOGD("%s: 3", __func__);
      async_fd_watcher_.WatchFdForNonBlockingReads(
@@ -110,7 +113,10 @@ class AsyncFdWatcherSocketTest : public ::testing::Test {
      // Time out if it takes longer than a second.
      SetTimeout(std::chrono::seconds(1));
    });
    conn_watcher_.ConfigureTimeout(std::chrono::seconds(1), [this]() { bool connection_timeout = true; ASSERT_FALSE(connection_timeout); });
    conn_watcher_.ConfigureTimeout(std::chrono::seconds(1), [this]() {
      bool connection_timeout = true;
      ASSERT_FALSE(connection_timeout);
    });
  }

  void CleanUpServer() {
@@ -220,10 +226,43 @@ TEST_F(AsyncFdWatcherSocketTest, TimedOutConnect) {
  });

  // Set the timeout flag after 100ms.
  conn_watcher.ConfigureTimeout(std::chrono::milliseconds(100), [this, timeout_ptr]() { *timeout_ptr = true; });
  conn_watcher.ConfigureTimeout(std::chrono::milliseconds(100),
                                [this, timeout_ptr]() { *timeout_ptr = true; });
  EXPECT_FALSE(timed_out);
  sleep(1);
  EXPECT_TRUE(timed_out);
  conn_watcher.StopWatchingFileDescriptor();
  close(socket_fd);
}

// Modify the timeout in a timeout callback.
TEST_F(AsyncFdWatcherSocketTest, TimedOutSchedulesTimeout) {
  int socket_fd = StartServer();
  bool timed_out = false;
  bool timed_out2 = false;

  AsyncFdWatcher conn_watcher;
  conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
    int connection_fd = AcceptConnection(fd);
    close(connection_fd);
  });

  // Set a timeout flag in each callback.
  conn_watcher.ConfigureTimeout(
      std::chrono::milliseconds(500),
      [this, &conn_watcher, &timed_out, &timed_out2]() {
        timed_out = true;
        conn_watcher.ConfigureTimeout(std::chrono::seconds(1),
                                      [&timed_out2]() { timed_out2 = true; });
      });
  EXPECT_FALSE(timed_out);
  EXPECT_FALSE(timed_out2);
  sleep(1);
  EXPECT_TRUE(timed_out);
  EXPECT_FALSE(timed_out2);
  sleep(1);
  EXPECT_TRUE(timed_out);
  EXPECT_TRUE(timed_out2);
  conn_watcher.StopWatchingFileDescriptor();
  close(socket_fd);
}
+47 −0
Original line number Diff line number Diff line
@@ -44,6 +44,11 @@ struct {
  uint16_t opcode;
} internal_command;

// True when LPM is not enabled yet or wake is not asserted.
bool lpm_wake_deasserted;
uint32_t lpm_timeout_ms;
bool recent_activity_flag;

VendorInterface* g_vendor_interface = nullptr;

const size_t preamble_size_for_type[] = {
@@ -271,6 +276,9 @@ bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb,
  fd_watcher_.WatchFdForNonBlockingReads(uart_fd_,
                                         [this](int fd) { OnDataReady(fd); });

  // Initially, the power management is off.
  lpm_wake_deasserted = false;

  // Start configuring the firmware
  firmware_startup_timer_ = new FirmwareStartupTimer();
  lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
@@ -302,6 +310,19 @@ void VendorInterface::Close() {
size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
  if (uart_fd_ == INVALID_FD) return 0;

  recent_activity_flag = true;

  if (lpm_wake_deasserted == true) {
    // Restart the timer.
    fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
                                 [this]() { OnTimeout(); });
    // Assert wake.
    lpm_wake_deasserted = false;
    bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
    lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
    ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
  }

  int rv = write_safely(uart_fd_, &type, sizeof(type));
  if (rv == sizeof(type))
    rv = write_safely(uart_fd_, data, length);
@@ -321,6 +342,32 @@ void VendorInterface::OnFirmwareConfigured(uint8_t result) {
    initialize_complete_cb_(result == 0);
    initialize_complete_cb_ = nullptr;
  }

  lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
  ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);

  bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
  lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);

  ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
  fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
                               [this]() { OnTimeout(); });

  bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
  lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
}

void VendorInterface::OnTimeout() {
  ALOGV("%s", __func__);
  if (recent_activity_flag == false) {
    lpm_wake_deasserted = true;
    bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
    lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
    fd_watcher_.ConfigureTimeout(std::chrono::seconds(0), []() {
      ALOGE("Zero timeout! Should never happen.");
    });
  }
  recent_activity_flag = false;
}

void VendorInterface::OnDataReady(int fd) {
+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ class VendorInterface {
            PacketReadCallback packet_read_cb);
  void Close();

  void OnTimeout();

  void OnDataReady(int fd);

  void *lib_handle_;