Floss: LeRand controller plumbing

Add ability to call LeRand and provide a callback function.

Bug: 219982689
Test: mma -j $(nproc)
Test: ./build.py
Test: atest bluetooth_test_gd_unit --test-filter="*controller*"
Tag: #floss
Change-Id: Id501efa2073f3b8887f7ca9a3894050becebc5cd
diff --git a/system/device/include/controller.h b/system/device/include/controller.h
index 93b5966..3fd28b6 100644
--- a/system/device/include/controller.h
+++ b/system/device/include/controller.h
@@ -21,9 +21,12 @@
 #include <cstddef>
 #include <cstdint>
 
+#include "base/callback.h"
 #include "btcore/include/version.h"
 #include "types/raw_address.h"
 
+using LeRandCallback = base::Callback<void(uint64_t)>;
+
 typedef struct controller_t {
   bool (*get_is_ready)(void);
 
@@ -116,6 +119,7 @@
   uint8_t (*get_le_all_initiating_phys)(void);
   uint8_t (*clear_event_filter)(void);
   uint8_t (*clear_event_mask)(void);
+  uint8_t (*le_rand)(LeRandCallback);
 
 } controller_t;
 
diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc
index da5986f..0db8f4d 100644
--- a/system/gd/hci/controller.cc
+++ b/system/gd/hci/controller.cc
@@ -511,6 +511,22 @@
                          module_.GetHandler()->BindOnceOn(this, &Controller::impl::check_status<ResetCompleteView>));
   }
 
+  void le_rand(LeRandCallback cb) {
+    std::unique_ptr<LeRandBuilder> packet = LeRandBuilder::Create();
+    hci_->EnqueueCommand(
+        std::move(packet),
+        module_.GetHandler()->BindOnceOn(this, &Controller::impl::le_rand_cb<LeRandCompleteView>, cb));
+  }
+
+  template <class T>
+  void le_rand_cb(LeRandCallback cb, CommandCompleteView view) {
+    ASSERT(view.IsValid());
+    auto status_view = T::Create(view);
+    ASSERT(status_view.IsValid());
+    ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+    cb.Run(status_view.GetRandomNumber());
+  }
+
   void set_event_filter(std::unique_ptr<SetEventFilterBuilder> packet) {
     hci_->EnqueueCommand(std::move(packet), module_.GetHandler()->BindOnceOn(
                                                 this, &Controller::impl::check_status<SetEventFilterCompleteView>));
@@ -1020,6 +1036,10 @@
   CallOn(impl_.get(), &impl::reset);
 }
 
+void Controller::LeRand(LeRandCallback cb) {
+  CallOn(impl_.get(), &impl::le_rand, cb);
+}
+
 void Controller::SetEventFilterClearAll() {
   std::unique_ptr<SetEventFilterClearAllBuilder> packet = SetEventFilterClearAllBuilder::Create();
   CallOn(impl_.get(), &impl::set_event_filter, std::move(packet));
diff --git a/system/gd/hci/controller.h b/system/gd/hci/controller.h
index 1539964..26fcf45 100644
--- a/system/gd/hci/controller.h
+++ b/system/gd/hci/controller.h
@@ -16,9 +16,9 @@
 
 #pragma once
 
-#include "common/contextual_callback.h"
 #include "hci/address.h"
 #include "hci/hci_packets.h"
+#include "hci/le_rand_callback.h"
 #include "module.h"
 #include "os/handler.h"
 
@@ -127,6 +127,8 @@
 
   virtual void Reset();
 
+  virtual void LeRand(LeRandCallback cb);
+
   virtual void SetEventFilterClearAll();
 
   virtual void SetEventFilterInquiryResultAllDevices();
diff --git a/system/gd/hci/controller_mock.h b/system/gd/hci/controller_mock.h
index d81e4af..6bb55eb 100644
--- a/system/gd/hci/controller_mock.h
+++ b/system/gd/hci/controller_mock.h
@@ -126,6 +126,7 @@
   MOCK_METHOD(uint8_t, GetLePeriodicAdvertiserListSize, (), (const));
   MOCK_METHOD(VendorCapabilities, GetVendorCapabilities, (), (const));
   MOCK_METHOD(bool, IsSupported, (OpCode op_code), (const));
+  MOCK_METHOD(void, LeRand, (LeRandCallback cb));
 };
 
 }  // namespace testing
