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