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