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 "bluetooth_socket_fbs_hal.h"
18
19 #include <cstdint>
20 #include <future>
21
22 #include "chre/platform/shared/host_protocol_common.h"
23 #include "chre_host/generated/host_messages_generated.h"
24 #include "chre_host/host_protocol_host.h"
25 #include "chre_host/log.h"
26 #include "flatbuffers/flatbuffers.h"
27
28 namespace aidl::android::hardware::bluetooth::socket::impl {
29
30 using ::android::chre::getStringFromByteVector;
31 using ndk::ScopedAStatus;
32
registerCallback(const std::shared_ptr<IBluetoothSocketCallback> & callback)33 ScopedAStatus BluetoothSocketFbsHal::registerCallback(
34 const std::shared_ptr<IBluetoothSocketCallback> &callback) {
35 mCallback = callback;
36 return ScopedAStatus::ok();
37 }
38
getSocketCapabilities(SocketCapabilities * result)39 ScopedAStatus BluetoothSocketFbsHal::getSocketCapabilities(
40 SocketCapabilities *result) {
41 std::future<SocketCapabilities> future = mCapabilitiesPromise.get_future();
42
43 flatbuffers::FlatBufferBuilder builder(64);
44 auto socketCapabilitiesRequest =
45 ::chre::fbs::CreateBtSocketCapabilitiesRequest(builder);
46 ::chre::HostProtocolCommon::finalize(
47 builder, ::chre::fbs::ChreMessage::BtSocketCapabilitiesRequest,
48 socketCapabilitiesRequest.Union());
49
50 if (!mOffloadLinkAvailable) {
51 LOGE("BT Socket Offload Link not available");
52 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
53 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
54 "BT offload link not available");
55 }
56
57 if (!mOffloadLink->sendMessageToOffloadStack(builder.GetBufferPointer(),
58 builder.GetSize())) {
59 LOGE("Failed to send BT socket capabilities request message");
60 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
61 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
62 "Failed to send BT socket message");
63 }
64
65 std::future_status status = future.wait_for(std::chrono::seconds(5));
66 if (status != std::future_status::ready) {
67 LOGE("BT Socket capabilities request timed out");
68 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
69 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
70 "BT socket capabilities request timed out");
71 }
72
73 *result = future.get();
74 return ScopedAStatus::ok();
75 }
76
opened(const SocketContext & context)77 ScopedAStatus BluetoothSocketFbsHal::opened(const SocketContext &context) {
78 LOGD("Host opened BT offload socket ID=%" PRIu64, context.socketId);
79 if (!mOffloadLinkAvailable) {
80 LOGE("BT Socket Offload Link not available");
81 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
82 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
83 "BT offload link not available");
84 }
85 if (context.channelInfo.getTag() != ChannelInfo::Tag::leCocChannelInfo) {
86 LOGE("Got open request for unsupported socket type %" PRId32,
87 context.channelInfo.getTag());
88 sendOpenedCompleteMessage(context.socketId, Status::FAILURE,
89 "Unsupported socket type");
90 return ScopedAStatus::ok();
91 }
92 flatbuffers::FlatBufferBuilder builder(1028);
93 auto socketName = ::chre::HostProtocolCommon::addStringAsByteVector(
94 builder, context.name.c_str());
95 const auto &socketChannelInfo =
96 context.channelInfo.get<ChannelInfo::Tag::leCocChannelInfo>();
97 auto leCocChannelInfo = ::chre::fbs::CreateLeCocChannelInfo(
98 builder, socketChannelInfo.localCid, socketChannelInfo.remoteCid,
99 socketChannelInfo.psm, socketChannelInfo.localMtu,
100 socketChannelInfo.remoteMtu, socketChannelInfo.localMps,
101 socketChannelInfo.remoteMps, socketChannelInfo.initialRxCredits,
102 socketChannelInfo.initialTxCredits);
103
104 auto socketOpen = ::chre::fbs::CreateBtSocketOpen(
105 builder, context.socketId, socketName, context.aclConnectionHandle,
106 ::chre::fbs::ChannelInfo::LeCocChannelInfo, leCocChannelInfo.Union(),
107 context.endpointId.hubId, context.endpointId.id);
108 ::chre::HostProtocolCommon::finalize(
109 builder, ::chre::fbs::ChreMessage::BtSocketOpen, socketOpen.Union());
110
111 if (!mOffloadLink->sendMessageToOffloadStack(builder.GetBufferPointer(),
112 builder.GetSize())) {
113 LOGE("Failed to send BT socket opened message");
114 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
115 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
116 "Failed to send BT socket message");
117 }
118 return ScopedAStatus::ok();
119 }
120
closed(int64_t socketId)121 ScopedAStatus BluetoothSocketFbsHal::closed(int64_t socketId) {
122 LOGD("Host closed BT offload socket ID=%" PRIu64, socketId);
123 if (!mOffloadLinkAvailable) {
124 LOGE("BT Socket Offload Link not available");
125 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
126 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
127 "BT offload link not available");
128 }
129
130 flatbuffers::FlatBufferBuilder builder(64);
131 auto socketCloseResponse =
132 ::chre::fbs::CreateBtSocketCloseResponse(builder, socketId);
133 ::chre::HostProtocolCommon::finalize(
134 builder, ::chre::fbs::ChreMessage::BtSocketCloseResponse,
135 socketCloseResponse.Union());
136
137 if (!mOffloadLink->sendMessageToOffloadStack(builder.GetBufferPointer(),
138 builder.GetSize())) {
139 LOGE("Failed to send BT socket closed message");
140 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
141 static_cast<int32_t>(STATUS_UNKNOWN_ERROR),
142 "Failed to send BT socket message");
143 }
144
145 return ScopedAStatus::ok();
146 }
147
handleMessageFromOffloadStack(const void * message,size_t length)148 void BluetoothSocketFbsHal::handleMessageFromOffloadStack(const void *message,
149 size_t length) {
150 if (!chre::HostProtocolCommon::verifyMessage(message, length)) {
151 LOGE("Could not decode Bluetooth Socket message");
152 } else {
153 std::unique_ptr<chre::fbs::MessageContainerT> container =
154 chre::fbs::UnPackMessageContainer(message);
155 chre::fbs::ChreMessageUnion &msg = container->message;
156 switch (container->message.type) {
157 case chre::fbs::ChreMessage::BtSocketOpenResponse:
158 handleBtSocketOpenResponse(*msg.AsBtSocketOpenResponse());
159 break;
160
161 case chre::fbs::ChreMessage::BtSocketClose:
162 handleBtSocketClose(*msg.AsBtSocketClose());
163 break;
164
165 case chre::fbs::ChreMessage::BtSocketCapabilitiesResponse:
166 handleBtSocketCapabilitiesResponse(
167 *msg.AsBtSocketCapabilitiesResponse());
168 break;
169
170 default:
171 LOGW("Got unexpected Bluetooth Socket message type %" PRIu8,
172 static_cast<uint8_t>(msg.type));
173 break;
174 }
175 }
176 }
177
handleBtSocketOpenResponse(const::chre::fbs::BtSocketOpenResponseT & response)178 void BluetoothSocketFbsHal::handleBtSocketOpenResponse(
179 const ::chre::fbs::BtSocketOpenResponseT &response) {
180 std::string reason = std::string(getStringFromByteVector(response.reason));
181 LOGD("Got BT Socket open response, socket ID=%" PRIu64
182 ", status=%d, reason=%s",
183 response.socketId, response.status, reason.c_str());
184 sendOpenedCompleteMessage(
185 response.socketId,
186 response.status == ::chre::fbs::BtSocketOpenStatus::SUCCESS
187 ? Status::SUCCESS
188 : Status::FAILURE,
189 reason);
190 }
191
handleBtSocketClose(const::chre::fbs::BtSocketCloseT & message)192 void BluetoothSocketFbsHal::handleBtSocketClose(
193 const ::chre::fbs::BtSocketCloseT &message) {
194 std::string reason = std::string(getStringFromByteVector(message.reason));
195 LOGD("Got BT Socket close, socket ID=%" PRIu64 ", reason=%s",
196 message.socketId, reason.c_str());
197 if (mCallback == nullptr) {
198 LOGE("Received socket close message with no registered callback");
199 return;
200 }
201 mCallback->close(message.socketId, reason);
202 }
203
handleBtSocketCapabilitiesResponse(const::chre::fbs::BtSocketCapabilitiesResponseT & response)204 void BluetoothSocketFbsHal::handleBtSocketCapabilitiesResponse(
205 const ::chre::fbs::BtSocketCapabilitiesResponseT &response) {
206 LOGD("Got BT Socket capabilities response");
207 SocketCapabilities capabilities = {
208 .leCocCapabilities =
209 {
210 .numberOfSupportedSockets =
211 response.leCocCapabilities->numberOfSupportedSockets,
212 .mtu = response.leCocCapabilities->mtu,
213 },
214 .rfcommCapabilities =
215 {
216 .numberOfSupportedSockets =
217 response.rfcommCapabilities->numberOfSupportedSockets,
218 .maxFrameSize = response.rfcommCapabilities->maxFrameSize,
219 },
220 };
221 mCapabilitiesPromise.set_value(capabilities);
222 }
223
sendOpenedCompleteMessage(int64_t socketId,Status status,std::string reason)224 void BluetoothSocketFbsHal::sendOpenedCompleteMessage(int64_t socketId,
225 Status status,
226 std::string reason) {
227 if (mCallback == nullptr) {
228 LOGE("Sending socket opened complete with no registered callback");
229 return;
230 }
231 mCallback->openedComplete(socketId, status, reason);
232 }
233
234 } // namespace aidl::android::hardware::bluetooth::socket::impl
235