/* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License") {} * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "host_protocol_host_v4.h" #include #include "permissions_util.h" namespace android::hardware::contexthub::common::implementation { using ::chre::fbs::ChreMessage; using ::chre::fbs::EndpointId; using ::chre::fbs::EndpointInfo; using ::chre::fbs::MessageDeliveryStatus; using ::chre::fbs::MessageHub; using ::chre::fbs::MessageHubDetails; using ::chre::fbs::Reason; using ::flatbuffers::FlatBufferBuilder; using ::flatbuffers::Offset; using ::flatbuffers::Vector; using AidlContextHubInfo = ::aidl::android::hardware::contexthub::ContextHubInfo; using AidlVendorHubInfo = ::aidl::android::hardware::contexthub::VendorHubInfo; using AidlErrorCode = ::aidl::android::hardware::contexthub::ErrorCode; using AidlRpcFormat = ::aidl::android::hardware::contexthub::Service::RpcFormat; void HostProtocolHostV4::encodeGetMessageHubsAndEndpointsRequest( FlatBufferBuilder &builder) { auto msg = ::chre::fbs::CreateGetMessageHubsAndEndpointsRequest(builder); finalize(builder, ChreMessage::GetMessageHubsAndEndpointsRequest, msg.Union()); } void HostProtocolHostV4::encodeGetMessageHubsAndEndpointsResponse( FlatBufferBuilder &builder, const std::vector &hubs, const std::vector &endpoints) { std::vector> fbsHubs; fbsHubs.reserve(hubs.size()); for (const auto &hub : hubs) fbsHubs.push_back(aidlToFbsMessageHub(builder, hub)); std::vector> fbsEndpoints; for (const auto &endpoint : endpoints) fbsEndpoints.push_back(aidlToFbsEndpointInfo(builder, endpoint)); auto hubsVector = builder.CreateVector(fbsHubs); auto endpointsVector = builder.CreateVector(fbsEndpoints); auto msg = ::chre::fbs::CreateGetMessageHubsAndEndpointsResponse( builder, hubsVector, endpointsVector); finalize(builder, ChreMessage::GetMessageHubsAndEndpointsResponse, msg.Union()); } void HostProtocolHostV4::encodeRegisterMessageHub(FlatBufferBuilder &builder, const AidlHubInfo &info) { auto msg = ::chre::fbs::CreateRegisterMessageHub( builder, aidlToFbsMessageHub(builder, info)); finalize(builder, ChreMessage::RegisterMessageHub, msg.Union()); } void HostProtocolHostV4::encodeUnregisterMessageHub(FlatBufferBuilder &builder, int64_t id) { auto msg = ::chre::fbs::CreateUnregisterMessageHub(builder, id); finalize(builder, ChreMessage::UnregisterMessageHub, msg.Union()); } void HostProtocolHostV4::encodeRegisterEndpoint(FlatBufferBuilder &builder, const AidlEndpointInfo &info) { auto msg = ::chre::fbs::CreateRegisterEndpoint( builder, aidlToFbsEndpointInfo(builder, info)); finalize(builder, ChreMessage::RegisterEndpoint, msg.Union()); } void HostProtocolHostV4::encodeUnregisterEndpoint(FlatBufferBuilder &builder, const AidlEndpointId &id) { auto msg = ::chre::fbs::CreateUnregisterEndpoint( builder, aidlToFbsEndpointId(builder, id)); finalize(builder, ChreMessage::UnregisterEndpoint, msg.Union()); } void HostProtocolHostV4::encodeOpenEndpointSessionRequest( FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId, const AidlEndpointId &initiator, const AidlEndpointId &destination, const std::optional &serviceDescriptor) { Offset> descriptorVector = serviceDescriptor ? addStringAsByteVector(builder, serviceDescriptor->c_str()) : 0; auto msg = ::chre::fbs::CreateOpenEndpointSessionRequest( builder, hostHubId, sessionId, aidlToFbsEndpointId(builder, initiator), aidlToFbsEndpointId(builder, destination), descriptorVector); finalize(builder, ChreMessage::OpenEndpointSessionRequest, msg.Union()); } void HostProtocolHostV4::encodeEndpointSessionOpened(FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId) { auto msg = ::chre::fbs::CreateEndpointSessionOpened(builder, hostHubId, sessionId); finalize(builder, ChreMessage::EndpointSessionOpened, msg.Union()); } void HostProtocolHostV4::encodeEndpointSessionClosed(FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId, AidlReason reason) { auto msg = ::chre::fbs::CreateEndpointSessionClosed( builder, hostHubId, sessionId, static_cast(reason)); finalize(builder, ChreMessage::EndpointSessionClosed, msg.Union()); } void HostProtocolHostV4::encodeEndpointSessionMessage( FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId, const AidlMessage &message) { auto msg = ::chre::fbs::CreateEndpointSessionMessage( builder, hostHubId, sessionId, message.type, androidToChrePermissions(message.permissions), builder.CreateVector(message.content), message.flags, message.sequenceNumber); finalize(builder, ChreMessage::EndpointSessionMessage, msg.Union()); } void HostProtocolHostV4::encodeEndpointSessionMessageDeliveryStatus( FlatBufferBuilder &builder, int64_t hostHubId, uint16_t sessionId, const AidlMessageDeliveryStatus &status) { auto fbsStatus = ::chre::fbs::CreateMessageDeliveryStatus( builder, status.messageSequenceNumber, static_cast(status.errorCode)); auto msg = ::chre::fbs::CreateEndpointSessionMessageDeliveryStatus( builder, hostHubId, sessionId, fbsStatus); finalize(builder, ChreMessage::EndpointSessionMessageDeliveryStatus, msg.Union()); } namespace { std::string stringFromBytes(const std::vector &bytes) { auto *cStr = ::android::chre::getStringFromByteVector(bytes); return cStr ? std::string(cStr) : std::string(); } } // namespace void HostProtocolHostV4::decodeGetMessageHubsAndEndpointsResponse( const ::chre::fbs::GetMessageHubsAndEndpointsResponseT &msg, std::vector &hubs, std::vector &endpoints) { for (const auto &hub : msg.hubs) hubs.push_back(fbsMessageHubToAidl(*hub)); for (const auto &endpoint : msg.endpoints) endpoints.push_back(fbsEndpointInfoToAidl(*endpoint)); } void HostProtocolHostV4::decodeRegisterMessageHub( const ::chre::fbs::RegisterMessageHubT &msg, AidlHubInfo &info) { info = fbsMessageHubToAidl(*msg.hub); } void HostProtocolHostV4::decodeUnregisterMessageHub( const ::chre::fbs::UnregisterMessageHubT &msg, int64_t &id) { id = msg.id; } void HostProtocolHostV4::decodeRegisterEndpoint( const ::chre::fbs::RegisterEndpointT &msg, AidlEndpointInfo &info) { info = fbsEndpointInfoToAidl(*msg.endpoint); } void HostProtocolHostV4::decodeAddServiceToEndpoint( const ::chre::fbs::AddServiceToEndpointT &msg, AidlEndpointId &id, AidlService &service) { id = fbsEndpointIdToAidl(*msg.endpoint); service.format = static_cast(msg.service->format); service.serviceDescriptor = stringFromBytes(msg.service->descriptor); service.majorVersion = msg.service->major_version; service.minorVersion = msg.service->minor_version; } void HostProtocolHostV4::decodeEndpointReady( const ::chre::fbs::EndpointReadyT &msg, AidlEndpointId &id) { id = fbsEndpointIdToAidl(*msg.endpoint); } void HostProtocolHostV4::decodeUnregisterEndpoint( const ::chre::fbs::UnregisterEndpointT &msg, AidlEndpointId &id) { id = fbsEndpointIdToAidl(*msg.endpoint); } void HostProtocolHostV4::decodeOpenEndpointSessionRequest( const ::chre::fbs::OpenEndpointSessionRequestT &msg, int64_t &hubId, uint16_t &sessionId, AidlEndpointId &hostEndpoint, AidlEndpointId &embeddedEndpoint, std::optional &serviceDescriptor) { hubId = msg.host_hub_id; sessionId = msg.session_id; hostEndpoint = fbsEndpointIdToAidl(*msg.toEndpoint); embeddedEndpoint = fbsEndpointIdToAidl(*msg.fromEndpoint); auto *serviceCStr = ::android::chre::getStringFromByteVector(msg.serviceDescriptor); if (serviceCStr) serviceDescriptor = std::string(serviceCStr); } void HostProtocolHostV4::decodeEndpointSessionOpened( const ::chre::fbs::EndpointSessionOpenedT &msg, int64_t &hubId, uint16_t &sessionId) { hubId = msg.host_hub_id; sessionId = msg.session_id; } void HostProtocolHostV4::decodeEndpointSessionClosed( const ::chre::fbs::EndpointSessionClosedT &msg, int64_t &hubId, uint16_t &sessionId, AidlReason &reason) { hubId = msg.host_hub_id; sessionId = msg.session_id; reason = static_cast(msg.reason); } void HostProtocolHostV4::decodeEndpointSessionMessage( const ::chre::fbs::EndpointSessionMessageT &msg, int64_t &hubId, uint16_t &sessionId, AidlMessage &message) { hubId = msg.host_hub_id; sessionId = msg.session_id; message = {.flags = static_cast(msg.flags), .sequenceNumber = static_cast(msg.sequence_number), .permissions = chreToAndroidPermissions(msg.permissions), .type = static_cast(msg.type), .content = msg.data}; } void HostProtocolHostV4::decodeEndpointSessionMessageDeliveryStatus( const ::chre::fbs::EndpointSessionMessageDeliveryStatusT &msg, int64_t &hubId, uint16_t &sessionId, AidlMessageDeliveryStatus &status) { hubId = msg.host_hub_id; sessionId = msg.session_id; status = {.messageSequenceNumber = static_cast(msg.status->message_sequence_number), .errorCode = static_cast(msg.status->error_code)}; } Offset HostProtocolHostV4::aidlToFbsMessageHub( FlatBufferBuilder &builder, const AidlHubInfo &info) { MessageHubDetails detailsEnum; Offset detailsUnion; switch (info.hubDetails.getTag()) { case AidlHubInfo::HubDetails::Tag::contextHubInfo: { detailsEnum = MessageHubDetails::HubInfoResponse; const auto &contextHub = info.hubDetails.get(); uint32_t chrePlatformVersion = (static_cast(contextHub.chreApiMajorVersion) << 24) | (static_cast(contextHub.chreApiMinorVersion) << 16) | static_cast(contextHub.chrePatchVersion); detailsUnion = ::chre::fbs::CreateHubInfoResponse( builder, addStringAsByteVector(builder, contextHub.name.c_str()), addStringAsByteVector(builder, contextHub.vendor.c_str()), addStringAsByteVector(builder, contextHub.toolchain.c_str()), /*platform_version=*/0, /*toolchain_version=*/0, contextHub.peakMips, /*stopped_power=*/0.0f, /*sleep_power=*/0.0f, /*peak_power=*/0.0f, contextHub.maxSupportedMessageLengthBytes, contextHub.chrePlatformId, chrePlatformVersion, contextHub.supportsReliableMessages) .Union(); } break; case AidlHubInfo::HubDetails::Tag::vendorHubInfo: { detailsEnum = MessageHubDetails::VendorHubInfo; const auto &vendorHub = info.hubDetails.get(); detailsUnion = ::chre::fbs::CreateVendorHubInfo( builder, addStringAsByteVector(builder, vendorHub.name.c_str()), vendorHub.version, /*extended_info=*/0) .Union(); } break; } return ::chre::fbs::CreateMessageHub(builder, info.hubId, detailsEnum, detailsUnion); } AidlHubInfo HostProtocolHostV4::fbsMessageHubToAidl( const ::chre::fbs::MessageHubT &hub) { AidlHubInfo info{.hubId = hub.id}; if (hub.details.type == MessageHubDetails::HubInfoResponse) { const auto &fbsContextHub = *hub.details.AsHubInfoResponse(); AidlContextHubInfo contextHub = { .name = stringFromBytes(fbsContextHub.name), .vendor = stringFromBytes(fbsContextHub.vendor), .toolchain = stringFromBytes(fbsContextHub.toolchain), .peakMips = fbsContextHub.peak_mips, .maxSupportedMessageLengthBytes = static_cast(fbsContextHub.max_msg_len), .chrePlatformId = static_cast(fbsContextHub.platform_id), .chreApiMajorVersion = static_cast( (fbsContextHub.chre_platform_version >> 24) & 0xff), .chreApiMinorVersion = static_cast( (fbsContextHub.chre_platform_version >> 16) & 0xff), .chrePatchVersion = static_cast(fbsContextHub.chre_platform_version & 0xffff), .supportsReliableMessages = fbsContextHub.supports_reliable_messages}; info.hubDetails = AidlHubInfo::HubDetails(std::move(contextHub)); } else { const auto &fbsVendorHub = *hub.details.AsVendorHubInfo(); AidlVendorHubInfo vendorHub = { .name = stringFromBytes(fbsVendorHub.name), .version = static_cast(fbsVendorHub.version)}; info.hubDetails = AidlHubInfo::HubDetails(std::move(vendorHub)); } return info; } Offset HostProtocolHostV4::aidlToFbsEndpointInfo( FlatBufferBuilder &builder, const AidlEndpointInfo &info) { std::vector> services; for (const auto &service : info.services) { services.push_back(::chre::fbs::CreateService( builder, static_cast<::chre::fbs::RpcFormat>(service.format), addStringAsByteVector(builder, service.serviceDescriptor.c_str()), service.majorVersion, service.minorVersion)); } auto servicesVector = builder.CreateVector(services); return ::chre::fbs::CreateEndpointInfo( builder, aidlToFbsEndpointId(builder, info.id), static_cast<::chre::fbs::EndpointType>(info.type), addStringAsByteVector(builder, info.name.c_str()), info.version, androidToChrePermissions(info.requiredPermissions), servicesVector); } AidlEndpointInfo HostProtocolHostV4::fbsEndpointInfoToAidl( const ::chre::fbs::EndpointInfoT &endpoint) { AidlEndpointInfo info = { .id = fbsEndpointIdToAidl(*endpoint.id), .type = static_cast(endpoint.type), .name = stringFromBytes(endpoint.name), .version = static_cast(endpoint.version), .requiredPermissions = chreToAndroidPermissions(endpoint.required_permissions)}; for (const auto &service : endpoint.services) { info.services.push_back( {.format = static_cast(service->format), .serviceDescriptor = stringFromBytes(service->descriptor), .majorVersion = static_cast(service->major_version), .minorVersion = static_cast(service->minor_version)}); } return info; } Offset HostProtocolHostV4::aidlToFbsEndpointId( FlatBufferBuilder &builder, const AidlEndpointId &id) { return ::chre::fbs::CreateEndpointId(builder, id.hubId, id.id); } AidlEndpointId HostProtocolHostV4::fbsEndpointIdToAidl( const ::chre::fbs::EndpointIdT &endpoint) { return AidlEndpointId{.id = endpoint.id, .hubId = endpoint.hubId}; } } // namespace android::hardware::contexthub::common::implementation