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