1 /*
2 * Copyright (C) 2025 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 "host_protocol_host_v4.h"
18
19 #include <chre_host/host_protocol_host.h>
20
21 #include "permissions_util.h"
22
23 namespace android::hardware::contexthub::common::implementation {
24
25 using ::chre::fbs::ChreMessage;
26 using ::chre::fbs::EndpointId;
27 using ::chre::fbs::EndpointInfo;
28 using ::chre::fbs::MessageDeliveryStatus;
29 using ::chre::fbs::MessageHub;
30 using ::chre::fbs::MessageHubDetails;
31 using ::chre::fbs::Reason;
32 using ::flatbuffers::FlatBufferBuilder;
33 using ::flatbuffers::Offset;
34 using ::flatbuffers::Vector;
35
36 using AidlContextHubInfo =
37 ::aidl::android::hardware::contexthub::ContextHubInfo;
38 using AidlVendorHubInfo = ::aidl::android::hardware::contexthub::VendorHubInfo;
39 using AidlErrorCode = ::aidl::android::hardware::contexthub::ErrorCode;
40 using AidlRpcFormat = ::aidl::android::hardware::contexthub::Service::RpcFormat;
41
encodeGetMessageHubsAndEndpointsRequest(FlatBufferBuilder & builder)42 void HostProtocolHostV4::encodeGetMessageHubsAndEndpointsRequest(
43 FlatBufferBuilder &builder) {
44 auto msg = ::chre::fbs::CreateGetMessageHubsAndEndpointsRequest(builder);
45 finalize(builder, ChreMessage::GetMessageHubsAndEndpointsRequest,
46 msg.Union());
47 }
48
encodeGetMessageHubsAndEndpointsResponse(FlatBufferBuilder & builder,const std::vector<AidlHubInfo> & hubs,const std::vector<AidlEndpointInfo> & endpoints)49 void HostProtocolHostV4::encodeGetMessageHubsAndEndpointsResponse(
50 FlatBufferBuilder &builder, const std::vector<AidlHubInfo> &hubs,
51 const std::vector<AidlEndpointInfo> &endpoints) {
52 std::vector<Offset<MessageHub>> fbsHubs;
53 fbsHubs.reserve(hubs.size());
54 for (const auto &hub : hubs)
55 fbsHubs.push_back(aidlToFbsMessageHub(builder, hub));
56 std::vector<Offset<EndpointInfo>> fbsEndpoints;
57 for (const auto &endpoint : endpoints)
58 fbsEndpoints.push_back(aidlToFbsEndpointInfo(builder, endpoint));
59 auto hubsVector = builder.CreateVector(fbsHubs);
60 auto endpointsVector = builder.CreateVector(fbsEndpoints);
61 auto msg = ::chre::fbs::CreateGetMessageHubsAndEndpointsResponse(
62 builder, hubsVector, endpointsVector);
63 finalize(builder, ChreMessage::GetMessageHubsAndEndpointsResponse,
64 msg.Union());
65 }
66
encodeRegisterMessageHub(FlatBufferBuilder & builder,const AidlHubInfo & info)67 void HostProtocolHostV4::encodeRegisterMessageHub(FlatBufferBuilder &builder,
68 const AidlHubInfo &info) {
69 auto msg = ::chre::fbs::CreateRegisterMessageHub(
70 builder, aidlToFbsMessageHub(builder, info));
71 finalize(builder, ChreMessage::RegisterMessageHub, msg.Union());
72 }
73
encodeUnregisterMessageHub(FlatBufferBuilder & builder,int64_t id)74 void HostProtocolHostV4::encodeUnregisterMessageHub(FlatBufferBuilder &builder,
75 int64_t id) {
76 auto msg = ::chre::fbs::CreateUnregisterMessageHub(builder, id);
77 finalize(builder, ChreMessage::UnregisterMessageHub, msg.Union());
78 }
79
encodeRegisterEndpoint(FlatBufferBuilder & builder,const AidlEndpointInfo & info)80 void HostProtocolHostV4::encodeRegisterEndpoint(FlatBufferBuilder &builder,
81 const AidlEndpointInfo &info) {
82 auto msg = ::chre::fbs::CreateRegisterEndpoint(
83 builder, aidlToFbsEndpointInfo(builder, info));
84 finalize(builder, ChreMessage::RegisterEndpoint, msg.Union());
85 }
86
encodeUnregisterEndpoint(FlatBufferBuilder & builder,const AidlEndpointId & id)87 void HostProtocolHostV4::encodeUnregisterEndpoint(FlatBufferBuilder &builder,
88 const AidlEndpointId &id) {
89 auto msg = ::chre::fbs::CreateUnregisterEndpoint(
90 builder, aidlToFbsEndpointId(builder, id));
91 finalize(builder, ChreMessage::UnregisterEndpoint, msg.Union());
92 }
93
encodeOpenEndpointSessionRequest(FlatBufferBuilder & builder,int64_t hostHubId,uint16_t sessionId,const AidlEndpointId & initiator,const AidlEndpointId & destination,const std::optional<std::string> & serviceDescriptor)94 void HostProtocolHostV4::encodeOpenEndpointSessionRequest(
95 FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId,
96 const AidlEndpointId &initiator, const AidlEndpointId &destination,
97 const std::optional<std::string> &serviceDescriptor) {
98 Offset<Vector<int8_t>> descriptorVector =
99 serviceDescriptor
100 ? addStringAsByteVector(builder, serviceDescriptor->c_str())
101 : 0;
102 auto msg = ::chre::fbs::CreateOpenEndpointSessionRequest(
103 builder, hostHubId, sessionId, aidlToFbsEndpointId(builder, initiator),
104 aidlToFbsEndpointId(builder, destination), descriptorVector);
105 finalize(builder, ChreMessage::OpenEndpointSessionRequest, msg.Union());
106 }
107
encodeEndpointSessionOpened(FlatBufferBuilder & builder,int64_t hostHubId,uint16_t sessionId)108 void HostProtocolHostV4::encodeEndpointSessionOpened(FlatBufferBuilder &builder,
109 int64_t hostHubId,
110 uint16_t sessionId) {
111 auto msg =
112 ::chre::fbs::CreateEndpointSessionOpened(builder, hostHubId, sessionId);
113 finalize(builder, ChreMessage::EndpointSessionOpened, msg.Union());
114 }
115
encodeEndpointSessionClosed(FlatBufferBuilder & builder,int64_t hostHubId,uint16_t sessionId,AidlReason reason)116 void HostProtocolHostV4::encodeEndpointSessionClosed(FlatBufferBuilder &builder,
117 int64_t hostHubId,
118 uint16_t sessionId,
119 AidlReason reason) {
120 auto msg = ::chre::fbs::CreateEndpointSessionClosed(
121 builder, hostHubId, sessionId, static_cast<Reason>(reason));
122 finalize(builder, ChreMessage::EndpointSessionClosed, msg.Union());
123 }
124
encodeEndpointSessionMessage(FlatBufferBuilder & builder,int64_t hostHubId,uint16_t sessionId,const AidlMessage & message)125 void HostProtocolHostV4::encodeEndpointSessionMessage(
126 FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId,
127 const AidlMessage &message) {
128 auto msg = ::chre::fbs::CreateEndpointSessionMessage(
129 builder, hostHubId, sessionId, message.type,
130 androidToChrePermissions(message.permissions),
131 builder.CreateVector(message.content), message.flags,
132 message.sequenceNumber);
133 finalize(builder, ChreMessage::EndpointSessionMessage, msg.Union());
134 }
135
encodeEndpointSessionMessageDeliveryStatus(FlatBufferBuilder & builder,int64_t hostHubId,uint16_t sessionId,const AidlMessageDeliveryStatus & status)136 void HostProtocolHostV4::encodeEndpointSessionMessageDeliveryStatus(
137 FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId,
138 const AidlMessageDeliveryStatus &status) {
139 auto fbsStatus = ::chre::fbs::CreateMessageDeliveryStatus(
140 builder, status.messageSequenceNumber,
141 static_cast<int8_t>(status.errorCode));
142 auto msg = ::chre::fbs::CreateEndpointSessionMessageDeliveryStatus(
143 builder, hostHubId, sessionId, fbsStatus);
144 finalize(builder, ChreMessage::EndpointSessionMessageDeliveryStatus,
145 msg.Union());
146 }
147
148 namespace {
149
stringFromBytes(const std::vector<int8_t> & bytes)150 std::string stringFromBytes(const std::vector<int8_t> &bytes) {
151 auto *cStr = ::android::chre::getStringFromByteVector(bytes);
152 return cStr ? std::string(cStr) : std::string();
153 }
154
155 } // namespace
156
decodeGetMessageHubsAndEndpointsResponse(const::chre::fbs::GetMessageHubsAndEndpointsResponseT & msg,std::vector<AidlHubInfo> & hubs,std::vector<AidlEndpointInfo> & endpoints)157 void HostProtocolHostV4::decodeGetMessageHubsAndEndpointsResponse(
158 const ::chre::fbs::GetMessageHubsAndEndpointsResponseT &msg,
159 std::vector<AidlHubInfo> &hubs, std::vector<AidlEndpointInfo> &endpoints) {
160 for (const auto &hub : msg.hubs) hubs.push_back(fbsMessageHubToAidl(*hub));
161 for (const auto &endpoint : msg.endpoints)
162 endpoints.push_back(fbsEndpointInfoToAidl(*endpoint));
163 }
164
decodeRegisterMessageHub(const::chre::fbs::RegisterMessageHubT & msg,AidlHubInfo & info)165 void HostProtocolHostV4::decodeRegisterMessageHub(
166 const ::chre::fbs::RegisterMessageHubT &msg, AidlHubInfo &info) {
167 info = fbsMessageHubToAidl(*msg.hub);
168 }
169
decodeUnregisterMessageHub(const::chre::fbs::UnregisterMessageHubT & msg,int64_t & id)170 void HostProtocolHostV4::decodeUnregisterMessageHub(
171 const ::chre::fbs::UnregisterMessageHubT &msg, int64_t &id) {
172 id = msg.id;
173 }
174
decodeRegisterEndpoint(const::chre::fbs::RegisterEndpointT & msg,AidlEndpointInfo & info)175 void HostProtocolHostV4::decodeRegisterEndpoint(
176 const ::chre::fbs::RegisterEndpointT &msg, AidlEndpointInfo &info) {
177 info = fbsEndpointInfoToAidl(*msg.endpoint);
178 }
179
decodeAddServiceToEndpoint(const::chre::fbs::AddServiceToEndpointT & msg,AidlEndpointId & id,AidlService & service)180 void HostProtocolHostV4::decodeAddServiceToEndpoint(
181 const ::chre::fbs::AddServiceToEndpointT &msg, AidlEndpointId &id,
182 AidlService &service) {
183 id = fbsEndpointIdToAidl(*msg.endpoint);
184 service.format = static_cast<AidlRpcFormat>(msg.service->format);
185 service.serviceDescriptor = stringFromBytes(msg.service->descriptor);
186 service.majorVersion = msg.service->major_version;
187 service.minorVersion = msg.service->minor_version;
188 }
189
decodeEndpointReady(const::chre::fbs::EndpointReadyT & msg,AidlEndpointId & id)190 void HostProtocolHostV4::decodeEndpointReady(
191 const ::chre::fbs::EndpointReadyT &msg, AidlEndpointId &id) {
192 id = fbsEndpointIdToAidl(*msg.endpoint);
193 }
194
decodeUnregisterEndpoint(const::chre::fbs::UnregisterEndpointT & msg,AidlEndpointId & id)195 void HostProtocolHostV4::decodeUnregisterEndpoint(
196 const ::chre::fbs::UnregisterEndpointT &msg, AidlEndpointId &id) {
197 id = fbsEndpointIdToAidl(*msg.endpoint);
198 }
199
decodeOpenEndpointSessionRequest(const::chre::fbs::OpenEndpointSessionRequestT & msg,int64_t & hubId,uint16_t & sessionId,AidlEndpointId & hostEndpoint,AidlEndpointId & embeddedEndpoint,std::optional<std::string> & serviceDescriptor)200 void HostProtocolHostV4::decodeOpenEndpointSessionRequest(
201 const ::chre::fbs::OpenEndpointSessionRequestT &msg, int64_t &hubId,
202 uint16_t &sessionId, AidlEndpointId &hostEndpoint,
203 AidlEndpointId &embeddedEndpoint,
204 std::optional<std::string> &serviceDescriptor) {
205 hubId = msg.host_hub_id;
206 sessionId = msg.session_id;
207 hostEndpoint = fbsEndpointIdToAidl(*msg.toEndpoint);
208 embeddedEndpoint = fbsEndpointIdToAidl(*msg.fromEndpoint);
209 auto *serviceCStr =
210 ::android::chre::getStringFromByteVector(msg.serviceDescriptor);
211 if (serviceCStr) serviceDescriptor = std::string(serviceCStr);
212 }
213
decodeEndpointSessionOpened(const::chre::fbs::EndpointSessionOpenedT & msg,int64_t & hubId,uint16_t & sessionId)214 void HostProtocolHostV4::decodeEndpointSessionOpened(
215 const ::chre::fbs::EndpointSessionOpenedT &msg, int64_t &hubId,
216 uint16_t &sessionId) {
217 hubId = msg.host_hub_id;
218 sessionId = msg.session_id;
219 }
220
decodeEndpointSessionClosed(const::chre::fbs::EndpointSessionClosedT & msg,int64_t & hubId,uint16_t & sessionId,AidlReason & reason)221 void HostProtocolHostV4::decodeEndpointSessionClosed(
222 const ::chre::fbs::EndpointSessionClosedT &msg, int64_t &hubId,
223 uint16_t &sessionId, AidlReason &reason) {
224 hubId = msg.host_hub_id;
225 sessionId = msg.session_id;
226 reason = static_cast<AidlReason>(msg.reason);
227 }
228
decodeEndpointSessionMessage(const::chre::fbs::EndpointSessionMessageT & msg,int64_t & hubId,uint16_t & sessionId,AidlMessage & message)229 void HostProtocolHostV4::decodeEndpointSessionMessage(
230 const ::chre::fbs::EndpointSessionMessageT &msg, int64_t &hubId,
231 uint16_t &sessionId, AidlMessage &message) {
232 hubId = msg.host_hub_id;
233 sessionId = msg.session_id;
234 message = {.flags = static_cast<int32_t>(msg.flags),
235 .sequenceNumber = static_cast<int32_t>(msg.sequence_number),
236 .permissions = chreToAndroidPermissions(msg.permissions),
237 .type = static_cast<int32_t>(msg.type),
238 .content = msg.data};
239 }
240
decodeEndpointSessionMessageDeliveryStatus(const::chre::fbs::EndpointSessionMessageDeliveryStatusT & msg,int64_t & hubId,uint16_t & sessionId,AidlMessageDeliveryStatus & status)241 void HostProtocolHostV4::decodeEndpointSessionMessageDeliveryStatus(
242 const ::chre::fbs::EndpointSessionMessageDeliveryStatusT &msg,
243 int64_t &hubId, uint16_t &sessionId, AidlMessageDeliveryStatus &status) {
244 hubId = msg.host_hub_id;
245 sessionId = msg.session_id;
246 status = {.messageSequenceNumber =
247 static_cast<int32_t>(msg.status->message_sequence_number),
248 .errorCode = static_cast<AidlErrorCode>(msg.status->error_code)};
249 }
250
aidlToFbsMessageHub(FlatBufferBuilder & builder,const AidlHubInfo & info)251 Offset<MessageHub> HostProtocolHostV4::aidlToFbsMessageHub(
252 FlatBufferBuilder &builder, const AidlHubInfo &info) {
253 MessageHubDetails detailsEnum;
254 Offset<void> detailsUnion;
255 switch (info.hubDetails.getTag()) {
256 case AidlHubInfo::HubDetails::Tag::contextHubInfo: {
257 detailsEnum = MessageHubDetails::HubInfoResponse;
258 const auto &contextHub =
259 info.hubDetails.get<AidlHubInfo::HubDetails::Tag::contextHubInfo>();
260 uint32_t chrePlatformVersion =
261 (static_cast<uint32_t>(contextHub.chreApiMajorVersion) << 24) |
262 (static_cast<uint32_t>(contextHub.chreApiMinorVersion) << 16) |
263 static_cast<uint32_t>(contextHub.chrePatchVersion);
264 detailsUnion =
265 ::chre::fbs::CreateHubInfoResponse(
266 builder, addStringAsByteVector(builder, contextHub.name.c_str()),
267 addStringAsByteVector(builder, contextHub.vendor.c_str()),
268 addStringAsByteVector(builder, contextHub.toolchain.c_str()),
269 /*platform_version=*/0, /*toolchain_version=*/0,
270 contextHub.peakMips,
271 /*stopped_power=*/0.0f, /*sleep_power=*/0.0f, /*peak_power=*/0.0f,
272 contextHub.maxSupportedMessageLengthBytes,
273 contextHub.chrePlatformId, chrePlatformVersion,
274 contextHub.supportsReliableMessages)
275 .Union();
276 } break;
277 case AidlHubInfo::HubDetails::Tag::vendorHubInfo: {
278 detailsEnum = MessageHubDetails::VendorHubInfo;
279 const auto &vendorHub =
280 info.hubDetails.get<AidlHubInfo::HubDetails::Tag::vendorHubInfo>();
281 detailsUnion =
282 ::chre::fbs::CreateVendorHubInfo(
283 builder, addStringAsByteVector(builder, vendorHub.name.c_str()),
284 vendorHub.version, /*extended_info=*/0)
285 .Union();
286 } break;
287 }
288 return ::chre::fbs::CreateMessageHub(builder, info.hubId, detailsEnum,
289 detailsUnion);
290 }
291
fbsMessageHubToAidl(const::chre::fbs::MessageHubT & hub)292 AidlHubInfo HostProtocolHostV4::fbsMessageHubToAidl(
293 const ::chre::fbs::MessageHubT &hub) {
294 AidlHubInfo info{.hubId = hub.id};
295 if (hub.details.type == MessageHubDetails::HubInfoResponse) {
296 const auto &fbsContextHub = *hub.details.AsHubInfoResponse();
297 AidlContextHubInfo contextHub = {
298 .name = stringFromBytes(fbsContextHub.name),
299 .vendor = stringFromBytes(fbsContextHub.vendor),
300 .toolchain = stringFromBytes(fbsContextHub.toolchain),
301 .peakMips = fbsContextHub.peak_mips,
302 .maxSupportedMessageLengthBytes =
303 static_cast<int32_t>(fbsContextHub.max_msg_len),
304 .chrePlatformId = static_cast<int64_t>(fbsContextHub.platform_id),
305 .chreApiMajorVersion = static_cast<int8_t>(
306 (fbsContextHub.chre_platform_version >> 24) & 0xff),
307 .chreApiMinorVersion = static_cast<int8_t>(
308 (fbsContextHub.chre_platform_version >> 16) & 0xff),
309 .chrePatchVersion =
310 static_cast<char16_t>(fbsContextHub.chre_platform_version & 0xffff),
311 .supportsReliableMessages = fbsContextHub.supports_reliable_messages};
312 info.hubDetails = AidlHubInfo::HubDetails(std::move(contextHub));
313 } else {
314 const auto &fbsVendorHub = *hub.details.AsVendorHubInfo();
315 AidlVendorHubInfo vendorHub = {
316 .name = stringFromBytes(fbsVendorHub.name),
317 .version = static_cast<int32_t>(fbsVendorHub.version)};
318 info.hubDetails = AidlHubInfo::HubDetails(std::move(vendorHub));
319 }
320 return info;
321 }
322
aidlToFbsEndpointInfo(FlatBufferBuilder & builder,const AidlEndpointInfo & info)323 Offset<EndpointInfo> HostProtocolHostV4::aidlToFbsEndpointInfo(
324 FlatBufferBuilder &builder, const AidlEndpointInfo &info) {
325 std::vector<Offset<::chre::fbs::Service>> services;
326 for (const auto &service : info.services) {
327 services.push_back(::chre::fbs::CreateService(
328 builder, static_cast<::chre::fbs::RpcFormat>(service.format),
329 addStringAsByteVector(builder, service.serviceDescriptor.c_str()),
330 service.majorVersion, service.minorVersion));
331 }
332 auto servicesVector = builder.CreateVector(services);
333 return ::chre::fbs::CreateEndpointInfo(
334 builder, aidlToFbsEndpointId(builder, info.id),
335 static_cast<::chre::fbs::EndpointType>(info.type),
336 addStringAsByteVector(builder, info.name.c_str()), info.version,
337 androidToChrePermissions(info.requiredPermissions), servicesVector);
338 }
339
fbsEndpointInfoToAidl(const::chre::fbs::EndpointInfoT & endpoint)340 AidlEndpointInfo HostProtocolHostV4::fbsEndpointInfoToAidl(
341 const ::chre::fbs::EndpointInfoT &endpoint) {
342 AidlEndpointInfo info = {
343 .id = fbsEndpointIdToAidl(*endpoint.id),
344 .type = static_cast<AidlEndpointInfo::EndpointType>(endpoint.type),
345 .name = stringFromBytes(endpoint.name),
346 .version = static_cast<int32_t>(endpoint.version),
347 .requiredPermissions =
348 chreToAndroidPermissions(endpoint.required_permissions)};
349 for (const auto &service : endpoint.services) {
350 info.services.push_back(
351 {.format = static_cast<AidlRpcFormat>(service->format),
352 .serviceDescriptor = stringFromBytes(service->descriptor),
353 .majorVersion = static_cast<int32_t>(service->major_version),
354 .minorVersion = static_cast<int32_t>(service->minor_version)});
355 }
356 return info;
357 }
358
aidlToFbsEndpointId(FlatBufferBuilder & builder,const AidlEndpointId & id)359 Offset<EndpointId> HostProtocolHostV4::aidlToFbsEndpointId(
360 FlatBufferBuilder &builder, const AidlEndpointId &id) {
361 return ::chre::fbs::CreateEndpointId(builder, id.hubId, id.id);
362 }
363
fbsEndpointIdToAidl(const::chre::fbs::EndpointIdT & endpoint)364 AidlEndpointId HostProtocolHostV4::fbsEndpointIdToAidl(
365 const ::chre::fbs::EndpointIdT &endpoint) {
366 return AidlEndpointId{.id = endpoint.id, .hubId = endpoint.hubId};
367 }
368
369 } // namespace android::hardware::contexthub::common::implementation
370