1 /*
2 * Copyright 2022 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 "remote_name_request.h"
18
19 #include <bluetooth/log.h>
20 #include <com_android_bluetooth_flags.h>
21
22 #include "hci/acl_manager/acl_scheduler.h"
23 #include "hci/hci_layer.h"
24 #include "hci/hci_packets.h"
25
26 namespace bluetooth {
27 namespace hci {
28
29 struct RemoteNameRequestModule::impl {
30 public:
implbluetooth::hci::RemoteNameRequestModule::impl31 impl(const RemoteNameRequestModule& module) : module_(module) {}
32
Startbluetooth::hci::RemoteNameRequestModule::impl33 void Start() {
34 log::info("Starting RemoteNameRequestModule");
35 hci_layer_ = module_.GetDependency<HciLayer>();
36 acl_scheduler_ = module_.GetDependency<acl_manager::AclScheduler>();
37 handler_ = module_.GetHandler();
38
39 hci_layer_->RegisterEventHandler(
40 EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION,
41 handler_->BindOn(
42 this, &RemoteNameRequestModule::impl::on_remote_host_supported_features_notification));
43 hci_layer_->RegisterEventHandler(
44 EventCode::REMOTE_NAME_REQUEST_COMPLETE,
45 handler_->BindOn(this, &RemoteNameRequestModule::impl::on_remote_name_request_complete));
46 }
47
Stopbluetooth::hci::RemoteNameRequestModule::impl48 void Stop() {
49 log::info("Stopping RemoteNameRequestModule");
50 hci_layer_->UnregisterEventHandler(EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION);
51 hci_layer_->UnregisterEventHandler(EventCode::REMOTE_NAME_REQUEST_COMPLETE);
52 }
53
StartRemoteNameRequestbluetooth::hci::RemoteNameRequestModule::impl54 void StartRemoteNameRequest(
55 Address address,
56 std::unique_ptr<RemoteNameRequestBuilder> request,
57 CompletionCallback on_completion,
58 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
59 RemoteNameCallback on_remote_name_complete) {
60 log::info("Enqueuing remote name request to {}", address.ToRedactedStringForLogging());
61
62 // This callback needs to be shared between the *start* callback and the *cancel_completed*
63 // callback, so we refcount it for safety. But since the scheduler guarantees that exactly one
64 // of these callbacks will be invokes, this is safe.
65 auto on_remote_name_complete_ptr =
66 std::make_shared<RemoteNameCallback>(std::move(on_remote_name_complete));
67
68 acl_scheduler_->EnqueueRemoteNameRequest(
69 address,
70 handler_->BindOnceOn(
71 this,
72 &impl::actually_start_remote_name_request,
73 address,
74 std::move(request),
75 std::move(on_completion),
76 std::move(on_remote_host_supported_features_notification),
77 on_remote_name_complete_ptr),
78 handler_->BindOnce(
79 [&](Address address, std::shared_ptr<RemoteNameCallback> on_remote_name_complete_ptr) {
80 log::info(
81 "Dequeued remote name request to {} since it was cancelled",
82 address.ToRedactedStringForLogging());
83 (*on_remote_name_complete_ptr)(ErrorCode::PAGE_TIMEOUT, {});
84 },
85 address,
86 on_remote_name_complete_ptr));
87 }
88
CancelRemoteNameRequestbluetooth::hci::RemoteNameRequestModule::impl89 void CancelRemoteNameRequest(Address address) {
90 log::info(
91 "Enqueuing cancel of remote name request to {}", address.ToRedactedStringForLogging());
92 acl_scheduler_->CancelRemoteNameRequest(
93 address, handler_->BindOnceOn(this, &impl::actually_cancel_remote_name_request, address));
94 }
95
ReportRemoteNameRequestCancellationbluetooth::hci::RemoteNameRequestModule::impl96 void ReportRemoteNameRequestCancellation(Address address) {
97 if (pending_) {
98 log::info(
99 "Received CONNECTION_COMPLETE (corresponding INCORRECTLY to an RNR cancellation) from {}",
100 address.ToRedactedStringForLogging());
101 pending_ = false;
102 on_remote_name_complete_(ErrorCode::UNKNOWN_CONNECTION, {});
103 acl_scheduler_->ReportRemoteNameRequestCompletion(address);
104 } else {
105 log::error(
106 "Received unexpected CONNECTION_COMPLETE when no Remote Name Request OR ACL connection "
107 "is outstanding");
108 }
109 }
110
111 private:
actually_start_remote_name_requestbluetooth::hci::RemoteNameRequestModule::impl112 void actually_start_remote_name_request(
113 Address address,
114 std::unique_ptr<RemoteNameRequestBuilder> request,
115 CompletionCallback on_completion,
116 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
117 std::shared_ptr<RemoteNameCallback> on_remote_name_complete_ptr) {
118 log::info("Starting remote name request to {}", address.ToRedactedStringForLogging());
119 log::assert_that(pending_ == false, "assert failed: pending_ == false");
120 pending_ = true;
121 on_remote_host_supported_features_notification_ =
122 std::move(on_remote_host_supported_features_notification);
123 on_remote_name_complete_ = std::move(*on_remote_name_complete_ptr.get());
124 hci_layer_->EnqueueCommand(
125 std::move(request),
126 handler_->BindOnceOn(
127 this, &impl::on_start_remote_name_request_status, address, std::move(on_completion)));
128 }
129
on_start_remote_name_request_statusbluetooth::hci::RemoteNameRequestModule::impl130 void on_start_remote_name_request_status(
131 Address address, CompletionCallback on_completion, CommandStatusView status) {
132 // TODO(b/294961421): Remove the ifdef when firmware fix in place. Realtek controllers
133 // unexpectedly sent a Remote Name Req Complete HCI event without the corresponding HCI command.
134 #ifndef TARGET_FLOSS
135 log::assert_that(pending_ == true, "assert failed: pending_ == true");
136 #else
137 if (pending_ != true) {
138 log::warn("Unexpected remote name response with no request pending");
139 return;
140 }
141 #endif
142 log::assert_that(
143 status.GetCommandOpCode() == OpCode::REMOTE_NAME_REQUEST,
144 "assert failed: status.GetCommandOpCode() == OpCode::REMOTE_NAME_REQUEST");
145 log::info(
146 "Started remote name request peer:{} status:{}",
147 address.ToRedactedStringForLogging(),
148 ErrorCodeText(status.GetStatus()));
149 on_completion(status.GetStatus());
150 if (status.GetStatus() != ErrorCode::SUCCESS /* pending */) {
151 pending_ = false;
152 acl_scheduler_->ReportRemoteNameRequestCompletion(address);
153 }
154 }
155
actually_cancel_remote_name_requestbluetooth::hci::RemoteNameRequestModule::impl156 void actually_cancel_remote_name_request(Address address) {
157 if (pending_) {
158 log::info("Cancelling remote name request to {}", address.ToRedactedStringForLogging());
159 hci_layer_->EnqueueCommand(
160 RemoteNameRequestCancelBuilder::Create(address),
161 handler_->BindOnceOn(this, &impl::check_cancel_status, address));
162 } else {
163 log::info(
164 "Ignoring cancel RNR as RNR event already received to {}",
165 address.ToRedactedStringForLogging());
166 }
167 }
168
on_remote_host_supported_features_notificationbluetooth::hci::RemoteNameRequestModule::impl169 void on_remote_host_supported_features_notification(EventView view) {
170 auto packet = RemoteHostSupportedFeaturesNotificationView::Create(view);
171 log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
172 if (pending_ && on_remote_host_supported_features_notification_) {
173 log::info(
174 "Received REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION from {}",
175 packet.GetBdAddr().ToRedactedStringForLogging());
176 on_remote_host_supported_features_notification_(packet.GetHostSupportedFeatures());
177 // Remove the callback so that we won't call it again.
178 on_remote_host_supported_features_notification_ = RemoteHostSupportedFeaturesCallback();
179 } else if (!pending_) {
180 log::error(
181 "Received unexpected REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION when no Remote Name "
182 "Request is outstanding");
183 } else { // callback is not set, which indicates we have processed the feature notification.
184 log::error(
185 "Received more than one REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION during Remote Name "
186 "Request");
187 }
188 }
189
completedbluetooth::hci::RemoteNameRequestModule::impl190 void completed(ErrorCode status, std::array<uint8_t, 248> name, Address address) {
191 if (pending_) {
192 log::info(
193 "Received REMOTE_NAME_REQUEST_COMPLETE from {} with status {}",
194 address.ToRedactedStringForLogging(),
195 ErrorCodeText(status));
196 pending_ = false;
197 on_remote_name_complete_(status, name);
198 acl_scheduler_->ReportRemoteNameRequestCompletion(address);
199 } else {
200 log::error(
201 "Received unexpected REMOTE_NAME_REQUEST_COMPLETE from {} with status {}",
202 address.ToRedactedStringForLogging(),
203 ErrorCodeText(status));
204 }
205 }
206
on_remote_name_request_completebluetooth::hci::RemoteNameRequestModule::impl207 void on_remote_name_request_complete(EventView view) {
208 auto packet = RemoteNameRequestCompleteView::Create(view);
209 log::assert_that(packet.IsValid(), "Invalid packet");
210 completed(packet.GetStatus(), packet.GetRemoteName(), packet.GetBdAddr());
211 }
212
check_cancel_statusbluetooth::hci::RemoteNameRequestModule::impl213 void check_cancel_status(Address remote, CommandCompleteView complete) {
214 auto packet = RemoteNameRequestCancelCompleteView::Create(complete);
215 if (!packet.IsValid()) {
216 completed(ErrorCode::UNSPECIFIED_ERROR, std::array<uint8_t, 248>{}, remote);
217 return;
218 }
219 auto status = packet.GetStatus();
220 if (status != ErrorCode::SUCCESS) {
221 completed(status, std::array<uint8_t, 248>{}, packet.GetBdAddr());
222 }
223 }
224
225 const RemoteNameRequestModule& module_;
226 HciLayer* hci_layer_;
227 acl_manager::AclScheduler* acl_scheduler_;
228 os::Handler* handler_;
229
230 bool pending_ = false;
231 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification_;
232 RemoteNameCallback on_remote_name_complete_;
233 };
234
235 const ModuleFactory RemoteNameRequestModule::Factory =
__anon1ffcd2b30202() 236 ModuleFactory([]() { return new RemoteNameRequestModule(); });
237
RemoteNameRequestModule()238 RemoteNameRequestModule::RemoteNameRequestModule() : pimpl_(std::make_unique<impl>(*this)){};
239 RemoteNameRequestModule::~RemoteNameRequestModule() = default;
240
StartRemoteNameRequest(Address address,std::unique_ptr<RemoteNameRequestBuilder> request,CompletionCallback on_completion,RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,RemoteNameCallback on_remote_name_complete)241 void RemoteNameRequestModule::StartRemoteNameRequest(
242 Address address,
243 std::unique_ptr<RemoteNameRequestBuilder> request,
244 CompletionCallback on_completion,
245 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
246 RemoteNameCallback on_remote_name_complete) {
247 CallOn(
248 pimpl_.get(),
249 &impl::StartRemoteNameRequest,
250 address,
251 std::move(request),
252 std::move(on_completion),
253 std::move(on_remote_host_supported_features_notification),
254 std::move(on_remote_name_complete));
255 }
256
CancelRemoteNameRequest(Address address)257 void RemoteNameRequestModule::CancelRemoteNameRequest(Address address) {
258 CallOn(pimpl_.get(), &impl::CancelRemoteNameRequest, address);
259 }
260
ReportRemoteNameRequestCancellation(Address address)261 void RemoteNameRequestModule::ReportRemoteNameRequestCancellation(Address address) {
262 CallOn(pimpl_.get(), &impl::ReportRemoteNameRequestCancellation, address);
263 }
264
ListDependencies(ModuleList * list) const265 void RemoteNameRequestModule::ListDependencies(ModuleList* list) const {
266 list->add<HciLayer>();
267 list->add<acl_manager::AclScheduler>();
268 }
269
Start()270 void RemoteNameRequestModule::Start() {
271 pimpl_->Start();
272 }
273
Stop()274 void RemoteNameRequestModule::Stop() {
275 pimpl_->Stop();
276 }
277
278 } // namespace hci
279 } // namespace bluetooth
280