1 /*
2 * Copyright 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
38 class SocketAidlCallback : public BnBluetoothSocketCallback {
39 class : public hal::SocketHalCallback {
40 public:
SocketOpenedComplete(uint64_t,hal::SocketStatus) const41 void SocketOpenedComplete(uint64_t /* socket_id */,
42 hal::SocketStatus /* status */) const override {
43 log::warn("Dropping SocketOpenedComplete event, since callback is not set");
44 }
45
SocketClose(uint64_t) const46 void SocketClose(uint64_t /* socket_id */) const override {
47 log::warn("Dropping SocketClose event, since callback is not set");
48 }
49 } kNullCallbacks;
50
51 public:
52 SocketAidlCallback() = default;
53
SetCallback(hal::SocketHalCallback const * callback)54 void SetCallback(hal::SocketHalCallback const* callback) {
55 log::assert_that(callback != nullptr, "callback != nullptr");
56 socket_hal_cb_ = callback;
57 }
58
openedComplete(int64_t socket_id,::aidl::android::hardware::bluetooth::socket::Status status,const std::string & reason)59 ::ndk::ScopedAStatus openedComplete(int64_t socket_id,
60 ::aidl::android::hardware::bluetooth::socket::Status status,
61 const std::string& reason) override {
62 log::info("socket_id: {} status: {} reason: {}", socket_id, static_cast<int>(status), reason);
63 socket_hal_cb_->SocketOpenedComplete(
64 socket_id, status == ::aidl::android::hardware::bluetooth::socket::Status::SUCCESS
65 ? hal::SocketStatus::SUCCESS
66 : hal::SocketStatus::FAILURE);
67 return ::ndk::ScopedAStatus::ok();
68 }
69
close(int64_t socket_id,const std::string & reason)70 ::ndk::ScopedAStatus close(int64_t socket_id, const std::string& reason) override {
71 log::info("socket_id: {} reason: {}", socket_id, reason);
72 socket_hal_cb_->SocketClose(socket_id);
73 return ::ndk::ScopedAStatus::ok();
74 }
75
76 private:
77 hal::SocketHalCallback const* socket_hal_cb_ = &kNullCallbacks;
78 };
79
80 class SocketHalAndroid : public SocketHal {
81 public:
IsBound() const82 bool IsBound() const { return socket_hal_instance_ != nullptr; }
83
84 protected:
ListDependencies(ModuleList *) const85 void ListDependencies(ModuleList* /*list*/) const {}
86
Start()87 void Start() override {
88 std::string instance = std::string() + IBluetoothSocket::descriptor + "/default";
89 if (!AServiceManager_isDeclared(instance.c_str())) {
90 log::error("The service {} is not declared", instance);
91 return;
92 }
93
94 ::ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str()));
95 socket_hal_instance_ = IBluetoothSocket::fromBinder(binder);
96
97 if (socket_hal_instance_ == nullptr) {
98 log::error("Failed to bind to the service {}", instance);
99 return;
100 }
101
102 socket_aidl_cb_ = ndk::SharedRefBase::make<SocketAidlCallback>();
103 ::ndk::ScopedAStatus status = socket_hal_instance_->registerCallback(socket_aidl_cb_);
104 if (!status.isOk()) {
105 log::error("registerCallback failure: {}", status.getDescription());
106 socket_hal_instance_ = nullptr;
107 return;
108 }
109
110 death_recipient_ =
111 ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new([](void* /* cookie*/) {
112 log::error("The Socket HAL service died.");
113 // At shutdown, sometimes the HAL service gets killed before Bluetooth.
114 std::this_thread::sleep_for(std::chrono::seconds(1));
115 log::fatal("Restarting Bluetooth after the socket HAL has died.");
116 }));
117
118 auto death_link = AIBinder_linkToDeath(socket_hal_instance_->asBinder().get(),
119 death_recipient_.get(), this);
120 log::assert_that(death_link == STATUS_OK,
121 "Unable to set the death recipient for the Socket HAL");
122 }
123
Stop()124 void Stop() override {
125 if (IsBound()) {
126 auto death_unlink = AIBinder_unlinkToDeath(socket_hal_instance_->asBinder().get(),
127 death_recipient_.get(), this);
128 if (death_unlink != STATUS_OK) {
129 log::error("Error unlinking death recipient from the Socket HAL");
130 }
131 socket_hal_instance_ = nullptr;
132 }
133 }
134
ToString() const135 std::string ToString() const override { return std::string("SocketHalAndroid"); }
136
GetSocketCapabilities() const137 hal::SocketCapabilities GetSocketCapabilities() const override {
138 if (!IsBound()) {
139 return {};
140 }
141 ::aidl::android::hardware::bluetooth::socket::SocketCapabilities socket_capabilities;
142 ::ndk::ScopedAStatus status = socket_hal_instance_->getSocketCapabilities(&socket_capabilities);
143 if (!status.isOk()) {
144 log::info("Failed to get socket capabilities");
145 return {};
146 }
147 if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets < 0) {
148 log::error("Invalid leCocCapabilities.numberOfSupportedSockets: {}",
149 socket_capabilities.leCocCapabilities.numberOfSupportedSockets);
150 return {};
151 }
152 if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets) {
153 if (socket_capabilities.leCocCapabilities.mtu < kLeCocMtuMin ||
154 socket_capabilities.leCocCapabilities.mtu > kLeCocMtuMax) {
155 log::error("Invalid leCocCapabilities.mtu: {}", socket_capabilities.leCocCapabilities.mtu);
156 return {};
157 }
158 }
159 log::info("le_coc_capabilities number_of_supported_sockets: {}, mtu: {}",
160 socket_capabilities.leCocCapabilities.numberOfSupportedSockets,
161 socket_capabilities.leCocCapabilities.mtu);
162 return hal::SocketCapabilities{
163 .le_coc_capabilities.number_of_supported_sockets =
164 socket_capabilities.leCocCapabilities.numberOfSupportedSockets,
165 .le_coc_capabilities.mtu =
166 static_cast<uint16_t>(socket_capabilities.leCocCapabilities.mtu)};
167 }
168
RegisterCallback(hal::SocketHalCallback const * callback)169 bool RegisterCallback(hal::SocketHalCallback const* callback) override {
170 if (!IsBound()) {
171 return false;
172 }
173 socket_aidl_cb_->SetCallback(callback);
174 return true;
175 }
176
Opened(const hal::SocketContext & context) const177 bool Opened(const hal::SocketContext& context) const override {
178 if (!IsBound()) {
179 return false;
180 }
181 log::info("socket_id: {}, name: {}, acl_connection_handle: {}, hub_id: {}, endpoint_id: {}",
182 context.socket_id, context.name, context.acl_connection_handle,
183 context.endpoint_info.hub_id, context.endpoint_info.endpoint_id);
184 ::aidl::android::hardware::bluetooth::socket::SocketContext hal_context = {
185 .socketId = static_cast<int64_t>(context.socket_id),
186 .name = context.name,
187 .aclConnectionHandle = context.acl_connection_handle,
188 .endpointId.id = static_cast<int64_t>(context.endpoint_info.endpoint_id),
189 .endpointId.hubId = static_cast<int64_t>(context.endpoint_info.hub_id),
190 };
191 if (std::holds_alternative<hal::LeCocChannelInfo>(context.channel_info)) {
192 auto& le_coc_context = std::get<hal::LeCocChannelInfo>(context.channel_info);
193 hal_context.channelInfo = ::aidl::android::hardware::bluetooth::socket::LeCocChannelInfo(
194 le_coc_context.local_cid, le_coc_context.remote_cid, le_coc_context.psm,
195 le_coc_context.local_mtu, le_coc_context.remote_mtu, le_coc_context.local_mps,
196 le_coc_context.remote_mps, le_coc_context.initial_rx_credits,
197 le_coc_context.initial_tx_credits);
198 log::info(
199 "le_coc local_cid: {}, remote_cid: {}, psm: {}, local_mtu: {}, remote_mtu: {}, "
200 "local_mps: {}, remote_mps: {}, initial_rx_credits: {}, initial_tx_credits: {}",
201 le_coc_context.local_cid, le_coc_context.remote_cid, le_coc_context.psm,
202 le_coc_context.local_mtu, le_coc_context.remote_mtu, le_coc_context.local_mps,
203 le_coc_context.remote_mps, le_coc_context.initial_rx_credits,
204 le_coc_context.initial_tx_credits);
205 } else {
206 log::error("Unsupported protocol");
207 return false;
208 }
209 ::ndk::ScopedAStatus status = socket_hal_instance_->opened(hal_context);
210 if (!status.isOk()) {
211 log::error("Opened failure: {}", status.getDescription());
212 return false;
213 }
214 return true;
215 }
216
Closed(uint64_t socket_id) const217 void Closed(uint64_t socket_id) const override {
218 if (!IsBound()) {
219 return;
220 }
221 log::info("socket_id: {}", socket_id);
222 ::ndk::ScopedAStatus status = socket_hal_instance_->closed(socket_id);
223 if (!status.isOk()) {
224 log::info("Closed failure: {}", status.getDescription());
225 }
226 }
227
228 private:
229 std::shared_ptr<IBluetoothSocket> socket_hal_instance_;
230 std::shared_ptr<SocketAidlCallback> socket_aidl_cb_;
231 ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
232 };
233
__anon8f451af30302() 234 const ModuleFactory SocketHal::Factory = ModuleFactory([]() { return new SocketHalAndroid(); });
235
236 } // namespace bluetooth::hal
237