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