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

Commit 30ab5383 authored by Marie Janssen's avatar Marie Janssen Committed by Pavlin Radoslavov
Browse files

tests: don't use bt_os_callouts for wakelocks

Introduces alarm_set_wake_lock_paths so wake lock paths can be changed
for testing, and adds AlarmTestHarness::WakeLockHeld to test whether a
wake lock is currently held.

Bug: 25387683
Change-Id: I9a41ae8266e252a3d436f8d41ea3f9e7ecb45cdc
parent 6ee24d68
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -59,3 +59,10 @@ period_ms_t alarm_get_remaining_ms(const alarm_t *alarm);

// Alarm-related state cleanup
void alarm_cleanup(void);

// This function should not need to be called normally.
// /sys/power/wake_{|un}lock are used by default.
// This is not guaranteed to have any effect after an alarm has been
// set with alarm_set.
// If |lock_path| or |unlock_path| are NULL, that path is not changed.
void alarm_set_wake_lock_paths(const char *lock_path, const char *unlock_path);
+43 −7
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <malloc.h>
#include <pthread.h>
#include <signal.h>
@@ -70,8 +71,10 @@ int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME_ALARM;
static const char *WAKE_LOCK_ID = "bluetooth_timer";
static const char *WAKE_LOCK_PATH = "/sys/power/wake_lock";
static const char *WAKE_UNLOCK_PATH = "/sys/power/wake_unlock";
static char *DEFAULT_WAKE_LOCK_PATH = "/sys/power/wake_lock";
static char *DEFAULT_WAKE_UNLOCK_PATH = "/sys/power/wake_unlock";
static char *wake_lock_path = NULL;
static char *wake_unlock_path = NULL;
static ssize_t locked_id_len = -1;
static pthread_once_t wake_fds_initialized = PTHREAD_ONCE_INIT;
static int wake_lock_fd = INVALID_FD;
@@ -214,7 +217,17 @@ void alarm_cancel(alarm_t *alarm) {
}

