{
"postsubmit" : [
{
- "name" : "bluetooth_gd_test_os"
- },
- {
"name" : "bluetooth_test_common"
},
{
-cc_library_static {
- name: "libbt-gd-os",
+cc_defaults {
+ name: "gd_defaults",
+ target: {
+ android: {
+ test_config_template: "AndroidTestTemplate.xml",
+ cflags: [
+ "-DOS_ANDROID",
+ "-DOS_LINUX_GENERIC",
+ ],
+ shared_libs: [
+ "liblog"
+ ]
+ },
+ host: {
+ cflags: [
+ "-DOS_LINUX",
+ "-DOS_LINUX_GENERIC",
+ ]
+ }
+ },
+ cpp_std: "c++17",
+ cflags: [
+ "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
+ "-fvisibility=hidden",
+ "-DLOG_NDEBUG=1",
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ ],
+ conlyflags: [
+ "-std=c99",
+ ],
+ sanitize: {
+ misc_undefined: ["bounds"],
+ },
+}
+
+// Enables code coverage for a set of source files. Must be combined with
+// "clang_coverage_bin" in order to work. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+ name: "gd_clang_file_coverage",
+ target: {
+ host: {
+ clang_cflags: [
+ "-fprofile-instr-generate",
+ "-fcoverage-mapping",
+ ],
+ },
+ },
+}
+
+// Enabled code coverage on a binary. These flags allow libraries that were
+// compiled with "clang_file_coverage" to be properly linked together in
+// order to create a binary that will create a profraw file when ran. Note
+// these flags themselves don't enable code coverage for the source files
+// compiled in the binary. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+ name: "gd_clang_coverage_bin",
+ target: {
+ host: {
+ ldflags: [
+ "-fprofile-instr-generate",
+ "-fcoverage-mapping",
+ ],
+ },
+ },
+}
+
+cc_library {
+ name: "libbluetooth_gd",
defaults: [
- "fluoride_defaults",
- "clang_file_coverage",
+ "gd_defaults",
+ "gd_clang_file_coverage",
],
host_supported: true,
- srcs: [
- "os/alarm.cc",
- "os/handler.cc",
- "os/reactor.cc",
- "os/repeating_alarm.cc",
- "os/thread.cc",
- ],
+ target: {
+ linux: {
+ srcs: [
+ ":BluetoothOsSources_linux_generic",
+ ]
+ }
+ },
}
cc_test {
- name: "bluetooth_gd_test_os",
+ name: "bluetooth_test_gd",
test_suites: ["device-tests"],
defaults: [
- "fluoride_defaults",
- "clang_coverage_bin",
+ "gd_defaults",
+ "gd_clang_coverage_bin",
],
host_supported: true,
- srcs : [
- "os/alarm_unittest.cc",
- "os/handler_unittest.cc",
- "os/reactor_unittest.cc",
- "os/repeating_alarm_unittest.cc",
- "os/thread_unittest.cc",
- ],
+ target: {
+ linux: {
+ srcs: [
+ ":BluetoothOsTestSources_linux_generic",
+ ]
+ }
+ },
static_libs : [
- "libbt-gd-os",
+ "libbluetooth_gd",
],
sanitize: {
cfi: false,
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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.
+-->
+<configuration description="Runs {MODULE}.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+ <option name="run-command" value="svc bluetooth disable" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.FolderSaver">
+ <option name="device-path" value="/data/vendor/ssrdump" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ <option name="run-test-as" value="0" />
+ </test>
+</configuration>
--- /dev/null
+{
+ "presubmit" : [
+ {
+ "name" : "bluetooth_test_gd",
+ "host" : true
+ }
+ ]
+}
--- /dev/null
+filegroup {
+ name: "BluetoothOsSources_linux_generic",
+ srcs: [
+ "linux_generic/alarm.cc",
+ "linux_generic/handler.cc",
+ "linux_generic/reactor.cc",
+ "linux_generic/repeating_alarm.cc",
+ "linux_generic/thread.cc",
+ ]
+}
+
+filegroup {
+ name: "BluetoothOsTestSources_linux_generic",
+ srcs: [
+ "linux_generic/alarm_unittest.cc",
+ "linux_generic/handler_unittest.cc",
+ "linux_generic/reactor_unittest.cc",
+ "linux_generic/repeating_alarm_unittest.cc",
+ "linux_generic/thread_unittest.cc",
+ ]
+}
#include <sys/timerfd.h>
#include <cstring>
+#include <unistd.h>
-#include "base/logging.h"
+#include "os/log.h"
#include "os/utils.h"
+#ifdef OS_ANDROID
+#define ALARM_CLOCK CLOCK_BOOTTIME_ALARM
+#else
+#define ALARM_CLOCK CLOCK_BOOTTIME
+#endif
+
namespace bluetooth {
namespace os {
Alarm::Alarm(Thread* thread)
: thread_(thread),
- fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
- CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
+ fd_(timerfd_create(ALARM_CLOCK, 0)) {
+ LOG_FATAL_WHEN(fd_ != -1, "cannot create timerfd: %s", strerror(errno));
token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
}
int close_status;
RUN_NO_INTR(close_status = close(fd_));
- CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
+ FATAL_WHEN(close_status != -1);
}
void Alarm::Schedule(Closure task, std::chrono::milliseconds delay) {
{delay_ms / 1000, delay_ms % 1000 * 1000000}
};
int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
- CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
+ FATAL_WHEN(result == 0);
task_ = std::move(task);
}
std::lock_guard<std::mutex> lock(mutex_);
itimerspec disarm_itimerspec{/* disarm timer */};
int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
- CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
+ FATAL_WHEN(result == 0);
}
void Alarm::on_fire() {
auto bytes_read = read(fd_, ×_invoked, sizeof(uint64_t));
lock.unlock();
task();
- CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
- CHECK_EQ(times_invoked, static_cast<uint64_t>(1));
+ FATAL_WHEN(bytes_read == static_cast<ssize_t>(sizeof(uint64_t)))
+ FATAL_WHEN(times_invoked == static_cast<uint64_t>(1));
}
} // namespace os
#include <future>
-#include "base/logging.h"
#include "gtest/gtest.h"
namespace bluetooth {
#include <sys/eventfd.h>
#include <cstring>
+#include <unistd.h>
-#include "base/logging.h"
-
+#include "os/log.h"
#include "os/reactor.h"
#include "os/utils.h"
Handler::Handler(Thread* thread)
: thread_(thread),
fd_(eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) {
- CHECK_NE(fd_, -1) << __func__ << ": cannot create eventfd: " << strerror(errno);
+ FATAL_WHEN(fd_ != -1);
reactable_ = thread_->GetReactor()->Register(fd_, [this] { this->handle_next_event(); }, nullptr);
}
int close_status;
RUN_NO_INTR(close_status = close(fd_));
- CHECK_NE(close_status, -1) << __func__ << ": cannot close eventfd: " << strerror(errno);
+ FATAL_WHEN(close_status != -1);
}
void Handler::Post(Closure closure) {
}
uint64_t val = 1;
auto write_result = eventfd_write(fd_, val);
- CHECK_NE(write_result, -1) << __func__ << ": failed to write: " << strerror(errno);
+ FATAL_WHEN(write_result != -1);
}
void Handler::Clear() {
Closure closure;
uint64_t val = 0;
auto read_result = eventfd_read(fd_, &val);
- CHECK_NE(read_result, -1) << __func__ << ": failed to read fd: " << strerror(errno);
+ if (read_result == -1 && errno == EAGAIN) {
+ // We were told there was an item, but it was removed before we got there
+ // (aka the queue was cleared). Not a fatal error, so just bail.
+ return;
+ }
+
+ FATAL_WHEN(read_result != -1);
{
std::lock_guard<std::mutex> lock(mutex_);
#include <thread>
#include <gtest/gtest.h>
-#include "base/logging.h"
namespace bluetooth {
namespace os {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
};
handler_->Post(std::move(closure));
- closure = []() { LOG(FATAL) << "Should not happen"; };
+ closure = []() {
+ ASSERT_TRUE(false);
+ };
std::this_thread::sleep_for(std::chrono::milliseconds(5));
handler_->Post(std::move(closure));
handler_->Clear();
#include <cerrno>
#include <cstring>
-#include "base/logging.h"
+#include "os/log.h"
namespace {
is_running_(false),
reactable_removed_(false) {
RUN_NO_INTR(epoll_fd_ = epoll_create1(EPOLL_CLOEXEC));
- CHECK_NE(epoll_fd_, -1) << __func__ << ": cannot create epoll_fd: " << strerror(errno);
+ LOG_FATAL_WHEN(epoll_fd_ != -1, "could not create epoll fd: %s", strerror(errno));
control_fd_ = eventfd(0, EFD_NONBLOCK);
- CHECK_NE(control_fd_, -1) << __func__ << ": cannot create control_fd: " << strerror(errno);
+ FATAL_WHEN(control_fd_ != -1);
epoll_event control_epoll_event = {EPOLLIN, {.ptr = nullptr}};
int result;
RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, control_fd_, &control_epoll_event));
- CHECK_NE(result, -1) << __func__ << ": cannot register control_fd: " << strerror(errno);
+ FATAL_WHEN(result != -1);
}
Reactor::~Reactor() {
int result;
RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, control_fd_, nullptr));
- CHECK_NE(result, -1) << __func__ << ": cannot unregister control_fd: " << strerror(errno);
+ FATAL_WHEN(result != -1);
RUN_NO_INTR(result = close(control_fd_));
- CHECK_NE(result, -1) << __func__ << ": cannot close control_fd: " << strerror(errno);
+ FATAL_WHEN(result != -1);
RUN_NO_INTR(result = close(epoll_fd_));
- CHECK_NE(result, -1) << __func__ << ": cannot close epoll_fd: " << strerror(errno);
+ FATAL_WHEN(result != -1);
}
void Reactor::Run() {
bool previously_running = is_running_.exchange(true);
- CHECK_EQ(previously_running, false) << __func__ << ": already running";
- LOG(INFO) << __func__ << ": started";
+ FATAL_WHEN(!previously_running);
for (;;) {
invalidation_list_.clear();
epoll_event events[kEpollMaxEvents];
int count;
RUN_NO_INTR(count = epoll_wait(epoll_fd_, events, kEpollMaxEvents, -1));
- CHECK_NE(count, -1) << __func__ << ": Error polling for fds: " << strerror(errno);
+ FATAL_WHEN(count != -1);
for (int i = 0; i < count; ++i) {
auto event = events[i];
- CHECK_NE(event.events, 0u) << __func__ << ": no result in epoll result";
+ FATAL_WHEN(event.events != 0u);
// If the ptr stored in epoll_event.data is nullptr, it means the control fd triggered
if (event.data.ptr == nullptr) {
uint64_t value;
eventfd_read(control_fd_, &value);
- LOG(INFO) << __func__ << ": stopped";
is_running_ = false;
return;
}
void Reactor::Stop() {
if (!is_running_) {
- LOG(WARNING) << __func__ << ": not running, will stop once it's started";
+ LOG_WARN("not running, will stop once it's started");
}
auto control = eventfd_write(control_fd_, 1);
- CHECK_NE(control, -1) << __func__ << ": failed: " << strerror(errno);
+ FATAL_WHEN(control != -1)
}
Reactor::Reactable* Reactor::Register(int fd, Closure on_read_ready, Closure on_write_ready) {
};
int register_fd;
RUN_NO_INTR(register_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event));
- CHECK_NE(register_fd, -1) << __func__ << ": failed: " << strerror(errno);
+ FATAL_WHEN(register_fd != -1)
return reactable;
}
void Reactor::Unregister(Reactor::Reactable* reactable) {
- CHECK_NE(reactable, nullptr);
+ FATAL_WHEN(reactable != nullptr);
{
std::lock_guard<std::mutex> lock(mutex_);
invalidation_list_.push_back(reactable);
std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, reactable->fd_, nullptr));
if (result == -1 && errno == ENOENT) {
- LOG(INFO) << __func__ << ": reactable is invalid or unregistered";
- } else if (result == -1) {
- LOG(FATAL) << __func__ << ": failed: " << strerror(errno);
+ LOG_INFO("reactable is invalid or unregistered");
+ } else {
+ FATAL_WHEN(result != -1);
}
// If we are unregistering during the callback event from this reactable, we delete it after the callback is executed.
// reactable->is_executing_ is protected by reactable->lock_, so it's thread safe.
}
void Reactor::ModifyRegistration(Reactor::Reactable* reactable, Closure on_read_ready, Closure on_write_ready) {
- CHECK_NE(reactable, nullptr);
+ FATAL_WHEN(reactable != nullptr);
uint32_t poll_event_type = 0;
if (on_read_ready != nullptr) {
};
int modify_fd;
RUN_NO_INTR(modify_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, reactable->fd_, &event));
- CHECK_NE(modify_fd, -1) << __func__ << ": failed: " << strerror(errno);
+ FATAL_WHEN(modify_fd != -1);
}
} // namespace os
#include <future>
#include <thread>
-#include "base/logging.h"
#include "gtest/gtest.h"
namespace bluetooth {
EXPECT_EQ(future.get(), kReadReadyValue);
reactor_->Stop();
reactor_thread.join();
- LOG(INFO);
reactor_->Unregister(reactable);
- LOG(INFO);
}
TEST_F(ReactorTest, start_and_stop_multi_times) {
#include <sys/timerfd.h>
#include <cstring>
+#include <unistd.h>
-#include "base/logging.h"
+#include "os/log.h"
#include "os/utils.h"
+#ifdef OS_ANDROID
+#define ALARM_CLOCK CLOCK_BOOTTIME_ALARM
+#else
+#define ALARM_CLOCK CLOCK_BOOTTIME
+#endif
+
namespace bluetooth {
namespace os {
RepeatingAlarm::RepeatingAlarm(Thread* thread)
: thread_(thread),
- fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
- CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
+ fd_(timerfd_create(ALARM_CLOCK, 0)) {
+ FATAL_WHEN(fd_ != -1);
token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
}
int close_status;
RUN_NO_INTR(close_status = close(fd_));
- CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
+ FATAL_WHEN(close_status != -1);
}
void RepeatingAlarm::Schedule(Closure task, std::chrono::milliseconds period) {
{period_ms / 1000, period_ms % 1000 * 1000000}
};
int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
- CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
+ FATAL_WHEN(result == 0);
task_ = std::move(task);
}
std::lock_guard<std::mutex> lock(mutex_);
itimerspec disarm_itimerspec{/* disarm timer */};
int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
- CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
+ FATAL_WHEN(result == 0);
}
void RepeatingAlarm::on_fire() {
auto bytes_read = read(fd_, ×_invoked, sizeof(uint64_t));
lock.unlock();
task();
- CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
+ FATAL_WHEN(bytes_read == static_cast<ssize_t>(sizeof(uint64_t)));
}
} // namespace os
#include <future>
-#include "base/logging.h"
#include "gtest/gtest.h"
namespace bluetooth {
}
TEST_F(RepeatingAlarmTest, cancel_alarm) {
- alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
+ alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
alarm_->Cancel();
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
- alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
+ alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
std::promise<void> promise;
auto future = promise.get_future();
alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
}
TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
- alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
+ alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
delete alarm_;
alarm_ = nullptr;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
#include "os/thread.h"
#include <fcntl.h>
+#include <unistd.h>
#include <sys/syscall.h>
#include <cerrno>
#include <cstring>
-#include "base/logging.h"
+#include "os/log.h"
namespace bluetooth {
namespace os {
int rc;
RUN_NO_INTR(rc = sched_setscheduler(linux_tid, SCHED_FIFO, &rt_params));
if (rc != 0) {
- LOG(ERROR) << __func__ << ": unable to set SCHED_FIFO priority: " << strerror(errno);
+ LOG_ERROR("unable to set SCHED_FIFO priority: %s", strerror(errno));
}
}
reactor_.Run();
bool Thread::Stop() {
std::lock_guard<std::mutex> lock(mutex_);
- CHECK_NE(std::this_thread::get_id(), running_thread_.get_id());
+ FATAL_WHEN(std::this_thread::get_id() != running_thread_.get_id());
if (!running_thread_.joinable()) {
return false;
#include <sys/eventfd.h>
-#include "base/logging.h"
#include "gtest/gtest.h"
#include "os/reactor.h"
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright 2019 Google, Inc.
+ *
+ * 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
+
+#ifndef LOG_TAG
+#define LOG_TAG "bt"
+#endif
+
+#if defined(OS_ANDROID)
+
+#include <log/log.h>
+
+#define LOG_VERBOSE(fmt, args...) ALOGV("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_DEBUG(fmt, args...) ALOGD("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_INFO(fmt, args...) ALOGI("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_WARN(fmt, args...) ALOGW("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_ERROR(fmt, args...) ALOGE("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+
+#else
+
+/* syslog didn't work well here since we would be redefining LOG_DEBUG. */
+#include <stdio.h>
+
+#define LOGWRAPPER(fmt, args...) \
+ fprintf(stderr, "%s - %s: " fmt "\n", LOG_TAG, __PRETTY_FUNCTION__, ##args)
+
+#define LOG_VERBOSE(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_DEBUG(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_INFO(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_WARN(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_ERROR(...) LOGWRAPPER(__VA_ARGS__)
+
+#endif /* defined(OS_ANDROID) */
+
+#define FATAL_WHEN(condition) \
+ if (!(condition)) { \
+ LOG_ERROR("%s:%d assertion '" #condition "' failed", __FILE__, __LINE__); \
+ abort(); \
+ }
+
+#define LOG_FATAL_WHEN(condition, fmt, args...) \
+ if (!(condition)) { \
+ LOG_ERROR("%s:%d assertion '" #condition "' failed - " fmt, __FILE__, __LINE__, ##args); \
+ abort(); \
+ }
+