Snap for 5339364 from 6e948fca8ec9d90e15b8ab488c6244c45aafd811 to qt-release

Change-Id: If4dbb0046aaa201120b16fced0fa6cc13056fb86
diff --git a/.clang-format b/.clang-format
index fc5f5fe..1f1f586 100644
--- a/.clang-format
+++ b/.clang-format
@@ -23,3 +23,6 @@
 CommentPragmas: NOLINT:.*
 DerivePointerAlignment: false
 ColumnLimit: 120
+AllowShortFunctionsOnASingleLine: Empty
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+BreakConstructorInitializers: BeforeColon
diff --git a/bta/Android.bp b/bta/Android.bp
index 9dfda3c..0e7bfe8 100644
--- a/bta/Android.bp
+++ b/bta/Android.bp
@@ -129,6 +129,7 @@
         "test/gatt/database_test.cc",
     ],
     shared_libs: [
+        "libcrypto",
         "liblog",
         "libprotobuf-cpp-lite",
     ],
diff --git a/btif/include/btif_keystore.h b/btif/include/btif_keystore.h
index 01ccd66..4762350 100644
--- a/btif/include/btif_keystore.h
+++ b/btif/include/btif_keystore.h
@@ -42,22 +42,20 @@
   BtifKeystore(keystore::KeystoreClient* keystore_client);
 
   /**
-   * Stores encrypted data to disk.
+   * Encrypts given data
    *
-   * <p>Returns true on success.
+   * <p>Returns a string representation of the encrypted data
    *
    * @param data to be encrypted
-   * @param output_filename location to write the file
-   * @param flags
+   * @param flags for keystore
    */
-  bool Encrypt(const std::string& data, const std::string& output_filename,
-               int32_t flags);
+  std::string Encrypt(const std::string& data, int32_t flags);
 
   /**
    * Returns a decrypted string representation of the encrypted data or empty
    * string on error.
    *
-   * @param input_filename location of file to read and decrypt
+   * @param input encrypted data
    */
   std::string Decrypt(const std::string& input_filename);
 
diff --git a/btif/src/btif_config.cc b/btif/src/btif_config.cc
index 567fce6..7d23e34 100644
--- a/btif/src/btif_config.cc
+++ b/btif/src/btif_config.cc
@@ -24,15 +24,15 @@
 #include <ctype.h>
 #include <openssl/rand.h>
 #include <openssl/sha.h>
+#include <private/android_filesystem_config.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <mutex>
 #include <sstream>
 #include <string>
 
-#include <mutex>
-
 #include "bt_types.h"
 #include "btcore/include/module.h"
 #include "btif_api.h"
@@ -55,10 +55,13 @@
 #define FILE_TIMESTAMP "TimeCreated"
 #define FILE_SOURCE "FileSource"
 #define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
+#define DISABLED "disabled"
 static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
 
 constexpr int kBufferSize = 400 * 10;  // initial file is ~400B
 
+static bool use_key_attestation() { return getuid() == AID_BLUETOOTH; }
+
 #define BT_CONFIG_METRICS_SECTION "Metrics"
 #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
 using bluetooth::BtifKeystore;
