BluetoothHAL: Reset the chip on open(), close once

Sending a reset and discarding extra packets
helps ensure that tests are hermetic for devices
that do not power off the chip with rfkill.

Add a mutex to make sure that close only gets
called once.

Bug: 266221125
Test: atest VtsHalBluetoothTargetTest
Change-Id: Ifb259a675202aa5399a8c7570ba8c4df2083e10e
diff --git a/bluetooth/aidl/default/Android.bp b/bluetooth/aidl/default/Android.bp
index 3f4ba99..32d1a13 100644
--- a/bluetooth/aidl/default/Android.bp
+++ b/bluetooth/aidl/default/Android.bp
@@ -30,8 +30,15 @@
     defaults: ["android.hardware.bluetooth-service-build-defaults"],
     srcs: [
         "BluetoothHci.cpp",
+        ":BluetoothPacketSources",
         "net_bluetooth_mgmt.cpp",
     ],
+    generated_headers: [
+        "BluetoothGeneratedPackets_h",
+    ],
+    include_dirs: [
+        "packages/modules/Bluetooth/system/gd",
+    ],
 }
 
 cc_binary {
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index eebbbc0..d4e4b34 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -29,6 +29,11 @@
 
 #include "log/log.h"
 
+// TODO: Remove custom logging defines from PDL packets.
+#undef LOG_INFO
+#undef LOG_DEBUG
+#include "hci/hci_packets.h"
+
 namespace {
 int SetTerminalRaw(int fd) {
   termios terminal_settings;
@@ -74,15 +79,22 @@
       ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
       return;
     }
-    has_died_ = true;
+    {
+      std::lock_guard<std::mutex> guard(mHasDiedMutex);
+      has_died_ = true;
+    }
     mHci->close();
   }
   BluetoothHci* mHci;
   std::shared_ptr<IBluetoothHciCallbacks> mCb;
   AIBinder_DeathRecipient* clientDeathRecipient_;
-  bool getHasDied() const { return has_died_; }
+  bool getHasDied() {
+    std::lock_guard<std::mutex> guard(mHasDiedMutex);
+    return has_died_;
+  }
 
  private:
+  std::mutex mHasDiedMutex;
   bool has_died_{false};
 };
 
@@ -114,16 +126,95 @@
   return fd;
 }
 
