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 <optional>
20 #include <queue>
21 #include <unordered_set>
22 #include <variant>
23
24 #include "hci/acl_manager/acl_scheduler.h"
25 #include "hci/acl_manager/event_checkers.h"
26 #include "hci/hci_layer.h"
27
28 namespace bluetooth {
29 namespace hci {
30
31 struct RemoteNameRequestModule::impl {
32 public:
implbluetooth::hci::RemoteNameRequestModule::impl33 impl(const RemoteNameRequestModule& module) : module_(module) {}
34
Startbluetooth::hci::RemoteNameRequestModule::impl35 void Start() {
36 LOG_INFO("Starting RemoteNameRequestModule");
37 hci_layer_ = module_.GetDependency<HciLayer>();
38 acl_scheduler_ = module_.GetDependency<acl_manager::AclScheduler>();
39 handler_ = module_.GetHandler();
40
41 hci_layer_->RegisterEventHandler(
42 EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION,
43 handler_->BindOn(
44 this, &RemoteNameRequestModule::impl::on_remote_host_supported_features_notification));
45 hci_layer_->RegisterEventHandler(
46 EventCode::REMOTE_NAME_REQUEST_COMPLETE,
47 handler_->BindOn(this, &RemoteNameRequestModule::impl::on_remote_name_request_complete));
48 }
49
Stopbluetooth::hci::RemoteNameRequestModule::impl50 void Stop() {
51 LOG_INFO("Stopping RemoteNameRequestModule");
52 hci_layer_->UnregisterEventHandler(EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION);
53 hci_layer_->UnregisterEventHandler(EventCode::REMOTE_NAME_REQUEST_COMPLETE);
54 }
55
StartRemoteNameRequestbluetooth::hci::RemoteNameRequestModule::impl56 void StartRemoteNameRequest(
57 Address address,
58 std::unique_ptr<RemoteNameRequestBuilder> request,
59 CompletionCallback on_completion,
60 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
61 RemoteNameCallback on_remote_name_complete) {
62 LOG_INFO("Enqueuing remote name request to %s", address.ToRedactedStringForLogging().c_str());
63
64 // This callback needs to be shared between the *start* callback and the *cancel_completed*
65 // callback, so we refcount it for safety. But since the scheduler guarantees that exactly one
66 // of these callbacks will be invokes, this is safe.
67 auto on_remote_name_complete_ptr =
68 std::make_shared<RemoteNameCallback>(std::move(on_remote_name_complete));
69
70 acl_scheduler_->EnqueueRemoteNameRequest(
71 address,
72 handler_->BindOnceOn(
73 this,
74 &impl::actually_start_remote_name_request,
75 address,
76 std::move(request),
77 std::move(on_completion),
78 std::move(on_remote_host_supported_features_notification),
79 on_remote_name_complete_ptr),
80 handler_->BindOnce(
81 [&](Address address, std::shared_ptr<RemoteNameCallback> on_remote_name_complete_ptr) {
82 LOG_INFO(
83 "Dequeued remote name request to %s since it was cancelled",
84 address.ToRedactedStringForLogging().c_str());
85 on_remote_name_complete_ptr->Invoke(ErrorCode::PAGE_TIMEOUT, {});
86 },
87 address,
88 on_remote_name_complete_ptr));
89 }
90
CancelRemoteNameRequestbluetooth::hci::RemoteNameRequestModule::impl91 void CancelRemoteNameRequest(Address address) {
92 LOG_INFO(
93 "Enqueuing cancel of remote name request to %s",
94 address.ToRedactedStringForLogging().c_str());
95 acl_scheduler_->CancelRemoteNameRequest(
96 address, handler_->BindOnceOn(this, &impl::actually_cancel_remote_name_request, address));
97 }
98
ReportRemoteNameRequestCancellationbluetooth::hci::RemoteNameRequestModule::impl99 void ReportRemoteNameRequestCancellation(Address address) {
100 if (pending_) {
101 LOG_INFO(
102 "Received CONNECTION_COMPLETE (corresponding INCORRECTLY to an RNR cancellation) from %s",
103 address.ToRedactedStringForLogging().c_str());
104 pending_ = false;
105 on_remote_name_complete_.Invoke(ErrorCode::UNKNOWN_CONNECTION, {});
106 acl_scheduler_->ReportRemoteNameRequestCompletion(address);
107 } else {
108 LOG_ERROR(
109 "Received unexpected CONNECTION_COMPLETE when no Remote Name Request OR ACL connection "
110 "is outstanding");
111 }
112 }
113
114 private:
actually_start_remote_name_requestbluetooth::hci::RemoteNameRequestModule::impl115 void actually_start_remote_name_request(
116 Address address,
117 std::unique_ptr<RemoteNameRequestBuilder> request,
118 CompletionCallback on_completion,
119 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
120 std::shared_ptr<RemoteNameCallback> on_remote_name_complete_ptr) {
121 LOG_INFO("Starting remote name request to %s", address.ToRedactedStringForLogging().c_str());
122 ASSERT(pending_ == false);
123 pending_ = true;
124 on_remote_host_supported_features_notification_ =
125 std::move(on_remote_host_supported_features_notification);
126 on_remote_name_complete_ = std::move(*on_remote_name_complete_ptr.get());
127 hci_layer_->EnqueueCommand(
128 std::move(request),
129 handler_->BindOnceOn(
130 this, &impl::on_start_remote_name_request_status, address, std::move(on_completion)));
131 }
132
on_start_remote_name_request_statusbluetooth::hci::RemoteNameRequestModule::impl133 void on_start_remote_name_request_status(
134 Address address, CompletionCallback on_completion, CommandStatusView status) {
135 ASSERT(pending_ == true);
136 ASSERT(status.GetCommandOpCode() == OpCode::REMOTE_NAME_REQUEST);
137 LOG_INFO(
138 "Got status %hhu when starting remote name request to to %s",
139 status.GetStatus(),
140 address.ToString().c_str());
141 on_completion.Invoke(status.GetStatus());
142 if (status.GetStatus() != ErrorCode::SUCCESS /* pending */) {
143 pending_ = false;
144 acl_scheduler_->ReportRemoteNameRequestCompletion(address);
145 }
146 }
147
actually_cancel_remote_name_requestbluetooth::hci::RemoteNameRequestModule::impl148 void actually_cancel_remote_name_request(Address address) {
149 ASSERT(pending_ == true);
150 LOG_INFO("Cancelling remote name request to %s", address.ToRedactedStringForLogging().c_str());
151 hci_layer_->EnqueueCommand(
152 RemoteNameRequestCancelBuilder::Create(address),
153 handler_->BindOnce(
154 &acl_manager::check_command_complete<RemoteNameRequestCancelCompleteView>));
155 }
156
on_remote_host_supported_features_notificationbluetooth::hci::RemoteNameRequestModule::impl157 void on_remote_host_supported_features_notification(EventView view) {
158 auto packet = RemoteHostSupportedFeaturesNotificationView::Create(view);
159 ASSERT(packet.IsValid());
160 if (pending_) {
161 LOG_INFO(
162 "Received REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION from %s",
163 packet.GetBdAddr().ToRedactedStringForLogging().c_str());
164 on_remote_host_supported_features_notification_.Invoke(packet.GetHostSupportedFeatures());
165 } else {
166 LOG_ERROR(
167 "Received unexpected REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION when no Remote Name "
168 "Request is outstanding");
169 }
170 }
171
on_remote_name_request_completebluetooth::hci::RemoteNameRequestModule::impl172 void on_remote_name_request_complete(EventView view) {
173 auto packet = RemoteNameRequestCompleteView::Create(view);
174 ASSERT(packet.IsValid());
175 if (pending_) {
176 LOG_INFO(
177 "Received REMOTE_NAME_REQUEST_COMPLETE from %s",
178 packet.GetBdAddr().ToRedactedStringForLogging().c_str());
179 pending_ = false;
180 on_remote_name_complete_.Invoke(packet.GetStatus(), packet.GetRemoteName());
181 acl_scheduler_->ReportRemoteNameRequestCompletion(packet.GetBdAddr());
182 } else {
183 LOG_ERROR(
184 "Received unexpected REMOTE_NAME_REQUEST_COMPLETE when no Remote Name Request is "
185 "outstanding");
186 }
187 }
188
189 const RemoteNameRequestModule& module_;
190 HciLayer* hci_layer_;
191 acl_manager::AclScheduler* acl_scheduler_;
192 os::Handler* handler_;
193
194 bool pending_ = false;
195 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification_;
196 RemoteNameCallback on_remote_name_complete_;
197 };
198
199 const ModuleFactory RemoteNameRequestModule::Factory =
__anonac4010980202() 200 ModuleFactory([]() { return new RemoteNameRequestModule(); });
201
RemoteNameRequestModule()202 RemoteNameRequestModule::RemoteNameRequestModule() : pimpl_(std::make_unique<impl>(*this)){};
203 RemoteNameRequestModule::~RemoteNameRequestModule() = default;
204
StartRemoteNameRequest(Address address,std::unique_ptr<RemoteNameRequestBuilder> request,CompletionCallback on_completion,RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,RemoteNameCallback on_remote_name_complete)205 void RemoteNameRequestModule::StartRemoteNameRequest(
206 Address address,
207 std::unique_ptr<RemoteNameRequestBuilder> request,
208 CompletionCallback on_completion,
209 RemoteHostSupportedFeaturesCallback on_remote_host_supported_features_notification,
210 RemoteNameCallback on_remote_name_complete) {
211 CallOn(
212 pimpl_.get(),
213 &impl::StartRemoteNameRequest,
214 address,
215 std::move(request),
216 std::move(on_completion),
217 std::move(on_remote_host_supported_features_notification),
218 std::move(on_remote_name_complete));
219 }
220
CancelRemoteNameRequest(Address address)221 void RemoteNameRequestModule::CancelRemoteNameRequest(Address address) {
222 CallOn(pimpl_.get(), &impl::CancelRemoteNameRequest, address);
223 }
224
ReportRemoteNameRequestCancellation(Address address)225 void RemoteNameRequestModule::ReportRemoteNameRequestCancellation(Address address) {
226 CallOn(pimpl_.get(), &impl::ReportRemoteNameRequestCancellation, address);
227 }
228
ListDependencies(ModuleList * list) const229 void RemoteNameRequestModule::ListDependencies(ModuleList* list) const {
230 list->add<HciLayer>();
231 list->add<acl_manager::AclScheduler>();
232 }
233
Start()234 void RemoteNameRequestModule::Start() {
235 pimpl_->Start();
236 }
237
Stop()238 void RemoteNameRequestModule::Stop() {
239 pimpl_->Stop();
240 }
241
242 } // namespace hci
243 } // namespace bluetooth