@@ -636,6 +639,10 @@
 }
 
 static std::string hash_file(const char* filename) {
+  if (!use_key_attestation()) {
+    LOG(INFO) << __func__ << ": Disabled for multi-user";
+    return DISABLED;
+  }
   FILE* fp = fopen(filename, "rb");
   if (!fp) {
     LOG(ERROR) << __func__ << ": unable to open config file: '" << filename
@@ -660,15 +667,31 @@
 }
 
 static std::string read_checksum_file(const char* checksum_filename) {
-  // Ensure file exists
-  if (access(checksum_filename, R_OK) != 0) {
+  if (!use_key_attestation()) {
+    LOG(INFO) << __func__ << ": Disabled for multi-user";
+    return DISABLED;
+  }
+  std::string encrypted_hash = checksum_read(checksum_filename);
+  if (encrypted_hash.empty()) {
+    LOG(INFO) << __func__ << ": read empty hash.";
     return "";
   }
-  return btif_keystore.Decrypt(checksum_filename);
+  return btif_keystore.Decrypt(encrypted_hash);
 }
 
 static void write_checksum_file(const char* checksum_filename,
                                 const std::string& hash) {
-  bool result = btif_keystore.Encrypt(hash, checksum_filename, 0);
-  CHECK(result) << "Failed writing checksum";
+  if (!use_key_attestation()) {
+    LOG(INFO) << __func__
+              << ": Disabled for multi-user, since config changed removing "
+                 "checksums.";
+    remove(CONFIG_FILE_CHECKSUM_PATH);
+    remove(CONFIG_BACKUP_CHECKSUM_PATH);
+    return;
+  }
+  std::string encrypted_checksum = btif_keystore.Encrypt(hash, 0);
+  CHECK(!encrypted_checksum.empty())
+      << __func__ << ": Failed encrypting checksum";
+  CHECK(checksum_save(encrypted_checksum, checksum_filename))
+      << __func__ << ": Failed to save checksum!";
 }
diff --git a/btif/src/btif_keystore.cc b/btif/src/btif_keystore.cc
index ac3a803..fe9d3dd 100644
--- a/btif/src/btif_keystore.cc
+++ b/btif/src/btif_keystore.cc
@@ -31,78 +31,41 @@
 
 constexpr char kKeyStore[] = "AndroidKeystore";
 
-static std::string ReadFile(const std::string& filename) {
-  CHECK(!filename.empty()) << __func__ << ": filename should not be empty";
-
-  std::string content;
-  base::FilePath path(filename);
-  if (!base::PathExists(path)) {
-    // Config file checksum file doesn't exist on first run after OTA.
-    LOG(ERROR) << "file '" << filename.c_str() << "'doesn't exists yet";
-  }
-  if (!base::ReadFileToString(path, &content)) {
-    LOG(ERROR) << "ReadFile failed: " << filename.c_str();
-  }
-  return content;
-}
-
-static void WriteFile(const std::string& filename, const std::string& content) {
-  CHECK(!filename.empty()) << __func__ << ": filename should not be empty";
-  CHECK(!content.empty()) << __func__ << ": content should not be empty";
-
-  base::FilePath path(filename);
-  int size = content.size();
-  if (base::WriteFile(path, content.data(), size) != size) {
-    LOG(FATAL) << "WriteFile failed.\n" << filename.c_str();
-  }
-}
-
 namespace bluetooth {
 
 BtifKeystore::BtifKeystore(keystore::KeystoreClient* keystore_client)
     : keystore_client_(keystore_client) {}
 
-bool BtifKeystore::Encrypt(const std::string& data,
-                           const std::string& output_filename, int32_t flags) {
+std::string BtifKeystore::Encrypt(const std::string& data, int32_t flags) {
   std::lock_guard<std::mutex> lock(api_mutex_);
+  std::string output;
   if (data.empty()) {
     LOG(ERROR) << __func__ << ": empty data";
-    return false;
+    return output;
   }
-  if (output_filename.empty()) {
-    LOG(ERROR) << __func__ << ": empty output filename";
-    return false;
-  }
-  std::string output;
   if (!keystore_client_->doesKeyExist(kKeyStore)) {
     auto gen_result = GenerateKey(kKeyStore, 0, false);
     if (!gen_result.isOk()) {
       LOG(FATAL) << "EncryptWithAuthentication Failed: generateKey response="
                  << gen_result;
-      return false;
+      return output;
     }
   }
   if (!keystore_client_->encryptWithAuthentication(kKeyStore, data, flags,
                                                    &output)) {
     LOG(FATAL) << "EncryptWithAuthentication failed.";
-    return false;
+    return output;
   }
-  WriteFile(output_filename, output);
-  return true;
+  return output;
 }
 
-std::string BtifKeystore::Decrypt(const std::string& input_filename) {
+std::string BtifKeystore::Decrypt(const std::string& input) {
   std::lock_guard<std::mutex> lock(api_mutex_);
-  std::string output;
-  if (input_filename.empty()) {
-    LOG(ERROR) << __func__ << ": empty input filename";
-    return output;
-  }
-  std::string input = ReadFile(input_filename);
   if (input.empty()) {
     LOG(ERROR) << __func__ << ": empty input data";
-    return output;
+    return "";
   }
+  std::string output;
   if (!keystore_client_->decryptWithAuthentication(kKeyStore, input, &output)) {
     LOG(FATAL) << "DecryptWithAuthentication failed.\n";
   }
diff --git a/btif/test/btif_keystore_test.cc b/btif/test/btif_keystore_test.cc
index e57c64f..4cabbad 100644
--- a/btif/test/btif_keystore_test.cc
+++ b/btif/test/btif_keystore_test.cc
@@ -16,7 +16,6 @@
  *
  ******************************************************************************/
 
-#include <base/files/file_util.h>
 #include <base/logging.h>
 #include <binder/ProcessState.h>
 #include <gtest/gtest.h>
@@ -26,73 +25,40 @@
 
 using namespace bluetooth;
 
-constexpr char kFilename[] = "/data/misc/bluedroid/testfile.txt";
-
 class BtifKeystoreTest : public ::testing::Test {
  protected:
   std::unique_ptr<BtifKeystore> btif_keystore_;
-  base::FilePath file_path_;
-  BtifKeystoreTest() : file_path_(kFilename) {}
   void SetUp() override {
     android::ProcessState::self()->startThreadPool();
     btif_keystore_ =
         std::make_unique<BtifKeystore>(static_cast<keystore::KeystoreClient*>(
             new keystore::KeystoreClientImpl));
-    base::DeleteFile(file_path_, true);
   };
   void TearDown() override { btif_keystore_ = nullptr; };
 };
 
-// Encrypt
 TEST_F(BtifKeystoreTest, test_encrypt_decrypt) {
   std::string hash = "test";
 
-  EXPECT_TRUE(btif_keystore_->Encrypt(hash, kFilename, 0));
-  std::string decrypted_hash = btif_keystore_->Decrypt(kFilename);
+  std::string encrypted_hash = btif_keystore_->Encrypt(hash, 0);
+  std::string decrypted_hash = btif_keystore_->Decrypt(encrypted_hash);
 
-  EXPECT_TRUE(base::PathExists(file_path_));
+  EXPECT_FALSE(encrypted_hash.empty());
   EXPECT_EQ(hash, decrypted_hash);
 }
 
 TEST_F(BtifKeystoreTest, test_encrypt_empty_hash) {
   std::string hash = "";
 
-  EXPECT_FALSE(btif_keystore_->Encrypt(hash, kFilename, 0));
+  std::string encrypted_hash = btif_keystore_->Encrypt(hash, 0);
 
-  EXPECT_FALSE(base::PathExists(file_path_));
+  EXPECT_TRUE(encrypted_hash.empty());
 }
 
-TEST_F(BtifKeystoreTest, test_encrypt_empty_filename) {
-  std::string hash = "test";
-
-  EXPECT_FALSE(btif_keystore_->Encrypt(hash, "", 0));
-
-  EXPECT_FALSE(base::PathExists(file_path_));
-}
-
-// Decrypt
 TEST_F(BtifKeystoreTest, test_decrypt_empty_hash) {
-  // Only way to get the hash to decrypt is to read it from the file
-  // So make empty file manually
-  std::ofstream outfile(kFilename);
-  outfile.close();
+  std::string hash = "";
 
-  std::string decrypted_hash = btif_keystore_->Decrypt(kFilename);
-
-  EXPECT_TRUE(decrypted_hash.empty());
-}
-
-TEST_F(BtifKeystoreTest, test_decrypt_file_not_exist) {
-  // Ensure file doesn't exist, then decrypt
-  EXPECT_FALSE(base::PathExists(file_path_));
-
-  std::string decrypted_hash = btif_keystore_->Decrypt(kFilename);
-
-  EXPECT_TRUE(decrypted_hash.empty());
-}
-
-TEST_F(BtifKeystoreTest, test_decrypt_empty_filename) {
-  std::string decrypted_hash = btif_keystore_->Decrypt("");
+  std::string decrypted_hash = btif_keystore_->Decrypt(hash);
 
   EXPECT_TRUE(decrypted_hash.empty());
 }
diff --git a/common/Android.bp b/common/Android.bp
index 8e077cd..0dd1fa2 100644
--- a/common/Android.bp
+++ b/common/Android.bp
@@ -1,6 +1,9 @@
 cc_library_static {
     name: "libbt-common",
-    defaults: ["fluoride_defaults"],
+    defaults: [
+        "fluoride_defaults",
+        "clang_file_coverage",
+    ],
     host_supported: true,
     include_dirs: [
         "system/bt",
@@ -8,10 +11,15 @@
     ],
     srcs: [
         "address_obfuscator.cc",
+        "alarm.cc",
+        "handler.cc",
         "message_loop_thread.cc",
         "metrics.cc",
         "once_timer.cc",
+        "reactor.cc",
+        "repeating_alarm.cc",
         "repeating_timer.cc",
+        "thread.cc",
         "time_util.cc",
     ],
     shared_libs: [
@@ -25,7 +33,10 @@
 cc_test {
     name: "bluetooth_test_common",
     test_suites: ["device-tests"],
-    defaults: ["fluoride_defaults"],
+    defaults: [
+        "fluoride_defaults",
+        "clang_coverage_bin",
+    ],
     host_supported: true,
     include_dirs: [
         "system/bt",
@@ -33,12 +44,17 @@
     ],
     srcs : [
         "address_obfuscator_unittest.cc",
+        "alarm_unittest.cc",
+        "handler_unittest.cc",
         "leaky_bonded_queue_unittest.cc",
         "message_loop_thread_unittest.cc",
         "metrics_unittest.cc",
         "once_timer_unittest.cc",
+        "reactor_unittest.cc",
+        "repeating_alarm_unittest.cc",
         "repeating_timer_unittest.cc",
         "state_machine_unittest.cc",
+        "thread_unittest.cc",
         "time_util_unittest.cc",
         "id_generator_unittest.cc",
     ],
@@ -77,12 +93,16 @@
 
 cc_benchmark {
     name: "bluetooth_benchmark_thread_performance",
-    defaults: ["fluoride_defaults"],
+    defaults: [
+        "fluoride_defaults",
+    ],
+    host_supported: true,
     include_dirs: ["system/bt"],
     srcs: [
         "benchmark/thread_performance_benchmark.cc",
     ],
     shared_libs: [
+        "libcrypto",
         "liblog",
     ],
     static_libs: [
@@ -93,14 +113,19 @@
 
 cc_benchmark {
     name: "bluetooth_benchmark_timer_performance",
-    defaults: ["fluoride_defaults"],
+    defaults: [
+        "fluoride_defaults",
+    ],
+    host_supported: false,
     include_dirs: ["system/bt"],
     srcs: [
         "benchmark/timer_performance_benchmark.cc",
     ],
     shared_libs: [
         "liblog",
+        "libcrypto",
         "libprotobuf-cpp-lite",
+        "libcrypto",
         "libcutils",
     ],
     static_libs: [
diff --git a/common/alarm.cc b/common/alarm.cc
new file mode 100644
index 0000000..247acb2
--- /dev/null
+++ b/common/alarm.cc
@@ -0,0 +1,76 @@
+/*
+ * 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 "alarm.h"
+
+#include <sys/timerfd.h>
+#include <cstring>
+
+#include "base/logging.h"
+#include "utils.h"
+
+namespace bluetooth {
+namespace common {
+
+Alarm::Alarm(Thread* thread)
+  : thread_(thread),
+    fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
+  CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
+
+  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
+}
+
+Alarm::~Alarm() {
+  thread_->GetReactor()->Unregister(token_);
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
+}
+
+void Alarm::Schedule(Closure task, std::chrono::milliseconds delay) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  long delay_ms = delay.count();
+  itimerspec timer_itimerspec{
+    {/* interval for periodic timer */},
+    {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);
+
+  task_ = std::move(task);
+}
+
+void Alarm::Cancel() {
+  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);
+}
+
+void Alarm::on_fire() {
+  std::unique_lock<std::mutex> lock(mutex_);
+  auto task = std::move(task_);
+  uint64_t times_invoked;
+  auto bytes_read = read(fd_, &times_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));
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/alarm.h b/common/alarm.h
new file mode 100644
index 0000000..1b35b8f
--- /dev/null
+++ b/common/alarm.h
@@ -0,0 +1,59 @@
+/*
+ * 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 <functional>
+#include <memory>
+#include <mutex>
+
+#include "common/thread.h"
+#include "common/utils.h"
+
+namespace bluetooth {
+namespace common {
+
+// A single-shot alarm for reactor-based thread, implemented by Linux timerfd.
+// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
+// itself from the thread.
+class Alarm {
+ public:
+  // Create and register a single-shot alarm on given thread
+  explicit Alarm(Thread* thread);
+
+  // Unregister this alarm from the thread and release resource
+  ~Alarm();
+
+  DISALLOW_COPY_AND_ASSIGN(Alarm);
+
+  // Schedule the alarm with given delay
+  void Schedule(Closure task, std::chrono::milliseconds delay);
+
+  // Cancel the alarm. No-op if it's not armed.
+  void Cancel();
+
+ private:
+  Closure task_;
+  Thread* thread_;
+  int fd_ = 0;
+  Reactor::Reactable* token_;
+  mutable std::mutex mutex_;
+  void on_fire();
+};
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/alarm_unittest.cc b/common/alarm_unittest.cc
new file mode 100644
index 0000000..25c20ad
--- /dev/null
+++ b/common/alarm_unittest.cc
@@ -0,0 +1,90 @@
+/*
+ * 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 "alarm.h"
+
+#include <future>
+
+#include "base/logging.h"
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace common {
+namespace {
+
+class AlarmTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    alarm_ = new Alarm(thread_);
+  }
+
+  void TearDown() override {
+    delete alarm_;
+    delete thread_;
+  }
+  Alarm* alarm_;
+
+ private:
+  Thread* thread_;
+};
+
+TEST_F(AlarmTest, cancel_while_not_armed) {
+  alarm_->Cancel();
+}
+
+TEST_F(AlarmTest, schedule) {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  auto before = std::chrono::steady_clock::now();
+  int delay_ms = 10;
+  int delay_error_ms = 3;
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(delay_ms));
+  future.get();
+  auto after = std::chrono::steady_clock::now();
+  auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
+  ASSERT_NEAR(duration_ms.count(), delay_ms, delay_error_ms);
+}
+
+TEST_F(AlarmTest, cancel_alarm) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(3));
+  alarm_->Cancel();
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(AlarmTest, cancel_alarm_from_callback) {
+  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(AlarmTest, schedule_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
+  future.get();
+}
+
+TEST_F(AlarmTest, delete_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
+  delete alarm_;
+  alarm_ = nullptr;
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+}
+
+}  // namespace
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/benchmark/thread_performance_benchmark.cc b/common/benchmark/thread_performance_benchmark.cc
index 74f157f..01f332f 100644
--- a/common/benchmark/thread_performance_benchmark.cc
+++ b/common/benchmark/thread_performance_benchmark.cc
@@ -23,12 +23,16 @@
 #include <memory>
 #include <thread>
 
+#include "common/handler.h"
 #include "common/message_loop_thread.h"
+#include "common/thread.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/thread.h"
 
 using ::benchmark::State;
+using bluetooth::common::Handler;
 using bluetooth::common::MessageLoopThread;
+using bluetooth::common::Thread;
 
 #define NUM_MESSAGES_TO_SEND 100000
 
@@ -419,6 +423,54 @@
   }
 };
 
+class BM_ReactorThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = new Thread("BM_ReactorThread thread", Thread::Priority::NORMAL);
+    handler_ = new Handler(thread_);
+    handler_->Post([this]() { set_up_promise_->set_value(); });
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    delete handler_;
+    handler_ = nullptr;
+    thread_->Stop();
+    delete thread_;
+    thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+
+  Thread* thread_ = nullptr;
+  Handler* handler_ = nullptr;
+};
+
+BENCHMARK_F(BM_ReactorThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      handler_->Post([this]() { callback_batch(bt_msg_queue_, nullptr); });
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_ReactorThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      handler_->Post([]() { callback_sequential(nullptr); });
+      counter_future.wait();
+    }
+  }
+};
+
 int main(int argc, char** argv) {
   // Disable LOG() output from libchrome
   logging::LoggingSettings log_settings;
diff --git a/common/benchmark/timer_performance_benchmark.cc b/common/benchmark/timer_performance_benchmark.cc
index deaaad8..2f7826b 100644
--- a/common/benchmark/timer_performance_benchmark.cc
+++ b/common/benchmark/timer_performance_benchmark.cc
@@ -20,16 +20,22 @@
 #include <benchmark/benchmark.h>
 #include <future>
 
+#include "common/alarm.h"
 #include "common/message_loop_thread.h"
 #include "common/once_timer.h"
+#include "common/repeating_alarm.h"
 #include "common/repeating_timer.h"
+#include "common/thread.h"
 #include "common/time_util.h"
 #include "osi/include/alarm.h"
 
 using ::benchmark::State;
+using bluetooth::common::Alarm;
 using bluetooth::common::MessageLoopThread;
 using bluetooth::common::OnceTimer;
+using bluetooth::common::RepeatingAlarm;
 using bluetooth::common::RepeatingTimer;
+using bluetooth::common::Thread;
 using bluetooth::common::time_get_os_boottime_us;
 
 // fake get_main_message_loop implementation for alarm
@@ -268,6 +274,88 @@
     ->Iterations(1)
     ->UseRealTime();
 
+class BM_ReactableAlarm : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    thread_ = std::make_unique<Thread>("timer_benchmark", Thread::Priority::REAL_TIME);
+    alarm_ = std::make_unique<Alarm>(thread_.get());
+    repeating_alarm_ = std::make_unique<RepeatingAlarm>(thread_.get());
+    g_map.clear();
+    g_promise = std::make_shared<std::promise<void>>();
+    g_scheduled_tasks = 0;
+    g_task_length = 0;
+    g_task_interval = 0;
+    g_task_counter = 0;
+  }
+
+  void TearDown(State& st) override {
+    g_promise = nullptr;
+    alarm_ = nullptr;
+    repeating_alarm_ = nullptr;
+    thread_->Stop();
+    thread_ = nullptr;
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  std::unique_ptr<Thread> thread_;
+  std::unique_ptr<Alarm> alarm_;
+  std::unique_ptr<RepeatingAlarm> repeating_alarm_;
+};
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, timer_performance_ms)(State& state) {
+  auto milliseconds = static_cast<int>(state.range(0));
+  for (auto _ : state) {
+    auto start_time_point = time_get_os_boottime_us();
+    alarm_->Schedule(std::bind(TimerFire, nullptr), std::chrono::milliseconds(milliseconds));
+    g_promise->get_future().get();
+    auto end_time_point = time_get_os_boottime_us();
+    auto duration = end_time_point - start_time_point;
+    state.SetIterationTime(duration * 1e-6);
+    alarm_->Cancel();
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, timer_performance_ms)
+    ->Arg(1)
+    ->Arg(5)
+    ->Arg(10)
+    ->Arg(20)
+    ->Arg(100)
+    ->Arg(1000)
+    ->Arg(2000)
+    ->Iterations(1)
+    ->UseRealTime();
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, periodic_accuracy)
+(State& state) {
+  for (auto _ : state) {
+    g_scheduled_tasks = state.range(0);
+    g_task_length = state.range(1);
+    g_task_interval = state.range(2);
+    g_start_time = time_get_os_boottime_us();
+    repeating_alarm_->Schedule([] { AlarmSleepAndCountDelayedTime(nullptr); },
+                               std::chrono::milliseconds(g_task_interval));
+    g_promise->get_future().get();
+    repeating_alarm_->Cancel();
+  }
+  for (const auto& delay : g_map) {
+    state.counters[std::to_string(delay.first)] = delay.second;
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, periodic_accuracy)
+    ->Args({2000, 1, 5})
+    ->Args({2000, 3, 5})
+    ->Args({2000, 1, 7})
+    ->Args({2000, 3, 7})
+    ->Args({2000, 1, 20})
+    ->Args({2000, 5, 20})
+    ->Args({2000, 10, 20})
+    ->Args({2000, 15, 20})
+    ->Iterations(1)
+    ->UseRealTime();
+
 int main(int argc, char** argv) {
   // Disable LOG() output from libchrome
   logging::LoggingSettings log_settings;
diff --git a/common/handler.cc b/common/handler.cc
new file mode 100644
index 0000000..219dd82
--- /dev/null
+++ b/common/handler.cc
@@ -0,0 +1,87 @@
+/*
+ * 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 "handler.h"
+
+#include <sys/eventfd.h>
+#include <cstring>
+
+#include "base/logging.h"
+
+#include "reactor.h"
+#include "utils.h"
+
+#ifndef EFD_SEMAPHORE
+#define EFD_SEMAPHORE 1
+#endif
+
+namespace bluetooth {
+namespace common {
+
+Handler::Handler(Thread* thread)
+  : thread_(thread),
+    fd_(eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) {
+  CHECK_NE(fd_, -1) << __func__ << ": cannot create eventfd: " << strerror(errno);
+
+  reactable_ = thread_->GetReactor()->Register(fd_, [this] { this->handle_next_event(); }, nullptr);
+}
+
+Handler::~Handler() {
+  thread_->GetReactor()->Unregister(reactable_);
+  reactable_ = nullptr;
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  CHECK_NE(close_status, -1) << __func__ << ": cannot close eventfd: " << strerror(errno);
+}
+
+void Handler::Post(Closure closure) {
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    tasks_.emplace(std::move(closure));
+  }
+  uint64_t val = 1;
+  auto write_result = eventfd_write(fd_, val);
+  CHECK_NE(write_result, -1) << __func__ << ": failed to write: " << strerror(errno);
+}
+
+void Handler::Clear() {
+  std::lock_guard<std::mutex> lock(mutex_);
+
+  std::queue<Closure> empty;
+  std::swap(tasks_, empty);
+
+  uint64_t val;
+  while (eventfd_read(fd_, &val) == 0) {
+  }
+}
+
+void Handler::handle_next_event() {
+  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);
+
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    closure = std::move(tasks_.front());
+    tasks_.pop();
+  }
+  closure();
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/handler.h b/common/handler.h
new file mode 100644
index 0000000..71b4dba
--- /dev/null
+++ b/common/handler.h
@@ -0,0 +1,59 @@
+/*
+ * 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 <functional>
+#include <memory>
+#include <mutex>
+#include <queue>
+
+#include "common/thread.h"
+#include "common/utils.h"
+
+namespace bluetooth {
+namespace common {
+
+// A message-queue style handler for reactor-based thread to handle incoming events from different threads. When it's
+// constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister itself
+// from the thread.
+class Handler {
+ public:
+  // Create and register a handler on given thread
+  explicit Handler(Thread* thread);
+
+  // Unregister this handler from the thread and release resource. Unhandled events will be discarded and not executed.
+  ~Handler();
+
+  DISALLOW_COPY_AND_ASSIGN(Handler);
+
+  // Enqueue a closure to the queue of this handler
+  void Post(Closure closure);
+
+  // Remove all pending events from the queue of this handler
+  void Clear();
+
+ private:
+  std::queue<Closure> tasks_;
+  Thread* thread_;
+  int fd_;
+  Reactor::Reactable* reactable_;
+  mutable std::mutex mutex_;
+  void handle_next_event();
+};
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/handler_unittest.cc b/common/handler_unittest.cc
new file mode 100644
index 0000000..c51e51b
--- /dev/null
+++ b/common/handler_unittest.cc
@@ -0,0 +1,71 @@
+/*
+ * 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 "handler.h"
+
+#include <sys/eventfd.h>
+#include <thread>
+
+#include <gtest/gtest.h>
+#include "base/logging.h"
+
+namespace bluetooth {
+namespace common {
+namespace {
+
+class HandlerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    handler_ = new Handler(thread_);
+  }
+  void TearDown() override {
+    delete handler_;
+    delete thread_;
+  }
+
+  Handler* handler_;
+  Thread* thread_;
+};
+
+TEST_F(HandlerTest, empty) {}
+
+TEST_F(HandlerTest, post_task_invoked) {
+  int val = 0;
+  Closure closure = [&val]() { val++; };
+  handler_->Post(closure);
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+  EXPECT_EQ(val, 1);
+}
+
+TEST_F(HandlerTest, post_task_cleared) {
+  int val = 0;
+  Closure closure = [&val]() {
+    val++;
+    std::this_thread::sleep_for(std::chrono::milliseconds(5));
+  };
+  handler_->Post(std::move(closure));
+  closure = []() { LOG(FATAL) << "Should not happen"; };
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+  handler_->Post(std::move(closure));
+  handler_->Clear();
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+  EXPECT_EQ(val, 1);
+}
+
+}  // namespace
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/reactor.cc b/common/reactor.cc
new file mode 100644
index 0000000..61cc7d6
--- /dev/null
+++ b/common/reactor.cc
@@ -0,0 +1,212 @@
+/*
+ * 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 "reactor.h"
+
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+#include <algorithm>
+#include <cerrno>
+#include <cstring>
+
+#include "base/logging.h"
+
+namespace {
+
+// Use at most sizeof(epoll_event) * kEpollMaxEvents kernel memory
+constexpr int kEpollMaxEvents = 64;
+
+}  // namespace
+
+namespace bluetooth {
+namespace common {
+
+class Reactor::Reactable {
+ public:
+  Reactable(int fd, Closure on_read_ready, Closure on_write_ready)
+      : fd_(fd),
+        on_read_ready_(std::move(on_read_ready)),
+        on_write_ready_(std::move(on_write_ready)),
+        is_executing_(false) {}
+  const int fd_;
+  Closure on_read_ready_;
+  Closure on_write_ready_;
+  bool is_executing_;
+  std::recursive_mutex lock_;
+};
+
+Reactor::Reactor()
+  : epoll_fd_(0),
+    control_fd_(0),
+    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);
+
+  control_fd_ = eventfd(0, EFD_NONBLOCK);
+  CHECK_NE(control_fd_, -1) << __func__ << ": cannot create control_fd: " << strerror(errno);
+
+  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);
+}
+
+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);
+
+  RUN_NO_INTR(result = close(control_fd_));
+  CHECK_NE(result, -1) << __func__ << ": cannot close control_fd: " << strerror(errno);
+
+  RUN_NO_INTR(result = close(epoll_fd_));
+  CHECK_NE(result, -1) << __func__ << ": cannot close epoll_fd: " << strerror(errno);
+}
+
+void Reactor::Run() {
+  bool previously_running = is_running_.exchange(true);
+  CHECK_EQ(previously_running, false) << __func__ << ": already running";
+  LOG(INFO) << __func__ << ": started";
+
+  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);
+
+    for (int i = 0; i < count; ++i) {
+      auto event = events[i];
+      CHECK_NE(event.events, 0u) << __func__ << ": no result in epoll result";
+
+      // 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;
+      }
+      auto* reactable = static_cast<Reactor::Reactable*>(event.data.ptr);
+      {
+        std::unique_lock<std::mutex> lock(mutex_);
+        // See if this reactable has been removed in the meantime.
+        if (std::find(invalidation_list_.begin(), invalidation_list_.end(), reactable) != invalidation_list_.end()) {
+          continue;
+        }
+
+        std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
+        lock.unlock();
+        reactable_removed_ = false;
+        reactable->is_executing_ = true;
+        if (event.events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && reactable->on_read_ready_ != nullptr) {
+          reactable->on_read_ready_();
+        }
+        if (!reactable_removed_ && event.events & EPOLLOUT && reactable->on_write_ready_ != nullptr) {
+          reactable->on_write_ready_();
+        }
+        reactable->is_executing_ = false;
+      }
+      if (reactable_removed_) {
+        delete reactable;
+      }
+    }
+  }
+}
+
+void Reactor::Stop() {
+  if (!is_running_) {
+    LOG(WARNING) << __func__ << ": not running, will stop once it's started";
+  }
+  auto control = eventfd_write(control_fd_, 1);
+  CHECK_NE(control, -1) << __func__ << ": failed: " << strerror(errno);
+}
+
+Reactor::Reactable* Reactor::Register(int fd, Closure on_read_ready, Closure on_write_ready) {
+  uint32_t poll_event_type = 0;
+  if (on_read_ready != nullptr) {
+    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
+  }
+  if (on_write_ready != nullptr) {
+    poll_event_type |= EPOLLOUT;
+  }
+  auto* reactable = new Reactable(fd, on_read_ready, on_write_ready);
+  epoll_event event = {
+      .events = poll_event_type,
+      {.ptr = reactable}
+  };
+  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);
+  return reactable;
+}
+
+void Reactor::Unregister(Reactor::Reactable* reactable) {
+  CHECK_NE(reactable, nullptr);
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    invalidation_list_.push_back(reactable);
+  }
+  {
+    int result;
+    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);
+    }
+    // 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.
+    if (reactable->is_executing_) {
+      reactable_removed_ = true;
+    }
+  }
+  // If we are unregistering outside of the callback event from this reactable, we delete it now
+  if (!reactable_removed_) {
+    delete reactable;
+  }
+}
+
+void Reactor::ModifyRegistration(Reactor::Reactable* reactable, Closure on_read_ready, Closure on_write_ready) {
+  CHECK_NE(reactable, nullptr);
+
+  uint32_t poll_event_type = 0;
+  if (on_read_ready != nullptr) {
+    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
+  }
+  if (on_write_ready != nullptr) {
+    poll_event_type |= EPOLLOUT;
+  }
+  {
+    std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
+    reactable->on_read_ready_ = std::move(on_read_ready);
+    reactable->on_write_ready_ = std::move(on_write_ready);
+  }
+  epoll_event event = {
+      .events = poll_event_type,
+      {.ptr = reactable}
+  };
+  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);
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/reactor.h b/common/reactor.h
new file mode 100644
index 0000000..27528ce
--- /dev/null
+++ b/common/reactor.h
@@ -0,0 +1,78 @@
+/*
+ * 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 <sys/epoll.h>
+#include <atomic>
+#include <functional>
+#include <list>
+#include <mutex>
+#include <thread>
+
+#include "common/utils.h"
+
+namespace bluetooth {
+namespace common {
+
+// Format of closure to be used in the entire stack
+using Closure = std::function<void()>;
+
+// A simple implementation of reactor-style looper.
+// When a reactor is running, the main loop is polling and blocked until at least one registered reactable is ready to
+// read or write. It will invoke on_read_ready() or on_write_ready(), which is registered with the reactor. Then, it
+// blocks again until ready event.
+class Reactor {
+ public:
+  // An object used for Unregister() and ModifyRegistration()
+  class Reactable;
+
+  // Construct a reactor on the current thread
+  Reactor();
+
+  // Destruct this reactor and release its resources
+  ~Reactor();
+
+  DISALLOW_COPY_AND_ASSIGN(Reactor);
+
+  // Start the reactor. The current thread will be blocked until Stop() is invoked and handled.
+  void Run();
+
+  // Stop the reactor. Must be invoked from a different thread. Note: all registered reactables will not be unregistered
+  // by Stop(). If the reactor is not running, it will be stopped once it's started.
+  void Stop();
+
+  // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this object to
+  // unregister or modify registration. Ownership of the memory space is NOT transferred to user.
+  Reactable* Register(int fd, Closure on_read_ready, Closure on_write_ready);
+
+  // Unregister a reactable from this reactor
+  void Unregister(Reactable* reactable);
+
+  // Modify the registration for a reactable with given reactable
+  void ModifyRegistration(Reactable* reactable, Closure on_read_ready, Closure on_write_ready);
+
+ private:
+  mutable std::mutex mutex_;
+  int epoll_fd_;
+  int control_fd_;
+  std::atomic<bool> is_running_;
+  std::list<Reactable*> invalidation_list_;
+  bool reactable_removed_;
+};
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/reactor_unittest.cc b/common/reactor_unittest.cc
new file mode 100644
index 0000000..5c7e90e
--- /dev/null
+++ b/common/reactor_unittest.cc
@@ -0,0 +1,283 @@
+/*
+ * 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 "reactor.h"
+
+#include <sys/eventfd.h>
+#include <chrono>
+#include <future>
+#include <thread>
+
+#include "base/logging.h"
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace common {
+namespace {
+
+constexpr int kReadReadyValue = 100;
+
+std::promise<int>* g_promise;
+
+class ReactorTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    g_promise = new std::promise<int>;
+    reactor_ = new Reactor;
+  }
+
+  void TearDown() override {
+    delete g_promise;
+    g_promise = nullptr;
+    delete reactor_;
+    reactor_ = nullptr;
+  }
+
+  Reactor* reactor_;
+};
+
+class SampleReactable {
+ public:
+  SampleReactable() : fd_(eventfd(0, EFD_NONBLOCK)) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~SampleReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {}
+
+  void OnWriteReady() {}
+
+  int fd_;
+};
+
+class FakeReactable {
+ public:
+  enum EventFdValue {
+    kSetPromise = 1,
+    kRegisterSampleReactable,
+    kUnregisterSampleReactable,
+    kSampleOutputValue,
+  };
+  FakeReactable() : fd_(eventfd(0, 0)), reactor_(nullptr) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  FakeReactable(Reactor* reactor) : fd_(eventfd(0, 0)), reactor_(reactor) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~FakeReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {
+    uint64_t value = 0;
+    auto read_result = eventfd_read(fd_, &value);
+    EXPECT_EQ(read_result, 0);
+    if (value == kSetPromise && g_promise != nullptr) {
+      g_promise->set_value(kReadReadyValue);
+    }
+    if (value == kRegisterSampleReactable) {
+      reactable_ = reactor_->Register(sample_reactable_.fd_, [this] { this->sample_reactable_.OnReadReady(); },
+                                      [this] { this->sample_reactable_.OnWriteReady(); });
+      g_promise->set_value(kReadReadyValue);
+    }
+    if (value == kUnregisterSampleReactable) {
+      reactor_->Unregister(reactable_);
+      g_promise->set_value(kReadReadyValue);
+    }
+  }
+
+  void OnWriteReady() {
+    auto write_result = eventfd_write(fd_, output_data_);
+    output_data_ = 0;
+    EXPECT_EQ(write_result, 0);
+  }
+
+  SampleReactable sample_reactable_;
+  Reactor::Reactable* reactable_ = nullptr;
+  int fd_;
+
+ private:
+  Reactor* reactor_;
+  uint64_t output_data_ = kSampleOutputValue;
+};
+
+TEST_F(ReactorTest, start_and_stop) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, stop_and_start) {
+  auto reactor_thread = std::thread(&Reactor::Stop, reactor_);
+  auto another_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_thread.join();
+  another_thread.join();
+}
+
+TEST_F(ReactorTest, stop_multi_times) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  for (int i = 0; i < 5; i++) {
+    reactor_->Stop();
+  }
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, cold_register_only) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, cold_register) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_register_from_different_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_unregister_from_different_thread) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Unregister(reactable);
+  auto future = g_promise->get_future();
+
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  future.wait_for(std::chrono::milliseconds(10));
+  g_promise->set_value(2);
+  EXPECT_EQ(future.get(), 2);
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, hot_register_from_same_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable(reactor_);
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_unregister_from_same_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable(reactor_);
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  delete g_promise;
+  g_promise = new std::promise<int>;
+  future = g_promise->get_future();
+  write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  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) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Stop();
+  reactor_thread.join();
+  for (int i = 0; i < 5; i++) {
+    reactor_thread = std::thread(&Reactor::Run, reactor_);
+    reactor_->Stop();
+    reactor_thread.join();
+  }
+}
+
+TEST_F(ReactorTest, on_write_ready) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  uint64_t value = 0;
+  auto read_result = eventfd_read(fake_reactable.fd_, &value);
+  EXPECT_EQ(read_result, 0);
+  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
+
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, modify_registration) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  reactor_->ModifyRegistration(reactable, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  uint64_t value = 0;
+  auto read_result = eventfd_read(fake_reactable.fd_, &value);
+  EXPECT_EQ(read_result, 0);
+  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
+
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+}  // namespace
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/repeating_alarm.cc b/common/repeating_alarm.cc
new file mode 100644
index 0000000..65c9b3a
--- /dev/null
+++ b/common/repeating_alarm.cc
@@ -0,0 +1,75 @@
+/*
+ * 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 "repeating_alarm.h"
+
+#include <sys/timerfd.h>
+#include <cstring>
+
+#include "base/logging.h"
+#include "utils.h"
+
+namespace bluetooth {
+namespace common {
+
+RepeatingAlarm::RepeatingAlarm(Thread* thread)
+  : thread_(thread),
+    fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
+  CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
+
+  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
+}
+
+RepeatingAlarm::~RepeatingAlarm() {
+  thread_->GetReactor()->Unregister(token_);
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
+}
+
+void RepeatingAlarm::Schedule(Closure task, std::chrono::milliseconds period) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  long period_ms = period.count();
+  itimerspec timer_itimerspec{
+    {period_ms / 1000, period_ms % 1000 * 1000000},
+    {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);
+
+  task_ = std::move(task);
+}
+
+void RepeatingAlarm::Cancel() {
+  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);
+}
+
+void RepeatingAlarm::on_fire() {
+  std::unique_lock<std::mutex> lock(mutex_);
+  auto task = task_;
+  uint64_t times_invoked;
+  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
+  lock.unlock();
+  task();
+  CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/repeating_alarm.h b/common/repeating_alarm.h
new file mode 100644
index 0000000..f1f6aa1
--- /dev/null
+++ b/common/repeating_alarm.h
@@ -0,0 +1,58 @@
+/*
+ * 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 <functional>
+#include <memory>
+#include <mutex>
+
+#include "common/thread.h"
+#include "common/utils.h"
+
+namespace bluetooth {
+namespace common {
+
+// A repeating alarm for reactor-based thread, implemented by Linux timerfd.
+// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
+// itself from the thread.
+class RepeatingAlarm {
+ public:
+  // Create and register a repeating alarm on given thread
+  explicit RepeatingAlarm(Thread* thread);
+
+  // Unregister this alarm from the thread and release resource
+  ~RepeatingAlarm();
+
+  DISALLOW_COPY_AND_ASSIGN(RepeatingAlarm);
+
+  // Schedule a repeating alarm with given period
+  void Schedule(Closure task, std::chrono::milliseconds period);
+
+  // Cancel the alarm. No-op if it's not armed.
+  void Cancel();
+
+ private:
+  Closure task_;
+  Thread* thread_;
+  int fd_ = 0;
+  Reactor::Reactable* token_;
+  mutable std::mutex mutex_;
+  void on_fire();
+};
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/repeating_alarm_unittest.cc b/common/repeating_alarm_unittest.cc
new file mode 100644
index 0000000..3c0f255
--- /dev/null
+++ b/common/repeating_alarm_unittest.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 "repeating_alarm.h"
+
+#include <future>
+
+#include "base/logging.h"
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace common {
+namespace {
+
+constexpr int error_ms = 20;
+
+class RepeatingAlarmTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    alarm_ = new RepeatingAlarm(thread_);
+  }
+
+  void TearDown() override {
+    delete alarm_;
+    delete thread_;
+  }
+
+  void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
+    std::promise<void> promise;
+    auto future = promise.get_future();
+    auto start_time = std::chrono::steady_clock::now();
+    int counter = 0;
+    alarm_->Schedule(
+        [&counter, &promise, start_time, scheduled_tasks, task_length_ms, interval_between_tasks_ms]() {
+          counter++;
+          auto time_now = std::chrono::steady_clock::now();
+          auto time_delta = time_now - start_time;
+          if (counter == scheduled_tasks) {
+            promise.set_value();
+          }
+          ASSERT_NEAR(time_delta.count(), interval_between_tasks_ms * 1000000 * counter, error_ms * 1000000);
+          std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
+        },
+        std::chrono::milliseconds(interval_between_tasks_ms));
+    future.get();
+    alarm_->Cancel();
+  }
+
+  RepeatingAlarm* alarm_;
+
+ private:
+  Thread* thread_;
+};
+
+TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
+  alarm_->Cancel();
+}
+
+TEST_F(RepeatingAlarmTest, schedule) {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  auto before = std::chrono::steady_clock::now();
+  int period_ms = 10;
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(period_ms));
+  future.get();
+  alarm_->Cancel();
+  auto after = std::chrono::steady_clock::now();
+  auto duration = after - before;
+  ASSERT_NEAR(duration.count(), period_ms * 1000000, error_ms * 1000000);
+}
+
+TEST_F(RepeatingAlarmTest, cancel_alarm) {
+  alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
+  alarm_->Cancel();
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
+  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
+  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));
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
+  future.get();
+  alarm_->Cancel();
+}
+
+TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
+  alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
+  delete alarm_;
+  alarm_ = nullptr;
+  std::this_thread::sleep_for(std::chrono::milliseconds(1));
+}
+
+TEST_F(RepeatingAlarmTest, verify_small) {
+  VerifyMultipleDelayedTasks(100, 1, 10);
+}
+
+TEST_F(RepeatingAlarmTest, verify_large) {
+  VerifyMultipleDelayedTasks(100, 3, 10);
+}
+
+}  // namespace
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/thread.cc b/common/thread.cc
new file mode 100644
index 0000000..2cb2205
--- /dev/null
+++ b/common/thread.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 "common/thread.h"
+
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <cerrno>
+#include <cstring>
+
+#include "base/logging.h"
+
+namespace bluetooth {
+namespace common {
+
+namespace {
+constexpr int kRealTimeFifoSchedulingPriority = 1;
+}
+
+Thread::Thread(const std::string& name, const Priority priority)
+    : name_(name),
+      reactor_(),
+      running_thread_(&Thread::run, this, priority) {}
+
+void Thread::run(Priority priority) {
+  if (priority == Priority::REAL_TIME) {
+    struct sched_param rt_params = {.sched_priority = kRealTimeFifoSchedulingPriority};
+    auto linux_tid = static_cast<pid_t>(syscall(SYS_gettid));
+    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);
+    }
+  }
+  reactor_.Run();
+}
+
+Thread::~Thread() {
+  Stop();
+}
+
+bool Thread::Stop() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  CHECK_NE(std::this_thread::get_id(), running_thread_.get_id());
+
+  if (!running_thread_.joinable()) {
+    return false;
+  }
+  reactor_.Stop();
+  running_thread_.join();
+  return true;
+}
+
+bool Thread::IsSameThread() const {
+  return std::this_thread::get_id() == running_thread_.get_id();
+}
+
+Reactor* Thread::GetReactor() const {
+  return &reactor_;
+}
+
+std::string Thread::GetThreadName() const {
+  return name_;
+}
+
+std::string Thread::ToString() const {
+  return "Thread " + name_;
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/thread.h b/common/thread.h
new file mode 100644
index 0000000..09e6b48
--- /dev/null
+++ b/common/thread.h
@@ -0,0 +1,75 @@
+/*
+ * 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 <mutex>
+#include <string>
+#include <thread>
+
+#include "common/reactor.h"
+#include "common/utils.h"
+
+namespace bluetooth {
+namespace common {
+
+// Reactor-based looper thread implementation. The thread runs immediately after it is constructed, and stops after
+// Stop() is invoked. To assign task to this thread, user needs to register a reactable object to the underlying
+// reactor.
+class Thread {
+ public:
+  // Used by thread constructor. Suggest the priority to the kernel scheduler. Use REAL_TIME if we need (soft) real-time
+  // scheduling guarantee for this thread; use NORMAL if no real-time guarantee is needed to save CPU time slice for
+  // other threads
+  enum class Priority {
+    REAL_TIME,
+    NORMAL,
+  };
+
+  // name: thread name for POSIX systems
+  // priority: priority for kernel scheduler
+  Thread(const std::string& name, Priority priority);
+
+  // Stop and destroy this thread
+  ~Thread();
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+
+  // Stop this thread. Must be invoked from another thread. After this thread is stopped, it cannot be started again.
+  bool Stop();
+
+  // Return true if this function is invoked from this thread
+  bool IsSameThread() const;
+
+  // Return the POSIX thread name
+  std::string GetThreadName() const;
+
+  // Return a user-friendly string representation of this thread object
+  std::string ToString() const;
+
+  // Return the pointer of underlying reactor. The ownership is NOT transferred.
+  Reactor* GetReactor() const;
+
+ private:
+  void run(Priority priority);
+  mutable std::mutex mutex_;
+  const std::string name_;
+  mutable Reactor reactor_;
+  std::thread running_thread_;
+};
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/thread_unittest.cc b/common/thread_unittest.cc
new file mode 100644
index 0000000..678f34d
--- /dev/null
+++ b/common/thread_unittest.cc
@@ -0,0 +1,99 @@
+/*
+ * 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 "thread.h"
+
+#include <sys/eventfd.h>
+
+#include "base/logging.h"
+#include "gtest/gtest.h"
+#include "reactor.h"
+
+namespace bluetooth {
+namespace common {
+namespace {
+
+constexpr int kCheckIsSameThread = 1;
+
+class SampleReactable {
+ public:
+  explicit SampleReactable(Thread* thread) : thread_(thread), fd_(eventfd(0, 0)), is_same_thread_checked_(false) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~SampleReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {
+    EXPECT_TRUE(thread_->IsSameThread());
+    is_same_thread_checked_ = true;
+    uint64_t val;
+    eventfd_read(fd_, &val);
+  }
+
+  bool IsSameThreadCheckDone() {
+    return is_same_thread_checked_;
+  }
+
+  Thread* thread_;
+  int fd_;
+  bool is_same_thread_checked_;
+};
+
+class ThreadTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread = new Thread("test", Thread::Priority::NORMAL);
+  }
+
+  void TearDown() override {
+    delete thread;
+  }
+  Thread* thread = nullptr;
+};
+
+TEST_F(ThreadTest, just_stop_no_op) {
+  thread->Stop();
+}
+
+TEST_F(ThreadTest, thread_name) {
+  EXPECT_EQ(thread->GetThreadName(), "test");
+}
+
+TEST_F(ThreadTest, thread_to_string) {
+  EXPECT_NE(thread->ToString().find("test"), std::string::npos);
+}
+
+TEST_F(ThreadTest, not_same_thread) {
+  EXPECT_FALSE(thread->IsSameThread());
+}
+
+TEST_F(ThreadTest, same_thread) {
+  Reactor* reactor = thread->GetReactor();
+  SampleReactable sample_reactable(thread);
+  auto* reactable =
+      reactor->Register(sample_reactable.fd_, std::bind(&SampleReactable::OnReadReady, &sample_reactable), nullptr);
+  int fd = sample_reactable.fd_;
+  int write_result = eventfd_write(fd, kCheckIsSameThread);
+  EXPECT_EQ(write_result, 0);
+  while (!sample_reactable.IsSameThreadCheckDone()) std::this_thread::yield();
+  reactor->Unregister(reactable);
+}
+
+}  // namespace
+}  // namespace common
+}  // namespace bluetooth
diff --git a/common/utils.h b/common/utils.h
new file mode 100644
index 0000000..26e8f23
--- /dev/null
+++ b/common/utils.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+// A macro to re-try a syscall when it receives EINTR
+#ifndef RUN_NO_INTR
+#define RUN_NO_INTR(fn) \
+  do {                  \
+  } while ((fn) == -1 && errno == EINTR)
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+#endif
diff --git a/osi/include/config.h b/osi/include/config.h
index 55adecb..47c3a3e 100644
--- a/osi/include/config.h
+++ b/osi/include/config.h
@@ -49,6 +49,9 @@
 // file on the filesystem.
 std::unique_ptr<config_t> config_new(const char* filename);
 
+// Read the checksum from the |filename|
+std::string checksum_read(const char* filename);
+
 // Clones |src|, including all of it's sections, keys, and values.
 // Returns a new config which is a copy and separated from the original;
 // changes to the new config are not reflected in any way in the original.
@@ -133,3 +136,8 @@
 // |config_save|, all comments and special formatting in the original file will
 // be lost. Neither |config| nor |filename| may be NULL.
 bool config_save(const config_t& config, const std::string& filename);
+
+// Saves the encrypted |checksum| of config file to a given |filename| Note
+// that this could be a destructive operation: if |filename| already exists,
+// it will be overwritten.
+bool checksum_save(const std::string& checksum, const std::string& filename);
diff --git a/osi/src/config.cc b/osi/src/config.cc
index e937959..de7e6e6 100644
--- a/osi/src/config.cc
+++ b/osi/src/config.cc
@@ -18,7 +18,7 @@
 
 #include "osi/include/config.h"
 
-#include <base/files/file_path.h>
+#include <base/files/file_util.h>
 #include <base/logging.h>
 #include <ctype.h>
 #include <errno.h>
@@ -84,6 +84,19 @@
   return config;
 }
 
+std::string checksum_read(const char* filename) {
+  base::FilePath path(filename);
+  if (!base::PathExists(path)) {
+    LOG(ERROR) << __func__ << ": unable to locate file '" << filename << "'";
+    return "";
+  }
+  std::string encrypted_hash;
+  if (!base::ReadFileToString(path, &encrypted_hash)) {
+    LOG(ERROR) << __func__ << ": unable to read file '" << filename << "'";
+  }
+  return encrypted_hash;
+}
+
 std::unique_ptr<config_t> config_new_clone(const config_t& src) {
   std::unique_ptr<config_t> ret = config_new_empty();
 
@@ -332,6 +345,107 @@
   return false;
 }
 
+bool checksum_save(const std::string& checksum, const std::string& filename) {
+  CHECK(!checksum.empty()) << __func__ << ": checksum cannot be empty";
+  CHECK(!filename.empty()) << __func__ << ": filename cannot be empty";
+
+  // Steps to ensure content of config checksum file gets to disk:
+  //
+  // 1) Open and write to temp file (e.g.
+  // bt_config.conf.encrypted-checksum.new). 2) Sync the temp file to disk with
+  // fsync(). 3) Rename temp file to actual config checksum file (e.g.
+  // bt_config.conf.encrypted-checksum).
+  //    This ensures atomic update.
+  // 4) Sync directory that has the conf file with fsync().
+  //    This ensures directory entries are up-to-date.
+  FILE* fp = nullptr;
+  int dir_fd = -1;
+
+  // Build temp config checksum file based on config checksum file (e.g.
+  // bt_config.conf.encrypted-checksum.new).
+  const std::string temp_filename = filename + ".new";
+  base::FilePath path(temp_filename);
+
+  // Extract directory from file path (e.g. /data/misc/bluedroid).
+  const std::string directoryname = base::FilePath(filename).DirName().value();
+  if (directoryname.empty()) {
+    LOG(ERROR) << __func__ << ": error extracting directory from '" << filename
+               << "': " << strerror(errno);
+    goto error2;
+  }
+
+  dir_fd = open(directoryname.c_str(), O_RDONLY);
+  if (dir_fd < 0) {
+    LOG(ERROR) << __func__ << ": unable to open dir '" << directoryname
+               << "': " << strerror(errno);
+    goto error2;
+  }
+
+  if (base::WriteFile(path, checksum.data(), checksum.size()) !=
+      (int)checksum.size()) {
+    LOG(ERROR) << __func__ << ": unable to write file '" << filename.c_str();
+    goto error2;
+  }
+
+  fp = fopen(temp_filename.c_str(), "rb");
+  if (!fp) {
+    LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename
+               << "': " << strerror(errno);
+    goto error2;
+  }
+
+  // Sync written temp file out to disk. fsync() is blocking until data makes it
+  // to disk.
+  if (fsync(fileno(fp)) < 0) {
+    LOG(WARNING) << __func__ << ": unable to fsync file '" << temp_filename
+                 << "': " << strerror(errno);
+  }
+
+  if (fclose(fp) == EOF) {
+    LOG(ERROR) << __func__ << ": unable to close file '" << temp_filename
+               << "': " << strerror(errno);
+    goto error2;
+  }
+  fp = nullptr;
+
+  // Change the file's permissions to Read/Write by User and Group
+  if (chmod(temp_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) ==
+      -1) {
+    LOG(ERROR) << __func__ << ": unable to change file permissions '"
+               << filename << "': " << strerror(errno);
+    goto error2;
+  }
+
+  // Rename written temp file to the actual config file.
+  if (rename(temp_filename.c_str(), filename.c_str()) == -1) {
+    LOG(ERROR) << __func__ << ": unable to commit file '" << filename
+               << "': " << strerror(errno);
+    goto error2;
+  }
+
+  // This should ensure the directory is updated as well.
+  if (fsync(dir_fd) < 0) {
+    LOG(WARNING) << __func__ << ": unable to fsync dir '" << directoryname
+                 << "': " << strerror(errno);
+  }
+
+  if (close(dir_fd) < 0) {
+    LOG(ERROR) << __func__ << ": unable to close dir '" << directoryname
+               << "': " << strerror(errno);
+    goto error2;
+  }
+
+  return true;
+
+error2:
+  // This indicates there is a write issue.  Unlink as partial data is not
+  // acceptable.
+  unlink(temp_filename.c_str());
+  if (fp) fclose(fp);
+  if (dir_fd != -1) close(dir_fd);
+  return false;
+}
+
 static char* trim(char* str) {
   while (isspace(*str)) ++str;
 
diff --git a/osi/test/config_test.cc b/osi/test/config_test.cc
index 58ce818..7cf4db8 100644
--- a/osi/test/config_test.cc
+++ b/osi/test/config_test.cc
@@ -1,3 +1,4 @@
+#include <base/files/file_util.h>
 #include <gtest/gtest.h>
 
 #include "AllocationTestHarness.h"
@@ -173,3 +174,24 @@
   std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
   EXPECT_TRUE(config_save(*config, CONFIG_FILE));
 }
+
+TEST_F(ConfigTest, checksum_read) {
+  std::string filename = "/data/misc/bluedroid/test.checksum";
+  std::string checksum = "0x1234";
+  base::FilePath file_path(filename);
+
+  EXPECT_EQ(base::WriteFile(file_path, checksum.data(), checksum.size()),
+            (int)checksum.size());
+
+  EXPECT_EQ(checksum_read(filename.c_str()), checksum.c_str());
+}
+
+TEST_F(ConfigTest, checksum_save) {
+  std::string filename = "/data/misc/bluedroid/test.checksum";
+  std::string checksum = "0x1234";
+  base::FilePath file_path(filename);
+
+  EXPECT_TRUE(checksum_save(checksum, filename));
+
+  EXPECT_TRUE(base::PathExists(file_path));
+}
diff --git a/stack/Android.bp b/stack/Android.bp
index 9f03b39..53076bb 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -202,6 +202,7 @@
         "test/stack_a2dp_test.cc",
     ],
     shared_libs: [
+        "libcrypto",
         "libhidlbase",
         "liblog",
         "libprotobuf-cpp-lite",
diff --git a/test/gen_coverage.py b/test/gen_coverage.py
index b1c9a2f..3697c37 100755
--- a/test/gen_coverage.py
+++ b/test/gen_coverage.py
@@ -79,6 +79,11 @@
         "covered_files": [
             "system/bt/vendor_libs/test_vendor_lib/packets",
         ],
+    }, {
+        "test_name": "bluetooth_test_common",
+        "covered_files": [
+            "system/bt/common",
+        ],
     },
 ]