+void BluetoothHci::reset() {
+  // Send a reset command and wait until the command complete comes back.
+
+  std::vector<uint8_t> reset;
+  ::bluetooth::packet::BitInserter bi{reset};
+  ::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
+
+  auto resetPromise = std::make_shared<std::promise<void>>();
+  auto resetFuture = resetPromise->get_future();
+
+  mH4 = std::make_shared<H4Protocol>(
+      mFd,
+      [](const std::vector<uint8_t>& raw_command) {
+        ALOGI("Discarding %d bytes with command type",
+              static_cast<int>(raw_command.size()));
+      },
+      [](const std::vector<uint8_t>& raw_acl) {
+        ALOGI("Discarding %d bytes with acl type",
+              static_cast<int>(raw_acl.size()));
+      },
+      [](const std::vector<uint8_t>& raw_sco) {
+        ALOGI("Discarding %d bytes with sco type",
+              static_cast<int>(raw_sco.size()));
+      },
+      [resetPromise](const std::vector<uint8_t>& raw_event) {
+        bool valid = ::bluetooth::hci::ResetCompleteView::Create(
+                         ::bluetooth::hci::CommandCompleteView::Create(
+                             ::bluetooth::hci::EventView::Create(
+                                 ::bluetooth::hci::PacketView<true>(
+                                     std::make_shared<std::vector<uint8_t>>(
+                                         raw_event)))))
+                         .IsValid();
+        if (valid) {
+          resetPromise->set_value();
+        } else {
+          ALOGI("Discarding %d bytes with event type",
+                static_cast<int>(raw_event.size()));
+        }
+      },
+      [](const std::vector<uint8_t>& raw_iso) {
+        ALOGI("Discarding %d bytes with iso type",
+              static_cast<int>(raw_iso.size()));
+      },
+      [this]() {
+        ALOGI("HCI socket device disconnected while waiting for reset");
+        mFdWatcher.StopWatchingFileDescriptors();
+      });
+  mFdWatcher.WatchFdForNonBlockingReads(mFd,
+                                        [this](int) { mH4->OnDataReady(); });
+
+  send(PacketType::COMMAND, reset);
+  auto status = resetFuture.wait_for(std::chrono::seconds(1));
+  mFdWatcher.StopWatchingFileDescriptors();
+  if (status == std::future_status::ready) {
+    ALOGI("HCI Reset successful");
+  } else {
+    ALOGE("HCI Reset Response not received in one second");
+  }
+
+  resetPromise.reset();
+}
+
 ndk::ScopedAStatus BluetoothHci::initialize(
     const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
   ALOGI(__func__);
 
-  mCb = cb;
-  if (mCb == nullptr) {
+  if (cb == nullptr) {
     ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
     return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
   }
 
+  HalState old_state = HalState::READY;
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    if (mState != HalState::READY) {
+      old_state = mState;
+    } else {
+      mState = HalState::INITIALIZING;
+    }
+  }
+
+  if (old_state != HalState::READY) {
+    ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
+    close();
+    cb->initializationComplete(Status::ALREADY_INITIALIZED);
+    return ndk::ScopedAStatus::ok();
+  }
+
+  mCb = cb;
   management_.reset(new NetBluetoothMgmt);
   mFd = management_->openHci();
   if (mFd < 0) {
@@ -132,12 +223,16 @@
     ALOGI("Unable to open Linux interface, trying default path.");
     mFd = getFdFromDevPath();
     if (mFd < 0) {
-      return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+      cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
+      return ndk::ScopedAStatus::ok();
     }
   }
 
   mDeathRecipient->LinkToDeath(mCb);
 
+  // TODO: This should not be necessary when the device implements rfkill.
+  reset();
+
   mH4 = std::make_shared<H4Protocol>(
       mFd,
       [](const std::vector<uint8_t>& /* raw_command */) {
@@ -162,6 +257,10 @@
   mFdWatcher.WatchFdForNonBlockingReads(mFd,
                                         [this](int) { mH4->OnDataReady(); });
 
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    mState = HalState::ONE_CLIENT;
+  }
   ALOGI("initialization complete");
   auto status = mCb->initializationComplete(Status::SUCCESS);
   if (!status.isOk()) {
@@ -178,13 +277,27 @@
 
 ndk::ScopedAStatus BluetoothHci::close() {
   ALOGI(__func__);
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    if (mState != HalState::ONE_CLIENT) {
+      ALOGI("Already closed");
+      return ndk::ScopedAStatus::ok();
+    }
+    mState = HalState::CLOSING;
+  }
+
   mFdWatcher.StopWatchingFileDescriptors();
+
   if (management_) {
     management_->closeHci();
   } else {
     ::close(mFd);
   }
 
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    mState = HalState::READY;
+  }
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
index a0908f8..85aafc8 100644
--- a/bluetooth/aidl/default/BluetoothHci.h
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -18,8 +18,8 @@
 
 #include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
 #include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
-#include <log/log.h>
 
+#include <future>
 #include <string>
 
 #include "async_fd_watcher.h"
@@ -69,6 +69,18 @@
   void send(::android::hardware::bluetooth::hci::PacketType type,
             const std::vector<uint8_t>& packet);
   std::unique_ptr<NetBluetoothMgmt> management_{};
+
+  // Send a reset command and discard all packets until a reset is received.
+  void reset();
+
+  // Don't close twice or open before close is complete
+  std::mutex mStateMutex;
+  enum class HalState {
+    READY,
+    INITIALIZING,
+    ONE_CLIENT,
+    CLOSING,
+  } mState{HalState::READY};
 };
 
 }  // namespace aidl::android::hardware::bluetooth::impl