1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "hci/acl_manager/le_acl_connection.h"
18
19 #include <bluetooth/log.h>
20 #include <com_android_bluetooth_flags.h>
21
22 #include "hci/acl_manager/le_connection_management_callbacks.h"
23 #include "hci/event_checkers.h"
24 #include "os/metrics.h"
25
26 using bluetooth::hci::Address;
27
28 namespace bluetooth {
29 namespace hci {
30 namespace acl_manager {
31
32 class LeAclConnectionTracker : public LeConnectionManagementCallbacks {
33 public:
LeAclConnectionTracker(LeAclConnectionInterface * le_acl_connection_interface,uint16_t connection_handle)34 LeAclConnectionTracker(LeAclConnectionInterface* le_acl_connection_interface,
35 uint16_t connection_handle)
36 : le_acl_connection_interface_(le_acl_connection_interface),
37 connection_handle_(connection_handle) {}
~LeAclConnectionTracker()38 ~LeAclConnectionTracker() {
39 log::assert_that(queued_callbacks_.empty(), "assert failed: queued_callbacks_.empty()");
40 }
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)41 void RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
42 client_handler_ = handler;
43 client_callbacks_ = callbacks;
44 while (!queued_callbacks_.empty()) {
45 auto iter = queued_callbacks_.begin();
46 handler->Post(std::move(*iter));
47 queued_callbacks_.erase(iter);
48 }
49 }
50
51 #define SAVE_OR_CALL(f, ...) \
52 if (client_handler_ == nullptr) { \
53 queued_callbacks_.emplace_back(common::BindOnce(&LeConnectionManagementCallbacks::f, \
54 common::Unretained(this), __VA_ARGS__)); \
55 } else { \
56 client_handler_->Post(common::BindOnce(&LeConnectionManagementCallbacks::f, \
57 common::Unretained(client_callbacks_), __VA_ARGS__)); \
58 }
59
OnConnectionUpdate(hci::ErrorCode hci_status,uint16_t conn_interval,uint16_t conn_latency,uint16_t supervision_timeout)60 void OnConnectionUpdate(hci::ErrorCode hci_status, uint16_t conn_interval, uint16_t conn_latency,
61 uint16_t supervision_timeout) override {
62 SAVE_OR_CALL(OnConnectionUpdate, hci_status, conn_interval, conn_latency, supervision_timeout)
63 }
64
OnParameterUpdateRequest(uint16_t interval_min,uint16_t interval_max,uint16_t latency,uint16_t supervision_timeout)65 void OnParameterUpdateRequest(uint16_t interval_min, uint16_t interval_max, uint16_t latency,
66 uint16_t supervision_timeout) override {
67 SAVE_OR_CALL(OnParameterUpdateRequest, interval_min, interval_max, latency, supervision_timeout)
68 }
69
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)70 void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets,
71 uint16_t rx_time) override {
72 SAVE_OR_CALL(OnDataLengthChange, tx_octets, tx_time, rx_octets, rx_time)
73 }
74
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)75 void OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, uint8_t lmp_version,
76 uint16_t manufacturer_name, uint16_t sub_version) {
77 bluetooth::os::LogMetricRemoteVersionInfo(connection_handle_, static_cast<uint8_t>(hci_status),
78 lmp_version, manufacturer_name, sub_version);
79 SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name,
80 sub_version);
81 }
82
OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status,uint64_t features)83 void OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status, uint64_t features) override {
84 SAVE_OR_CALL(OnLeReadRemoteFeaturesComplete, hci_status, features);
85 }
86
OnPhyUpdate(hci::ErrorCode hci_status,uint8_t tx_phy,uint8_t rx_phy)87 void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {
88 SAVE_OR_CALL(OnPhyUpdate, hci_status, tx_phy, rx_phy);
89 }
OnLeSubrateChange(hci::ErrorCode hci_status,uint16_t subrate_factor,uint16_t peripheral_latency,uint16_t continuation_number,uint16_t supervision_timeout)90 void OnLeSubrateChange(hci::ErrorCode hci_status, uint16_t subrate_factor,
91 uint16_t peripheral_latency, uint16_t continuation_number,
92 uint16_t supervision_timeout) override {
93 SAVE_OR_CALL(OnLeSubrateChange, hci_status, subrate_factor, peripheral_latency,
94 continuation_number, supervision_timeout);
95 }
96
OnDisconnection(ErrorCode reason)97 void OnDisconnection(ErrorCode reason) override { SAVE_OR_CALL(OnDisconnection, reason); }
98 #undef SAVE_OR_CALL
99
100 LeAclConnectionInterface* le_acl_connection_interface_;
101 os::Handler* client_handler_ = nullptr;
102 LeConnectionManagementCallbacks* client_callbacks_ = nullptr;
103 std::list<common::OnceClosure> queued_callbacks_;
104 const uint16_t connection_handle_;
105 };
106
107 struct LeAclConnection::impl {
implbluetooth::hci::acl_manager::LeAclConnection::impl108 impl(LeAclConnectionInterface* le_acl_connection_interface, std::shared_ptr<Queue> queue,
109 uint16_t connection_handle)
110 : queue_(std::move(queue)), tracker(le_acl_connection_interface, connection_handle) {}
GetEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl111 LeConnectionManagementCallbacks* GetEventCallbacks(
112 std::function<void(uint16_t)> invalidate_callbacks) {
113 log::assert_that(!invalidate_callbacks_,
114 "Already returned event callbacks for this connection");
115 invalidate_callbacks_ = std::move(invalidate_callbacks);
116 return &tracker;
117 }
PutEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl118 void PutEventCallbacks() {
119 if (invalidate_callbacks_) {
120 invalidate_callbacks_(tracker.connection_handle_);
121 }
122 }
123 std::shared_ptr<Queue> queue_;
124 LeAclConnectionTracker tracker;
125 std::function<void(uint16_t)> invalidate_callbacks_;
126 };
127
LeAclConnection()128 LeAclConnection::LeAclConnection()
129 : AclConnection(),
130 remote_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS),
131 role_specific_data_(DataAsUninitializedPeripheral{}) {}
132
LeAclConnection(std::shared_ptr<Queue> queue,LeAclConnectionInterface * le_acl_connection_interface,uint16_t handle,RoleSpecificData role_specific_data,AddressWithType remote_address)133 LeAclConnection::LeAclConnection(std::shared_ptr<Queue> queue,
134 LeAclConnectionInterface* le_acl_connection_interface,
135 uint16_t handle, RoleSpecificData role_specific_data,
136 AddressWithType remote_address)
137 : AclConnection(queue->GetUpEnd(), handle),
138 remote_address_(remote_address),
139 role_specific_data_(role_specific_data) {
140 pimpl_ = new LeAclConnection::impl(le_acl_connection_interface, std::move(queue), handle);
141 }
142
~LeAclConnection()143 LeAclConnection::~LeAclConnection() {
144 if (pimpl_) {
145 pimpl_->PutEventCallbacks();
146 }
147 delete pimpl_;
148 }
149
GetLocalAddress() const150 AddressWithType LeAclConnection::GetLocalAddress() const {
151 return std::visit(
152 [](auto&& data) {
153 using T = std::decay_t<decltype(data)>;
154 if constexpr (std::is_same_v<T, DataAsUninitializedPeripheral>) {
155 // This case should never happen outside of acl_manager.cc, since once the connection
156 // is passed into the OnConnectSuccess callback, it should be fully initialized.
157 log::fatal("Attempted to read the local address of an uninitialized connection");
158 return AddressWithType{};
159 } else {
160 return data.local_address;
161 }
162 },
163 role_specific_data_);
164 }
165
GetRole() const166 Role LeAclConnection::GetRole() const {
167 return std::visit(
168 [](auto&& data) {
169 using T = std::decay_t<decltype(data)>;
170 if constexpr (std::is_same_v<T, DataAsCentral>) {
171 return Role::CENTRAL;
172 } else if constexpr (std::is_same_v<T, DataAsPeripheral> ||
173 std::is_same_v<T, DataAsUninitializedPeripheral>) {
174 return Role::PERIPHERAL;
175 } else {
176 static_assert(!sizeof(T*), "missing case");
177 }
178 },
179 role_specific_data_);
180 }
181
GetRoleSpecificData() const182 const RoleSpecificData& LeAclConnection::GetRoleSpecificData() const { return role_specific_data_; }
183
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)184 void LeAclConnection::RegisterCallbacks(LeConnectionManagementCallbacks* callbacks,
185 os::Handler* handler) {
186 return pimpl_->tracker.RegisterCallbacks(callbacks, handler);
187 }
188
Disconnect(DisconnectReason reason)189 void LeAclConnection::Disconnect(DisconnectReason reason) {
190 if (com::android::bluetooth::flags::dont_send_hci_disconnect_repeatedly()) {
191 if (is_disconnecting_) {
192 log::info("Already disconnecting {}", remote_address_);
193 return;
194 }
195 }
196
197 is_disconnecting_ = true;
198 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
199 DisconnectBuilder::Create(handle_, reason),
200 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
201 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
202 log::assert_that(status.GetCommandOpCode() == OpCode::DISCONNECT,
203 "assert failed: status.GetCommandOpCode() == OpCode::DISCONNECT");
204 auto disconnect_status = DisconnectStatusView::Create(status);
205 log::assert_that(disconnect_status.IsValid(),
206 "assert failed: disconnect_status.IsValid()");
207 auto error_code = disconnect_status.GetStatus();
208 if (error_code != ErrorCode::SUCCESS) {
209 log::info("Disconnect status {}", ErrorCodeText(error_code));
210 }
211 }));
212 }
213
OnLeSubrateRequestStatus(CommandStatusView status)214 void LeAclConnection::OnLeSubrateRequestStatus(CommandStatusView status) {
215 auto subrate_request_status = LeSubrateRequestStatusView::Create(status);
216 log::assert_that(subrate_request_status.IsValid(),
217 "assert failed: subrate_request_status.IsValid()");
218 auto hci_status = subrate_request_status.GetStatus();
219 if (hci_status != ErrorCode::SUCCESS) {
220 log::info("LeSubrateRequest status {}", ErrorCodeText(hci_status));
221 pimpl_->tracker.OnLeSubrateChange(hci_status, 0, 0, 0, 0);
222 }
223 }
224
LeSubrateRequest(uint16_t subrate_min,uint16_t subrate_max,uint16_t max_latency,uint16_t cont_num,uint16_t sup_tout)225 void LeAclConnection::LeSubrateRequest(uint16_t subrate_min, uint16_t subrate_max,
226 uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
227 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
228 LeSubrateRequestBuilder::Create(handle_, subrate_min, subrate_max, max_latency, cont_num,
229 sup_tout),
230 pimpl_->tracker.client_handler_->BindOnceOn(this,
231 &LeAclConnection::OnLeSubrateRequestStatus));
232 }
233
GetEventCallbacks(std::function<void (uint16_t)> invalidate_callbacks)234 LeConnectionManagementCallbacks* LeAclConnection::GetEventCallbacks(
235 std::function<void(uint16_t)> invalidate_callbacks) {
236 return pimpl_->GetEventCallbacks(std::move(invalidate_callbacks));
237 }
238
LeConnectionUpdate(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout,uint16_t min_ce_length,uint16_t max_ce_length)239 bool LeAclConnection::LeConnectionUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max,
240 uint16_t conn_latency, uint16_t supervision_timeout,
241 uint16_t min_ce_length, uint16_t max_ce_length) {
242 if (!check_connection_parameters(conn_interval_min, conn_interval_max, conn_latency,
243 supervision_timeout)) {
244 log::error("Invalid parameter");
245 return false;
246 }
247 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
248 LeConnectionUpdateBuilder::Create(handle_, conn_interval_min, conn_interval_max,
249 conn_latency, supervision_timeout, min_ce_length,
250 max_ce_length),
251 pimpl_->tracker.client_handler_->BindOnce(check_status<LeConnectionUpdateStatusView>));
252 return true;
253 }
254
ReadRemoteVersionInformation()255 bool LeAclConnection::ReadRemoteVersionInformation() {
256 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
257 ReadRemoteVersionInformationBuilder::Create(handle_),
258 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
259 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
260 log::assert_that(status.GetCommandOpCode() == OpCode::READ_REMOTE_VERSION_INFORMATION,
261 "assert failed: status.GetCommandOpCode() == "
262 "OpCode::READ_REMOTE_VERSION_INFORMATION");
263 }));
264 return true;
265 }
266
LeReadRemoteFeatures()267 bool LeAclConnection::LeReadRemoteFeatures() {
268 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
269 LeReadRemoteFeaturesBuilder::Create(handle_),
270 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
271 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
272 log::assert_that(
273 status.GetCommandOpCode() == OpCode::LE_READ_REMOTE_FEATURES,
274 "assert failed: status.GetCommandOpCode() == OpCode::LE_READ_REMOTE_FEATURES");
275 }));
276 return true;
277 }
278
check_connection_parameters(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout)279 bool LeAclConnection::check_connection_parameters(uint16_t conn_interval_min,
280 uint16_t conn_interval_max, uint16_t conn_latency,
281 uint16_t supervision_timeout) {
282 if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
283 conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A ||
284 supervision_timeout > 0x0C80) {
285 log::error("Invalid parameter");
286 return false;
287 }
288 // The Maximum interval in milliseconds will be conn_interval_max * 1.25 ms
289 // The Timeout in milliseconds will be expected_supervision_timeout * 10 ms
290 // The Timeout in milliseconds shall be larger than (1 + Latency) * Interval_Max * 2, where
291 // Interval_Max is given in milliseconds.
292 uint32_t supervision_timeout_min = (uint32_t)(1 + conn_latency) * conn_interval_max * 2 + 1;
293 if (supervision_timeout * 8 < supervision_timeout_min || conn_interval_max < conn_interval_min) {
294 log::error("Invalid parameter");
295 return false;
296 }
297
298 return true;
299 }
300
301 } // namespace acl_manager
302 } // namespace hci
303 } // namespace bluetooth
304