diff --git a/system/gd/hci/controller_test.cc b/system/gd/hci/controller_test.cc
index 3b1df9d..ebf4374 100644
--- a/system/gd/hci/controller_test.cc
+++ b/system/gd/hci/controller_test.cc
@@ -462,6 +462,18 @@
 
   test_hci_layer_->IncomingCredit();
 }
+
+std::promise<uint64_t> le_rand_set;
+
+void le_rand_callback(uint64_t random) {
+  le_rand_set.set_value(random);
+}
+
+TEST_F(ControllerTest, leRandTest) {
+  controller_->LeRand(client_handler_->Bind(&le_rand_callback));
+  le_rand_set.get_future().wait();
+}
+
 }  // namespace
 }  // namespace hci
 }  // namespace bluetooth
diff --git a/system/gd/hci/le_rand_callback.h b/system/gd/hci/le_rand_callback.h
new file mode 100644
index 0000000..60222e9
--- /dev/null
+++ b/system/gd/hci/le_rand_callback.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 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 "common/callback.h"
+
+// Define new enums or parsers for existing enums
+namespace bluetooth {
+namespace hci {
+
+using LeRandCallback = common::Callback<void(uint64_t)>;
+
+}  // namespace hci
+}  // namespace bluetooth
diff --git a/system/main/shim/controller.cc b/system/main/shim/controller.cc
index 6cbf623..7f60a98 100644
--- a/system/main/shim/controller.cc
+++ b/system/main/shim/controller.cc
@@ -19,7 +19,9 @@
 #include "main/shim/controller.h"
 
 #include "btcore/include/module.h"
+#include "gd/common/contextual_callback.h"
 #include "gd/common/init_flags.h"
+#include "gd/hci/controller.h"
 #include "hci/controller.h"
 #include "main/shim/entry.h"
 #include "main/shim/shim.h"
@@ -326,6 +328,12 @@
   return BTM_SUCCESS;
 }
 
+static uint8_t controller_le_rand(LeRandCallback cb) {
+  LOG_VERBOSE("Called!");
+  bluetooth::shim::GetController()->LeRand(cb);
+  return BTM_SUCCESS;
+}
+
 static const controller_t interface = {
     .get_is_ready = get_is_ready,
 
@@ -425,7 +433,8 @@
     .get_local_supported_codecs = get_local_supported_codecs,
     .get_le_all_initiating_phys = get_le_all_initiating_phys,
     .clear_event_filter = controller_clear_event_filter,
-    .clear_event_mask = controller_clear_event_mask};
+    .clear_event_mask = controller_clear_event_mask,
+    .le_rand = controller_le_rand};
 
 const controller_t* bluetooth::shim::controller_get_interface() {
   static bool loaded = false;
diff --git a/system/test/mock/mock_device_controller.cc b/system/test/mock/mock_device_controller.cc
index 89b5442..e80b8de 100644
--- a/system/test/mock/mock_device_controller.cc
+++ b/system/test/mock/mock_device_controller.cc
@@ -371,6 +371,8 @@
 
 tBTM_STATUS clear_event_mask() { return BTM_SUCCESS; }
 
+tBTM_STATUS le_rand(LeRandCallback cb) { return BTM_SUCCESS; }
+
 const controller_t interface = {
     get_is_ready,
 
@@ -457,7 +459,8 @@
     get_local_supported_codecs,
     get_le_all_initiating_phys,
     clear_event_filter,
-    clear_event_mask};
+    clear_event_mask,
+    le_rand};
 
 }  // namespace device_controller
 }  // namespace mock