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