void alarm_cleanup(void) {
  // If lazy_initialize never ran there is nothing to do
  if (wake_lock_path && wake_lock_path != DEFAULT_WAKE_LOCK_PATH) {
    osi_free(wake_lock_path);
    wake_lock_path = NULL;
  }

  if (wake_unlock_path && wake_unlock_path != DEFAULT_WAKE_UNLOCK_PATH) {
    osi_free(wake_unlock_path);
    wake_unlock_path = NULL;
  }

  // If lazy_initialize never ran there is nothing else to do
  if (!alarms)
    return;

@@ -229,9 +242,26 @@ void alarm_cleanup(void) {
  list_free(alarms);
  alarms = NULL;

  wake_fds_initialized = PTHREAD_ONCE_INIT;

  pthread_mutex_destroy(&monitor);
}

void alarm_set_wake_lock_paths(const char *lock_path, const char *unlock_path) {
  if (lock_path) {
    if (wake_lock_path && wake_lock_path != DEFAULT_WAKE_LOCK_PATH)
      osi_free(wake_lock_path);
    wake_lock_path = osi_strndup(lock_path, PATH_MAX);
  }

  if (unlock_path) {
    if (wake_unlock_path && wake_unlock_path != DEFAULT_WAKE_UNLOCK_PATH)
      osi_free(wake_unlock_path);
    wake_unlock_path = osi_strndup(unlock_path, PATH_MAX);
  }

}

static bool lazy_initialize(void) {
  assert(alarms == NULL);

@@ -478,16 +508,22 @@ static void callback_dispatch(UNUSED_ATTR void *context) {
static void initialize_wake_fds(void) {
  LOG_DEBUG(LOG_TAG, "%s opening wake locks", __func__);

  wake_lock_fd = open(WAKE_LOCK_PATH, O_RDWR | O_CLOEXEC);
  if (!wake_lock_path)
    wake_lock_path = DEFAULT_WAKE_LOCK_PATH;

  wake_lock_fd = open(wake_lock_path, O_RDWR | O_CLOEXEC);
  if (wake_lock_fd == INVALID_FD) {
    LOG_ERROR(LOG_TAG, "%s can't open wake lock %s: %s",
              __func__, WAKE_LOCK_PATH, strerror(errno));
              __func__, wake_lock_path, strerror(errno));
  }

  wake_unlock_fd = open(WAKE_UNLOCK_PATH, O_RDWR | O_CLOEXEC);
  if (!wake_unlock_path)
    wake_unlock_path = DEFAULT_WAKE_UNLOCK_PATH;

  wake_unlock_fd = open(wake_unlock_path, O_RDWR | O_CLOEXEC);
  if (wake_unlock_fd == INVALID_FD) {
    LOG_ERROR(LOG_TAG, "%s can't open wake unlock %s: %s",
              __func__, WAKE_UNLOCK_PATH, strerror(errno));
              __func__, wake_unlock_path, strerror(errno));
  }
}

+64 −31
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@
 *
 ******************************************************************************/

#include <gtest/gtest.h>
#include <hardware/bluetooth.h>
#include "AlarmTestHarness.h"

#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#include "AlarmTestHarness.h"
#include <hardware/bluetooth.h>

extern "C" {
#include "osi/include/alarm.h"
@@ -41,7 +43,6 @@ void AlarmTestHarness::SetUp() {

  current_harness = this;
  TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 100;
  lock_count = 0;

  struct sigevent sigevent;
  memset(&sigevent, 0, sizeof(sigevent));
@@ -49,44 +50,76 @@ void AlarmTestHarness::SetUp() {
  sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
  sigevent.sigev_value.sival_ptr = NULL;
  timer_create(CLOCK_BOOTTIME, &sigevent, &timer);

  // TODO (jamuraa): maybe use base::CreateNewTempDirectory instead?
#if defined(OS_GENERIC)
  tmp_dir_ = "/tmp/btwlXXXXXX";
#else  // !defined(OS_GENERIC)
  tmp_dir_ = "/data/local/tmp/btwlXXXXXX";
#endif  // !defined(OS_GENERIC)

  char *buffer = const_cast<char *>(tmp_dir_.c_str());
  char *dtemp = mkdtemp(buffer);
  if (!dtemp) {
    perror("Can't make wake lock test directory: ");
    assert(false);
  }

  lock_path_ = tmp_dir_ + "/wake_lock";
  unlock_path_ = tmp_dir_ + "/wake_unlock";

  creat(lock_path_.c_str(), S_IRWXU);
  creat(unlock_path_.c_str(), S_IRWXU);

  alarm_set_wake_lock_paths(lock_path_.c_str(), unlock_path_.c_str());
}

void AlarmTestHarness::TearDown() {
  alarm_cleanup();

  // clean up the temp wake lock directory
  unlink(lock_path_.c_str());
  unlink(unlock_path_.c_str());
  rmdir(tmp_dir_.c_str());

  timer_delete(timer);
  AllocationTestHarness::TearDown();
}

static bool set_wake_alarm(uint64_t delay_millis, bool, alarm_cb cb, void *data) {
  saved_callback = cb;
  saved_data = data;

  struct itimerspec wakeup_time;
  memset(&wakeup_time, 0, sizeof(wakeup_time));
  wakeup_time.it_value.tv_sec = (delay_millis / 1000);
  wakeup_time.it_value.tv_nsec = (delay_millis % 1000) * 1000000LL;
  timer_settime(timer, 0, &wakeup_time, NULL);
  return true;
}
bool AlarmTestHarness::WakeLockHeld() {
  bool held = false;

static int acquire_wake_lock(const char *) {
  if (!current_harness->lock_count)
    current_harness->lock_count = 1;
  return BT_STATUS_SUCCESS;
}
  int lock_fd = open(lock_path_.c_str(), O_RDONLY);
  assert(lock_fd >= 0);

static int release_wake_lock(const char *) {
  if (current_harness->lock_count)
    current_harness->lock_count = 0;
  return BT_STATUS_SUCCESS;
}
  int unlock_fd = open(unlock_path_.c_str(), O_RDONLY);
  assert(unlock_fd >= 0);

  struct stat lock_stat, unlock_stat;
  fstat(lock_fd, &lock_stat);
  fstat(unlock_fd, &unlock_stat);

static bt_os_callouts_t stub = {
  sizeof(bt_os_callouts_t),
  set_wake_alarm,
  acquire_wake_lock,
  release_wake_lock,
};
  assert(lock_stat.st_size >= unlock_stat.st_size);

bt_os_callouts_t *bt_os_callouts = &stub;
  void *lock_file = mmap(nullptr, lock_stat.st_size, PROT_READ,
                         MAP_PRIVATE, lock_fd, 0);

  void *unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ,
                           MAP_PRIVATE, unlock_fd, 0);

  if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) {
    held = lock_stat.st_size > unlock_stat.st_size;
  } else {
    // these files should always either be with a lock that has more,
    // or equal.
    assert(false);
  }

  munmap(lock_file, lock_stat.st_size);
  munmap(unlock_file, unlock_stat.st_size);
  close(lock_fd);
  close(unlock_fd);

  return held;
}
+6 −1
Original line number Diff line number Diff line
@@ -27,6 +27,11 @@ class AlarmTestHarness : public AllocationTestHarness {
    virtual void SetUp();
    virtual void TearDown();

    std::string tmp_dir_;
    std::string lock_path_;
    std::string unlock_path_;

  public:
    int lock_count;
    // Returns true if a wake lock is held.
    bool WakeLockHeld();
};
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#pragma once

#include <gtest/gtest.h>

class AllocationTestHarness : public ::testing::Test {
  protected:
    virtual void SetUp();
Loading