• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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