• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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