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 <algorithm>
18 #include <cstdint>
19 #include <iterator>
20 #include <optional>
21
22 #include "hci/acl_manager.h"
23 #include "hci/address_with_type.h"
24 #include "hci/hci_packets.h"
25 #include "main/shim/entry.h"
26 #ifndef TARGET_FLOSS
27 #include "src/connection/ffi.rs.h"
28 #endif
29 #include "src/core/ffi/types.h"
30 #include "stack/btm/btm_dev.h"
31
32 extern const tBLE_BD_ADDR convert_to_address_with_type(
33 const RawAddress& bd_addr, const tBTM_SEC_DEV_REC* p_dev_rec);
34
35 namespace bluetooth {
36 namespace connection {
37
38 #ifdef TARGET_FLOSS
39 struct LeAclManagerCallbackShim {
OnLeConnectSuccessbluetooth::connection::LeAclManagerCallbackShim40 void OnLeConnectSuccess(core::AddressWithType addr) const {
41 LOG_ALWAYS_FATAL("system/rust not available in Floss");
42 }
OnLeConnectFailbluetooth::connection::LeAclManagerCallbackShim43 void OnLeConnectFail(core::AddressWithType addr, uint8_t status) const {
44 LOG_ALWAYS_FATAL("system/rust not available in Floss");
45 };
OnLeDisconnectionbluetooth::connection::LeAclManagerCallbackShim46 void OnLeDisconnection(core::AddressWithType addr) const {
47 LOG_ALWAYS_FATAL("system/rust not available in Floss");
48 };
49 };
50
51 using BoxedLeAclManagerCallbackShim = std::unique_ptr<LeAclManagerCallbackShim>;
52
53 #else
54
55 using BoxedLeAclManagerCallbackShim = ::rust::Box<LeAclManagerCallbackShim>;
56
57 #endif
58
59 namespace {
ToCppAddress(core::AddressWithType address)60 hci::AddressWithType ToCppAddress(core::AddressWithType address) {
61 auto hci_address = hci::Address();
62 hci_address.FromOctets(address.address.data());
63 return hci::AddressWithType(hci_address,
64 (hci::AddressType)address.address_type);
65 }
66
ToRustAddress(hci::AddressWithType address)67 core::AddressWithType ToRustAddress(hci::AddressWithType address) {
68 return core::AddressWithType{address.GetAddress().address,
69 (core::AddressType)address.GetAddressType()};
70 }
71 } // namespace
72
73 struct LeAclManagerShim::impl : hci::acl_manager::LeAcceptlistCallbacks {
74 public:
implbluetooth::connection::LeAclManagerShim::impl75 impl() { acl_manager_ = shim::GetAclManager(); }
76
~implbluetooth::connection::LeAclManagerShim::impl77 ~impl() {
78 if (callbacks_.has_value()) {
79 callbacks_.reset();
80 auto promise = std::promise<void>();
81 auto future = promise.get_future();
82 acl_manager_->UnregisterLeAcceptlistCallbacks(this, std::move(promise));
83 future.wait();
84 }
85 }
86
CreateLeConnectionbluetooth::connection::LeAclManagerShim::impl87 void CreateLeConnection(core::AddressWithType address, bool is_direct) {
88 acl_manager_->CreateLeConnection(ToCppAddress(address), is_direct);
89 }
90
CancelLeConnectbluetooth::connection::LeAclManagerShim::impl91 void CancelLeConnect(core::AddressWithType address) {
92 acl_manager_->CancelLeConnect(ToCppAddress(address));
93 }
94
95 #ifndef TARGET_FLOSS
RegisterRustCallbacksbluetooth::connection::LeAclManagerShim::impl96 void RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks) {
97 callbacks_ = std::move(callbacks);
98 acl_manager_->RegisterLeAcceptlistCallbacks(this);
99 }
100 #endif
101
102 // hci::acl_manager::LeAcceptlistCallbacks
OnLeConnectSuccessbluetooth::connection::LeAclManagerShim::impl103 virtual void OnLeConnectSuccess(hci::AddressWithType address) {
104 callbacks_.value()->OnLeConnectSuccess(ToRustAddress(address));
105 }
106
107 // hci::acl_manager::LeAcceptlistCallbacks
OnLeConnectFailbluetooth::connection::LeAclManagerShim::impl108 virtual void OnLeConnectFail(hci::AddressWithType address,
109 hci::ErrorCode reason) {
110 callbacks_.value()->OnLeConnectFail(ToRustAddress(address),
111 static_cast<uint8_t>(reason));
112 }
113
114 // hci::acl_manager::LeAcceptlistCallbacks
OnLeDisconnectionbluetooth::connection::LeAclManagerShim::impl115 virtual void OnLeDisconnection(hci::AddressWithType address) {
116 callbacks_.value()->OnLeDisconnection(ToRustAddress(address));
117 }
118
119 // hci::acl_manager::LeAcceptlistCallbacks
OnResolvingListChangebluetooth::connection::LeAclManagerShim::impl120 virtual void OnResolvingListChange() {}
121
122 private:
123 std::optional<BoxedLeAclManagerCallbackShim> callbacks_;
124 hci::AclManager* acl_manager_{};
125 };
126
LeAclManagerShim()127 LeAclManagerShim::LeAclManagerShim() {
128 pimpl_ = std::make_unique<LeAclManagerShim::impl>();
129 }
130
131 LeAclManagerShim::~LeAclManagerShim() = default;
132
CreateLeConnection(core::AddressWithType address,bool is_direct) const133 void LeAclManagerShim::CreateLeConnection(core::AddressWithType address,
134 bool is_direct) const {
135 pimpl_->CreateLeConnection(address, is_direct);
136 }
137
CancelLeConnect(core::AddressWithType address) const138 void LeAclManagerShim::CancelLeConnect(core::AddressWithType address) const {
139 pimpl_->CancelLeConnect(address);
140 }
141
142 #ifndef TARGET_FLOSS
RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks)143 void LeAclManagerShim::RegisterRustCallbacks(
144 BoxedLeAclManagerCallbackShim callbacks) {
145 pimpl_->RegisterRustCallbacks(std::move(callbacks));
146 }
147 #endif
148
149 namespace {
150
151 std::optional<RustConnectionManager> connection_manager;
152
153 } // namespace
154
GetConnectionManager()155 RustConnectionManager& GetConnectionManager() {
156 return connection_manager.value();
157 }
158
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)159 void RegisterRustApis(
160 ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
161 start_direct_connection,
162 ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
163 stop_direct_connection,
164 ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
165 add_background_connection,
166 ::rust::Fn<void(uint8_t client_id, core::AddressWithType address)>
167 remove_background_connection,
168 ::rust::Fn<void(uint8_t client_id)> remove_client,
169 ::rust::Fn<void(core::AddressWithType address)>
170 stop_all_connections_to_device) {
171 connection_manager = {start_direct_connection,
172 stop_direct_connection,
173 add_background_connection,
174 remove_background_connection,
175 remove_client,
176 stop_all_connections_to_device};
177 }
178
ResolveRawAddress(RawAddress bd_addr)179 core::AddressWithType ResolveRawAddress(RawAddress bd_addr) {
180 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
181 tBLE_BD_ADDR address = convert_to_address_with_type(bd_addr, p_dev_rec);
182 return core::ToRustAddress(address);
183 }
184
185 } // namespace connection
186 } // namespace bluetooth
187