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