1 /*
2 * Copyright (C) 2024 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 <aidl/android/hardware/bluetooth/socket/BnBluetoothSocketCallback.h>
18 #include <aidl/android/hardware/bluetooth/socket/IBluetoothSocket.h>
19 #include <aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.h>
20 #include <android/binder_manager.h>
21 #include <bluetooth/log.h>
22
23 // syslog.h conflicts with libchrome/base/logging.h
24 #undef LOG_DEBUG
25 #undef LOG_INFO
26 #undef LOG_WARNING
27
28 #include "hal/socket_hal.h"
29
30 using ::aidl::android::hardware::bluetooth::socket::BnBluetoothSocketCallback;
31 using ::aidl::android::hardware::bluetooth::socket::IBluetoothSocket;
32
33 namespace bluetooth::hal {
34
35 constexpr uint16_t kLeCocMtuMin = 23;
36 constexpr uint16_t kLeCocMtuMax = 65535;
37 constexpr uint16_t kRfcommFrameSizeMin = 23;
38 constexpr uint16_t kRfcommFrameSizeMax = 32767;
39
40 class SocketAidlCallback : public BnBluetoothSocketCallback {
41 class : public hal::SocketHalCallback {
42 public:
SocketOpenedComplete(uint64_t,hal::SocketStatus) const43 void SocketOpenedComplete(uint64_t /* socket_id */,
44 hal::SocketStatus /* status */) const override {
45 log::warn("Dropping SocketOpenedComplete event, since callback is not set");
46 }
47
SocketClose(uint64_t) const48 void SocketClose(uint64_t /* socket_id */) const override {
49 log::warn("Dropping SocketClose event, since callback is not set");
50 }
51 } kNullCallbacks;
52
53 public:
54 SocketAidlCallback() = default;
55
SetCallback(hal::SocketHalCallback const * callback)56 void SetCallback(hal::SocketHalCallback const* callback) {
57 log::assert_that(callback != nullptr, "callback != nullptr");
58 socket_hal_cb_ = callback;
59 }
60
openedComplete(int64_t socket_id,::aidl::android::hardware::bluetooth::socket::Status status,const std::string & reason)61 ::ndk::ScopedAStatus openedComplete(int64_t socket_id,
62 ::aidl::android::hardware::bluetooth::socket::Status status,
63 const std::string& reason) override {
64 log::info("socket_id: {} status: {} reason: {}", static_cast<uint64_t>(socket_id),
65 static_cast<int>(status), reason);
66 socket_hal_cb_->SocketOpenedComplete(
67 socket_id, status == ::aidl::android::hardware::bluetooth::socket::Status::SUCCESS
68 ? hal::SocketStatus::SUCCESS
69 : hal::SocketStatus::FAILURE);
70 return ::ndk::ScopedAStatus::ok();
71 }
72
close(int64_t socket_id,const std::string & reason)73 ::ndk::ScopedAStatus close(int64_t socket_id, const std::string& reason) override {
74 log::info("socket_id: {} reason: {}", static_cast<uint64_t>(socket_id), reason);
75 socket_hal_cb_->SocketClose(socket_id);
76 return ::ndk::ScopedAStatus::ok();
77 }
78
79 private:
80 hal::SocketHalCallback const* socket_hal_cb_ = &kNullCallbacks;
81 };
82
83 class SocketHalAndroid : public SocketHal {
84 public:
IsBound() const85 bool IsBound() const { return socket_hal_instance_ != nullptr; }
86
87 protected:
ListDependencies(ModuleList *) const88 void ListDependencies(ModuleList* /*list*/) const {}
89
Start()90 void Start() override {
91 std::string instance = std::string() + IBluetoothSocket::descriptor + "/default";
92 if (!AServiceManager_isDeclared(instance.c_str())) {
93 log::error("The service {} is not declared", instance);
94 return;
95 }
96
97 ::ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str()));
98 socket_hal_instance_ = IBluetoothSocket::fromBinder(binder);
99
100 if (socket_hal_instance_ == nullptr) {
101 log::error("Failed to bind to the service {}", instance);
102 return;
103 }
104
105 socket_aidl_cb_ = ndk::SharedRefBase::make<SocketAidlCallback>();
106 ::ndk::ScopedAStatus status = socket_hal_instance_->registerCallback(socket_aidl_cb_);
107 if (!status.isOk()) {
108 log::error("registerCallback failure: {}", status.getDescription());
109 socket_hal_instance_ = nullptr;
110 return;
111 }
112
113 death_recipient_ =
114 ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new([](void* /* cookie*/) {
115 log::error("The Socket HAL service died.");
116 // At shutdown, sometimes the HAL service gets killed before Bluetooth.
117 std::this_thread::sleep_for(std::chrono::seconds(1));
118 log::fatal("Restarting Bluetooth after the socket HAL has died.");
119 }));
120
121 auto death_link = AIBinder_linkToDeath(socket_hal_instance_->asBinder().get(),
122 death_recipient_.get(), this);
123 log::assert_that(death_link == STATUS_OK,
124 "Unable to set the death recipient for the Socket HAL");
125 }
126
Stop()127 void Stop() override {
128 if (IsBound()) {
129 auto death_unlink = AIBinder_unlinkToDeath(socket_hal_instance_->asBinder().get(),
130 death_recipient_.get(), this);
131 if (death_unlink != STATUS_OK) {
132 log::error("Error unlinking death recipient from the Socket HAL");
133 }
134 socket_hal_instance_ = nullptr;
135 }
136 }
137
ToString() const138 std::string ToString() const override { return std::string("SocketHalAndroid"); }
139
GetSocketCapabilities() const140 hal::SocketCapabilities GetSocketCapabilities() const override {
141 if (!IsBound()) {
142 return {};
143 }
144 ::aidl::android::hardware::bluetooth::socket::SocketCapabilities socket_capabilities;
145 ::ndk::ScopedAStatus status = socket_hal_instance_->getSocketCapabilities(&socket_capabilities);
146 if (!status.isOk()) {
147 log::info("Failed to get socket capabilities");
148 return {};
149 }
150 if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets < 0) {
151 log::error("Invalid leCocCapabilities.numberOfSupportedSockets: {}",
152 socket_capabilities.leCocCapabilities.numberOfSupportedSockets);
153 return {};
154 }
155 if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets) {
156 if (socket_capabilities.leCocCapabilities.mtu < kLeCocMtuMin ||
157 socket_capabilities.leCocCapabilities.mtu > kLeCocMtuMax) {
158 log::error("Invalid leCocCapabilities.mtu: {}", socket_capabilities.leCocCapabilities.mtu);
159 return {};
160 }
161 }
162 log::info("le_coc_capabilities number_of_supported_sockets: {}, mtu: {}",
163 socket_capabilities.leCocCapabilities.numberOfSupportedSockets,
164 socket_capabilities.leCocCapabilities.mtu);
165
166 if (socket_capabilities.rfcommCapabilities.numberOfSupportedSockets < 0) {
167 log::error("Invalid rfcommCapabilities.numberOfSupportedSockets: {}",
168 socket_capabilities.rfcommCapabilities.numberOfSupportedSockets);
169 return {};
170 }
171 if (socket_capabilities.rfcommCapabilities.numberOfSupportedSockets) {
172 if (socket_capabilities.rfcommCapabilities.maxFrameSize < kRfcommFrameSizeMin ||
173 socket_capabilities.rfcommCapabilities.maxFrameSize > kRfcommFrameSizeMax) {
174 log::error("Invalid rfcommCapabilities.maxFrameSize: {}",
175 socket_capabilities.rfcommCapabilities.maxFrameSize);
176 return {};
177 }
178 }
179 log::info("rfcomm_capabilities number_of_supported_sockets: {}, max_frame_size: {}",
180 socket_capabilities.rfcommCapabilities.numberOfSupportedSockets,
181 socket_capabilities.rfcommCapabilities.maxFrameSize);
182
183 return hal::SocketCapabilities{
184 .le_coc_capabilities.number_of_supported_sockets =
185 socket_capabilities.leCocCapabilities.numberOfSupportedSockets,
186 .le_coc_capabilities.mtu =
187 static_cast<uint16_t>(socket_capabilities.leCocCapabilities.mtu),
188 .rfcomm_capabilities.number_of_supported_sockets =
189 socket_capabilities.rfcommCapabilities.numberOfSupportedSockets,
190 .rfcomm_capabilities.max_frame_size =
191 static_cast<uint16_t>(socket_capabilities.rfcommCapabilities.maxFrameSize)};
192 }
193
RegisterCallback(hal::SocketHalCallback const * callback)194 bool RegisterCallback(hal::SocketHalCallback const* callback) override {
195 if (!IsBound()) {
196 return false;
197 }
198 socket_aidl_cb_->SetCallback(callback);
199 return true;
200 }
201
Opened(const hal::SocketContext & context) const202 bool Opened(const hal::SocketContext& context) const override {
203 if (!IsBound()) {
204 return false;
205 }
206 log::info("socket_id: {}, name: {}, acl_connection_handle: {}, hub_id: {}, endpoint_id: {}",
207 context.socket_id, context.name, context.acl_connection_handle,
208 context.endpoint_info.hub_id, context.endpoint_info.endpoint_id);
209 ::aidl::android::hardware::bluetooth::socket::SocketContext hal_context = {
210 .socketId = static_cast<int64_t>(context.socket_id),
211 .name = context.name,
212 .aclConnectionHandle = context.acl_connection_handle,
213 .endpointId.id = static_cast<int64_t>(context.endpoint_info.endpoint_id),
214 .endpointId.hubId = static_cast<int64_t>(context.endpoint_info.hub_id),
215 };
216 if (std::holds_alternative<hal::LeCocChannelInfo>(context.channel_info)) {
217 auto& le_coc_context = std::get<hal::LeCocChannelInfo>(context.channel_info);
218 hal_context.channelInfo = ::aidl::android::hardware::bluetooth::socket::LeCocChannelInfo(
219 le_coc_context.local_cid, le_coc_context.remote_cid, le_coc_context.psm,
220 le_coc_context.local_mtu, le_coc_context.remote_mtu, le_coc_context.local_mps,
221 le_coc_context.remote_mps, le_coc_context.initial_rx_credits,
222 le_coc_context.initial_tx_credits);
223 log::info(
224 "le_coc local_cid: {}, remote_cid: {}, psm: {}, local_mtu: {}, remote_mtu: {}, "
225 "local_mps: {}, remote_mps: {}, initial_rx_credits: {}, initial_tx_credits: {}",
226 le_coc_context.local_cid, le_coc_context.remote_cid, le_coc_context.psm,
227 le_coc_context.local_mtu, le_coc_context.remote_mtu, le_coc_context.local_mps,
228 le_coc_context.remote_mps, le_coc_context.initial_rx_credits,
229 le_coc_context.initial_tx_credits);
230 } else if (std::holds_alternative<hal::RfcommChannelInfo>(context.channel_info)) {
231 auto& rfcomm_context = std::get<hal::RfcommChannelInfo>(context.channel_info);
232 hal_context.channelInfo = ::aidl::android::hardware::bluetooth::socket::RfcommChannelInfo(
233 rfcomm_context.local_cid, rfcomm_context.remote_cid, rfcomm_context.local_mtu,
234 rfcomm_context.remote_mtu, rfcomm_context.initial_rx_credits,
235 rfcomm_context.initial_tx_credits, rfcomm_context.dlci, rfcomm_context.max_frame_size,
236 rfcomm_context.mux_initiator);
237 log::info(
238 "rfcomm local_cid: {}, remote_cid: {}, local_mtu: {}, remote_mtu: {}, "
239 "initial_rx_credits: {}, initial_tx_credits: {}, dlci: {}, max_frame_size: {}, "
240 "mux_initiator: {}",
241 rfcomm_context.local_cid, rfcomm_context.remote_cid, rfcomm_context.local_mtu,
242 rfcomm_context.remote_mtu, rfcomm_context.initial_rx_credits,
243 rfcomm_context.initial_tx_credits, rfcomm_context.dlci, rfcomm_context.max_frame_size,
244 rfcomm_context.mux_initiator);
245 } else {
246 log::error("Unsupported protocol");
247 return false;
248 }
249 ::ndk::ScopedAStatus status = socket_hal_instance_->opened(hal_context);
250 if (!status.isOk()) {
251 log::error("Opened failure: {}", status.getDescription());
252 return false;
253 }
254 return true;
255 }
256
Closed(uint64_t socket_id) const257 void Closed(uint64_t socket_id) const override {
258 if (!IsBound()) {
259 return;
260 }
261 log::info("socket_id: {}", socket_id);
262 ::ndk::ScopedAStatus status = socket_hal_instance_->closed(socket_id);
263 if (!status.isOk()) {
264 log::info("Closed failure: {}", status.getDescription());
265 }
266 }
267
268 private:
269 std::shared_ptr<IBluetoothSocket> socket_hal_instance_;
270 std::shared_ptr<SocketAidlCallback> socket_aidl_cb_;
271 ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
272 };
273
__anonf0db95730302() 274 const ModuleFactory SocketHal::Factory = ModuleFactory([]() { return new SocketHalAndroid(); });
275
276 } // namespace bluetooth::hal
277