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 #include "hci/acl_manager/le_connection_management_callbacks.h"
19 #include "os/metrics.h"
20 
21 namespace bluetooth {
22 namespace hci {
23 namespace acl_manager {
24 
25 class LeAclConnectionTracker : public LeConnectionManagementCallbacks {
26  public:
LeAclConnectionTracker(LeAclConnectionInterface * le_acl_connection_interface,uint16_t connection_handle)27   LeAclConnectionTracker(LeAclConnectionInterface* le_acl_connection_interface, uint16_t connection_handle)
28       : le_acl_connection_interface_(le_acl_connection_interface), connection_handle_(connection_handle) {}
~LeAclConnectionTracker()29   ~LeAclConnectionTracker() {
30     ASSERT(queued_callbacks_.empty());
31   }
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)32   void RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
33     client_handler_ = handler;
34     client_callbacks_ = callbacks;
35     while (!queued_callbacks_.empty()) {
36       auto iter = queued_callbacks_.begin();
37       handler->Post(std::move(*iter));
38       queued_callbacks_.erase(iter);
39     }
40   }
41 
42 #define SAVE_OR_CALL(f, ...)                                                                                        \
43   if (client_handler_ == nullptr) {                                                                                 \
44     queued_callbacks_.emplace_back(                                                                                 \
45         common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(this), __VA_ARGS__));              \
46   } else {                                                                                                          \
47     client_handler_->Post(                                                                                          \
48         common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(client_callbacks_), __VA_ARGS__)); \
49   }
50 
OnConnectionUpdate(hci::ErrorCode hci_status,uint16_t conn_interval,uint16_t conn_latency,uint16_t supervision_timeout)51   void OnConnectionUpdate(
52       hci::ErrorCode hci_status, uint16_t conn_interval, uint16_t conn_latency, uint16_t supervision_timeout) override {
53     SAVE_OR_CALL(OnConnectionUpdate, hci_status, conn_interval, conn_latency, supervision_timeout)
54   }
55 
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)56   void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override {
57     SAVE_OR_CALL(OnDataLengthChange, tx_octets, tx_time, rx_octets, rx_time)
58   }
59 
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)60   void OnReadRemoteVersionInformationComplete(
61       hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) {
62     bluetooth::os::LogMetricRemoteVersionInfo(
63         connection_handle_, static_cast<uint8_t>(hci_status), lmp_version, manufacturer_name, sub_version);
64     SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name, sub_version);
65   }
OnPhyUpdate(hci::ErrorCode hci_status,uint8_t tx_phy,uint8_t rx_phy)66   void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {
67     SAVE_OR_CALL(OnPhyUpdate, hci_status, tx_phy, rx_phy);
68   }
OnLocalAddressUpdate(AddressWithType address_with_type)69   void OnLocalAddressUpdate(AddressWithType address_with_type) override {
70     SAVE_OR_CALL(OnLocalAddressUpdate, address_with_type);
71   }
72 
OnDisconnection(ErrorCode reason)73   void OnDisconnection(ErrorCode reason) override {
74     SAVE_OR_CALL(OnDisconnection, reason);
75   }
76 #undef SAVE_OR_CALL
77 
78   LeAclConnectionInterface* le_acl_connection_interface_;
79   os::Handler* client_handler_ = nullptr;
80   LeConnectionManagementCallbacks* client_callbacks_ = nullptr;
81   std::list<common::OnceClosure> queued_callbacks_;
82   uint16_t connection_handle_;
83 };
84 
85 struct LeAclConnection::impl {
implbluetooth::hci::acl_manager::LeAclConnection::impl86   impl(LeAclConnectionInterface* le_acl_connection_interface, std::shared_ptr<Queue> queue, uint16_t connection_handle)
87       : queue_(std::move(queue)), tracker(le_acl_connection_interface, connection_handle) {}
GetEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl88   LeConnectionManagementCallbacks* GetEventCallbacks() {
89     ASSERT(!callbacks_given_);
90     callbacks_given_ = true;
91     return &tracker;
92   }
93 
94   bool callbacks_given_{false};
95   std::shared_ptr<Queue> queue_;
96   LeAclConnectionTracker tracker;
97 };
98 
LeAclConnection()99 LeAclConnection::LeAclConnection()
100     : AclConnection(), local_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS),
101       remote_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS) {}
102 
LeAclConnection(std::shared_ptr<Queue> queue,LeAclConnectionInterface * le_acl_connection_interface,uint16_t handle,AddressWithType local_address,AddressWithType remote_address,Role role)103 LeAclConnection::LeAclConnection(
104     std::shared_ptr<Queue> queue,
105     LeAclConnectionInterface* le_acl_connection_interface,
106     uint16_t handle,
107     AddressWithType local_address,
108     AddressWithType remote_address,
109     Role role)
110     : AclConnection(queue->GetUpEnd(), handle),
111       local_address_(local_address),
112       remote_address_(remote_address),
113       role_(role) {
114   pimpl_ = new LeAclConnection::impl(le_acl_connection_interface, std::move(queue), handle);
115 }
116 
~LeAclConnection()117 LeAclConnection::~LeAclConnection() {
118   delete pimpl_;
119 }
120 
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)121 void LeAclConnection::RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
122   return pimpl_->tracker.RegisterCallbacks(callbacks, handler);
123 }
124 
Disconnect(DisconnectReason reason)125 void LeAclConnection::Disconnect(DisconnectReason reason) {
126   pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
127       DisconnectBuilder::Create(handle_, reason),
128       pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
129         ASSERT(status.IsValid());
130         ASSERT(status.GetCommandOpCode() == OpCode::DISCONNECT);
131         auto disconnect_status = DisconnectStatusView::Create(status);
132         ASSERT(disconnect_status.IsValid());
133         auto error_code = disconnect_status.GetStatus();
134         if (error_code != ErrorCode::SUCCESS) {
135           LOG_INFO("Disconnect status %s", ErrorCodeText(error_code).c_str());
136         }
137       }));
138 }
139 
GetEventCallbacks()140 LeConnectionManagementCallbacks* LeAclConnection::GetEventCallbacks() {
141   return pimpl_->GetEventCallbacks();
142 }
143 
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)144 bool LeAclConnection::LeConnectionUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency,
145                                          uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length) {
146   if (!check_connection_parameters(conn_interval_min, conn_interval_max, conn_latency, supervision_timeout)) {
147     LOG_ERROR("Invalid parameter");
148     return false;
149   }
150   pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
151       LeConnectionUpdateBuilder::Create(handle_, conn_interval_min, conn_interval_max, conn_latency,
152                                         supervision_timeout, min_ce_length, max_ce_length),
153       pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
154         ASSERT(status.IsValid());
155         ASSERT(status.GetCommandOpCode() == OpCode::LE_CONNECTION_UPDATE);
156       }));
157   return true;
158 }
159 
ReadRemoteVersionInformation()160 bool LeAclConnection::ReadRemoteVersionInformation() {
161   pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
162       ReadRemoteVersionInformationBuilder::Create(handle_),
163       pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
164         ASSERT(status.IsValid());
165         ASSERT(status.GetCommandOpCode() == OpCode::READ_REMOTE_VERSION_INFORMATION);
166       }));
167   return true;
168 }
169 
check_connection_parameters(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout)170 bool LeAclConnection::check_connection_parameters(
171     uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
172   if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
173       conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A ||
174       supervision_timeout > 0x0C80) {
175     LOG_ERROR("Invalid parameter");
176     return false;
177   }
178   // The Maximum interval in milliseconds will be conn_interval_max * 1.25 ms
179   // The Timeout in milliseconds will be expected_supervision_timeout * 10 ms
180   // The Timeout in milliseconds shall be larger than (1 + Latency) * Interval_Max * 2, where Interval_Max is given in
181   // milliseconds.
182   uint32_t supervision_timeout_min = (uint32_t)(1 + conn_latency) * conn_interval_max * 2 + 1;
183   if (supervision_timeout * 8 < supervision_timeout_min || conn_interval_max < conn_interval_min) {
184     LOG_ERROR("Invalid parameter");
185     return false;
186   }
187 
188   return true;
189 }
190 
191 }  // namespace acl_manager
192 }  // namespace hci
193 }  // namespace bluetooth
194