"l2c_api.cc",
"l2cap.cc",
"shim.cc",
+ "timer.cc",
]
}
name: "LibBluetoothShimTestSources",
srcs: [
"l2cap_test.cc",
+ "timer_test.cc",
]
}
#include "main/shim/stub/osi.h"
#include "osi/include/alarm.h"
-bool osi_property_get_int32(char const* n, int a) { return true; }
-
-const module_t* get_module(const char*) { return nullptr; };
-bool module_init(module_t const*) { return true; };
-void module_clean_up(module_t const*){};
+bool module_init(module_t const*) { return true; }
+bool module_start_up(module_t const*) { return true; }
+const module_t* get_module(const char*) { return nullptr; }
+void module_clean_up(module_t const*) {}
+void module_shut_down(module_t const*) {}
void* osi_alloc(size_t size) { return malloc(size); }
void* osi_calloc(size_t size) { return calloc(1, size); }
--- /dev/null
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "bt_shim_timer"
+
+#include <base/bind.h>
+#include <cstdint>
+#include <functional>
+
+#include "main/shim/shim.h"
+#include "main/shim/timer.h"
+#include "osi/include/alarm.h"
+#include "osi/include/log.h"
+
+static void timer_timeout(void* data) {
+ CHECK(data != nullptr);
+ bluetooth::shim::Timer* timeout = static_cast<bluetooth::shim::Timer*>(data);
+ bluetooth::shim::Post(
+ base::Bind(&bluetooth::shim::Timer::Pop, base::Unretained(timeout)));
+}
+
+void bluetooth::shim::Timer::Set(uint64_t duration_ms,
+ std::function<void()> func) {
+ CHECK(duration_ms != 0);
+ callback_ = func;
+ alarm_set_on_mloop(timer_, duration_ms, timer_timeout, (void*)this);
+}
+
+void bluetooth::shim::Timer::Cancel() {
+ alarm_cancel(timer_);
+ callback_ = {};
+}
+
+bool bluetooth::shim::Timer::IsActive() { return callback_ != nullptr; }
+
+bluetooth::shim::Timer::Timer(const char* name) {
+ timer_ = alarm_new(name);
+ CHECK(timer_ != nullptr);
+}
+
+bluetooth::shim::Timer::~Timer() { alarm_free(timer_); }
+
+void bluetooth::shim::Timer::Pop(Timer* timer) {
+ timer->callback_();
+ timer->callback_ = {};
+}
--- /dev/null
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <functional>
+#include "osi/include/alarm.h"
+
+namespace bluetooth {
+namespace shim {
+
+class Timer {
+ public:
+ /**
+ * Set this timer using the osi timer alarm functionality.
+ *
+ * The alarm duration *must not* be zero. The timer is set
+ * on the bluetooth main message loop thread.
+ *
+ * @param duration_ms Duration in milliseconds (>0) before alarm pops
+ * @param func Function to execute upon alarm pop.
+ */
+ void Set(uint64_t duration_ms, std::function<void()> func);
+
+ /**
+ * Cancel this previously set timer.
+ *
+ * The associated function call will *not* be executed.
+ */
+ void Cancel();
+
+ /**
+ * Determine if a given timer has been set or not.
+ *
+ * @return |true| if timer has been set, |false| otherwise.
+ */
+ bool IsActive();
+
+ /**
+ * @param name Arbitrary name passed to the osi module.
+ */
+ Timer(const char* name);
+ ~Timer();
+
+ /**
+ * Pop this timer.
+ *
+ * Called from an internal trampoline timeout global function registered
+ * with osi alarm. This trampoline function will then post
+ * the execution of the callback function onto the shim thread.
+ */
+ static void Pop(Timer* timer);
+
+ private:
+ std::function<void()> callback_{};
+ alarm_t* timer_{nullptr};
+};
+
+} // namespace shim
+} // namespace bluetooth
--- /dev/null
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <cstdint>
+#include <future>
+
+#define LOG_TAG "bt_shim_test"
+
+#include <base/logging.h>
+#include "osi/include/log.h"
+#include "shim/timer.h"
+#include "stub/osi.h"
+
+#include <stdlib.h>
+
+namespace bluetooth {
+namespace legacy {
+
+constexpr uint64_t kDurationMs = 3;
+
+static const char* kTimer0 = "TestTimer00";
+static const char* kTimer1 = "TestTimer01";
+
+namespace {
+
+class TimerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ // Ensure expected global state default initial conditions
+ bluetooth::shim::stub::name_to_alarm_map_.clear();
+ }
+
+ void TearDown() override {
+ // Reset global state to defaults
+ bluetooth::shim::stub::name_to_alarm_map_.clear();
+ }
+};
+
+TEST_F(TimerTest, Set) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+
+ shim::Timer* timer = new shim::Timer(kTimer0);
+
+ timer->Set(kDurationMs, [&promise]() { promise.set_value(); });
+
+ CHECK(bluetooth::shim::stub::alarm_is_set(kTimer0) == true);
+ CHECK(bluetooth::shim::stub::alarm_interval_ms(kTimer0) == kDurationMs);
+ CHECK(bluetooth::shim::stub::alarm_data(kTimer0));
+
+ {
+ shim::Timer* timer =
+ static_cast<shim::Timer*>(bluetooth::shim::stub::alarm_data(kTimer0));
+ bluetooth::shim::Timer::Pop(timer);
+ }
+ future.wait();
+
+ delete timer;
+ CHECK(bluetooth::shim::stub::name_to_alarm_map_.empty());
+}
+
+TEST_F(TimerTest, Set2) {
+ std::promise<void> promise0;
+ std::promise<void> promise1;
+ auto future0 = promise0.get_future();
+ auto future1 = promise1.get_future();
+
+ shim::Timer* timer0 = new shim::Timer(kTimer0);
+ CHECK(bluetooth::shim::stub::name_to_alarm_map_.size() == 1);
+
+ shim::Timer* timer1 = new shim::Timer(kTimer1);
+ CHECK(bluetooth::shim::stub::name_to_alarm_map_.size() == 2);
+
+ timer0->Set(kDurationMs, [&promise0]() { promise0.set_value(); });
+
+ timer1->Set(kDurationMs * 2, [&promise1]() { promise1.set_value(); });
+
+ CHECK(bluetooth::shim::stub::alarm_is_set(kTimer0) == true);
+ CHECK(bluetooth::shim::stub::alarm_interval_ms(kTimer0) == kDurationMs);
+ CHECK(bluetooth::shim::stub::alarm_data(kTimer0));
+
+ CHECK(bluetooth::shim::stub::alarm_is_set(kTimer1) == true);
+ CHECK(bluetooth::shim::stub::alarm_interval_ms(kTimer1) == kDurationMs * 2);
+ CHECK(bluetooth::shim::stub::alarm_data(kTimer1));
+
+ {
+ shim::Timer* timer =
+ static_cast<shim::Timer*>(bluetooth::shim::stub::alarm_data(kTimer0));
+ bluetooth::shim::Timer::Pop(timer);
+ }
+
+ {
+ shim::Timer* timer =
+ static_cast<shim::Timer*>(bluetooth::shim::stub::alarm_data(kTimer1));
+ bluetooth::shim::Timer::Pop(timer);
+ }
+
+ future0.wait();
+ future1.wait();
+
+ delete timer0;
+ delete timer1;
+
+ CHECK(bluetooth::shim::stub::name_to_alarm_map_.empty());
+}
+
+TEST_F(TimerTest, Cancel) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+
+ shim::Timer* timer = new shim::Timer(kTimer0);
+
+ timer->Set(kDurationMs, [&promise]() { promise.set_value(); });
+
+ CHECK(bluetooth::shim::stub::alarm_is_set(kTimer0) == true);
+ CHECK(bluetooth::shim::stub::alarm_interval_ms(kTimer0) == kDurationMs);
+ CHECK(bluetooth::shim::stub::alarm_data(kTimer0));
+
+ timer->Cancel();
+
+ CHECK(bluetooth::shim::stub::alarm_is_set(kTimer0) == false);
+ CHECK(bluetooth::shim::stub::alarm_interval_ms(kTimer0) == 0);
+ CHECK(bluetooth::shim::stub::alarm_data(kTimer0) == nullptr);
+
+ delete timer;
+ CHECK(bluetooth::shim::stub::name_to_alarm_map_.empty());
+}
+
+} // namespace
+} // namespace legacy
+} // namespace bluetooth