1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "connection_shim.h"
16 
17 #include <bluetooth/log.h>
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <iterator>
22 #include <optional>
23 
24 #include "hci/acl_manager.h"
25 #include "hci/address_with_type.h"
26 #include "hci/hci_packets.h"
27 #include "main/shim/entry.h"
28 #ifndef TARGET_FLOSS
29 #include "src/connection/ffi.rs.h"
30 #endif
31 #include "src/core/ffi/types.h"
32 #include "stack/btm/btm_dev.h"
33 
34 namespace bluetooth {
35 namespace connection {
36 
37 #ifdef TARGET_FLOSS
38 struct LeAclManagerCallbackShim {
OnLeConnectSuccessbluetooth::connection::LeAclManagerCallbackShim39   void OnLeConnectSuccess(core::AddressWithType addr) const {
40     log::fatal("system/rust not available in Floss");
41   }
OnLeConnectFailbluetooth::connection::LeAclManagerCallbackShim42   void OnLeConnectFail(core::AddressWithType addr, uint8_t status) const {
43     log::fatal("system/rust not available in Floss");
44   };
OnLeDisconnectionbluetooth::connection::LeAclManagerCallbackShim45   void OnLeDisconnection(core::AddressWithType addr) const {
46     log::fatal("system/rust not available in Floss");
47   };
48 };
49 
50 using BoxedLeAclManagerCallbackShim = std::unique_ptr<LeAclManagerCallbackShim>;
51 
52 #else
53 
54 using BoxedLeAclManagerCallbackShim = ::rust::Box<LeAclManagerCallbackShim>;
55 
56 #endif
57 
58 namespace {
ToCppAddress(core::AddressWithType address)59 hci::AddressWithType ToCppAddress(core::AddressWithType address) {
60   auto hci_address = hci::Address();
61   hci_address.FromOctets(address.address.data());
62   return hci::AddressWithType(hci_address,
63                               (hci::AddressType)address.address_type);
64 }
65 
ToRustAddress(hci::AddressWithType address)66 core::AddressWithType ToRustAddress(hci::AddressWithType address) {
67   return core::AddressWithType{address.GetAddress().address,
68                                (core::AddressType)address.GetAddressType()};
69 }
70 }  // namespace
71 
72 struct LeAclManagerShim::impl : hci::acl_manager::LeAcceptlistCallbacks {
73  public:
implbluetooth::connection::LeAclManagerShim::impl74   impl() { acl_manager_ = shim::GetAclManager(); }
75 
~implbluetooth::connection::LeAclManagerShim::impl76   ~impl() {
77     if (callbacks_.has_value()) {
78       callbacks_.reset();
79       auto promise = std::promise<void>();
80       auto future = promise.get_future();
81       acl_manager_->UnregisterLeAcceptlistCallbacks(this, std::move(promise));
82       future.wait();
83     }
84   }
85 
CreateLeConnectionbluetooth::connection::LeAclManagerShim::impl86   void CreateLeConnection(core::AddressWithType address, bool is_direct) {
87     acl_manager_->CreateLeConnection(ToCppAddress(address), is_direct);
88   }
89 
CancelLeConnectbluetooth::connection::LeAclManagerShim::impl90   void CancelLeConnect(core::AddressWithType address) {
91     acl_manager_->CancelLeConnect(ToCppAddress(address));
92   }
93 
94 #ifndef TARGET_FLOSS
RegisterRustCallbacksbluetooth::connection::LeAclManagerShim::impl95   void RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks) {
96     callbacks_ = std::move(callbacks);
97     acl_manager_->RegisterLeAcceptlistCallbacks(this);
98   }
99 #endif
100 
101   // hci::acl_manager::LeAcceptlistCallbacks
OnLeConnectSuccessbluetooth::connection::LeAclManagerShim::impl102   virtual void OnLeConnectSuccess(hci::AddressWithType address) {
103     callbacks_.value()->OnLeConnectSuccess(ToRustAddress(address));
104   }
105 
106   // hci::acl_manager::LeAcceptlistCallbacks
OnLeConnectFailbluetooth::connection::LeAclManagerShim::impl107   virtual void OnLeConnectFail(hci::AddressWithType address,
108                                hci::ErrorCode reason) {
109     callbacks_.value()->OnLeConnectFail(ToRustAddress(address),
110                                         static_cast<uint8_t>(reason));
111   }
112 
113   // hci::acl_manager::LeAcceptlistCallbacks
OnLeDisconnectionbluetooth::connection::LeAclManagerShim::impl114   virtual void OnLeDisconnection(hci::AddressWithType address) {
115     callbacks_.value()->OnLeDisconnection(ToRustAddress(address));
116   }
117 
118   // hci::acl_manager::LeAcceptlistCallbacks
OnResolvingListChangebluetooth::connection::LeAclManagerShim::impl119   virtual void OnResolvingListChange() {}
120 
121  private:
122   std::optional<BoxedLeAclManagerCallbackShim> callbacks_;
123   hci::AclManager* acl_manager_{};
124 };
125 
LeAclManagerShim()126 LeAclManagerShim::LeAclManagerShim() {
127   pimpl_ = std::make_unique<LeAclManagerShim::impl>();
128 }
129 
130 LeAclManagerShim::~LeAclManagerShim() = default;
131 
CreateLeConnection(core::AddressWithType address,bool is_direct) const132 void LeAclManagerShim::CreateLeConnection(core::AddressWithType address,
133                                           bool is_direct) const {
134   pimpl_->CreateLeConnection(address, is_direct);
135 }
136 
CancelLeConnect(core::AddressWithType address) const137 void LeAclManagerShim::CancelLeConnect(core::AddressWithType address) const {
138   pimpl_->CancelLeConnect(address);
139 }
140 
141 #ifndef TARGET_FLOSS
RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks)142 void LeAclManagerShim::RegisterRustCallbacks(
143     BoxedLeAclManagerCallbackShim callbacks) {
144   pimpl_->RegisterRustCallbacks(std::move(callbacks));
145 }
146 #endif
147 
148 namespace {
149 
150 std::optional<RustConnectionManager> connection_manager;
151 
152 }  // namespace
153 
GetConnectionManager()154 RustConnectionManager& GetConnectionManager() {
155   return connection_manager.value();
156 }
157 
RegisterRustApis(::rust::Fn<void (uint8_t client_id,core::AddressWithType address)> start_direct_connection,::rust::Fn<void (uint8_t client_id,core::AddressWithType address)> stop_direct_connection,::rust::Fn<void (uint8_t client_id,core::AddressWithType address)> add_background_connection,::rust::Fn<void (uint8_t client_id,core::AddressWithType address)> remove_background_connection,::rust::Fn<void (uint8_t client_id)> remove_client,::rust::Fn<void (core::AddressWithType address)> stop_all_connections_to_device)158 void RegisterRustApis(
159     ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
160         start_direct_connection,
161     ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
162         stop_direct_connection,
163     ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
164         add_background_connection,
165     ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
166         remove_background_connection,
167     ::rust::Fn<void(uint8_t client_id)> remove_client,
168     ::rust::Fn<void(core::AddressWithType address)>
169         stop_all_connections_to_device) {
170   connection_manager = {start_direct_connection,
171                         stop_direct_connection,
172                         add_background_connection,
173                         remove_background_connection,
174                         remove_client,
175                         stop_all_connections_to_device};
176 }
177 
ResolveRawAddress(RawAddress bd_addr)178 core::AddressWithType ResolveRawAddress(RawAddress bd_addr) {
179   tBLE_BD_ADDR address = BTM_Sec_GetAddressWithType(bd_addr);
180   return core::ToRustAddress(address);
181 }
182 
183 }  // namespace connection
184 }  // namespace bluetooth
185