/* * Copyright (C) 2017 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 "chre/platform/shared/host_protocol_chre.h" #include #include #include "chre/platform/log.h" #include "chre/platform/shared/host_messages_generated.h" using flatbuffers::FlatBufferBuilder; using flatbuffers::Offset; using flatbuffers::Vector; namespace chre { // This is similar to getStringFromByteVector in host_protocol_host.h. Ensure // that method's implementation is kept in sync with this. const char *getStringFromByteVector(const flatbuffers::Vector *vec) { constexpr int8_t kNullChar = static_cast('\0'); const char *str = nullptr; // Check that the vector is present, non-empty, and null-terminated if (vec != nullptr && vec->size() > 0 && (*vec)[vec->size() - 1] == kNullChar) { str = reinterpret_cast(vec->Data()); } return str; } bool HostProtocolChre::decodeMessageFromHost(const void *message, size_t messageLen) { bool success = verifyMessage(message, messageLen); if (!success) { LOGE("Dropping invalid/corrupted message from host (length %zu)", messageLen); } else { const fbs::MessageContainer *container = fbs::GetMessageContainer(message); uint16_t hostClientId = container->host_addr()->client_id(); switch (container->message_type()) { case fbs::ChreMessage::NanoappMessage: { const auto *nanoappMsg = static_cast( container->message()); // Required field; verifier ensures that this is not null (though it // may be empty) const flatbuffers::Vector *msgData = nanoappMsg->message(); HostMessageHandlers::handleNanoappMessage( nanoappMsg->app_id(), nanoappMsg->message_type(), nanoappMsg->host_endpoint(), msgData->data(), msgData->size()); break; } case fbs::ChreMessage::HubInfoRequest: HostMessageHandlers::handleHubInfoRequest(hostClientId); break; case fbs::ChreMessage::NanoappListRequest: HostMessageHandlers::handleNanoappListRequest(hostClientId); break; case fbs::ChreMessage::LoadNanoappRequest: { const auto *request = static_cast( container->message()); const flatbuffers::Vector *appBinary = request->app_binary(); const char *appBinaryFilename = getStringFromByteVector( request->app_binary_file_name()); HostMessageHandlers::handleLoadNanoappRequest( hostClientId, request->transaction_id(), request->app_id(), request->app_version(), request->target_api_version(), appBinary->data(), appBinary->size(), appBinaryFilename, request->fragment_id(), request->total_app_size()); break; } case fbs::ChreMessage::UnloadNanoappRequest: { const auto *request = static_cast( container->message()); HostMessageHandlers::handleUnloadNanoappRequest( hostClientId, request->transaction_id(), request->app_id(), request->allow_system_nanoapp_unload()); break; } case fbs::ChreMessage::TimeSyncMessage: { const auto *request = static_cast( container->message()); HostMessageHandlers::handleTimeSyncMessage(request->offset()); break; } case fbs::ChreMessage::DebugDumpRequest: HostMessageHandlers::handleDebugDumpRequest(hostClientId); break; default: LOGW("Got invalid/unexpected message type %" PRIu8, static_cast(container->message_type())); success = false; } } return success; } void HostProtocolChre::encodeHubInfoResponse( FlatBufferBuilder& builder, const char *name, const char *vendor, const char *toolchain, uint32_t legacyPlatformVersion, uint32_t legacyToolchainVersion, float peakMips, float stoppedPower, float sleepPower, float peakPower, uint32_t maxMessageLen, uint64_t platformId, uint32_t version, uint16_t hostClientId) { auto nameOffset = addStringAsByteVector(builder, name); auto vendorOffset = addStringAsByteVector(builder, vendor); auto toolchainOffset = addStringAsByteVector(builder, toolchain); auto response = fbs::CreateHubInfoResponse( builder, nameOffset, vendorOffset, toolchainOffset, legacyPlatformVersion, legacyToolchainVersion, peakMips, stoppedPower, sleepPower, peakPower, maxMessageLen, platformId, version); finalize(builder, fbs::ChreMessage::HubInfoResponse, response.Union(), hostClientId); } void HostProtocolChre::addNanoappListEntry( FlatBufferBuilder& builder, DynamicVector>& offsetVector, uint64_t appId, uint32_t appVersion, bool enabled, bool isSystemNanoapp) { auto offset = fbs::CreateNanoappListEntry( builder, appId, appVersion, enabled, isSystemNanoapp); if (!offsetVector.push_back(offset)) { LOGE("Couldn't push nanoapp list entry offset!"); } } void HostProtocolChre::finishNanoappListResponse( FlatBufferBuilder& builder, DynamicVector>& offsetVector, uint16_t hostClientId) { auto vectorOffset = builder.CreateVector>( offsetVector); auto response = fbs::CreateNanoappListResponse(builder, vectorOffset); finalize(builder, fbs::ChreMessage::NanoappListResponse, response.Union(), hostClientId); } void HostProtocolChre::encodeLoadNanoappResponse( flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId, uint32_t transactionId, bool success, uint32_t fragmentId) { auto response = fbs::CreateLoadNanoappResponse(builder, transactionId, success, fragmentId); finalize(builder, fbs::ChreMessage::LoadNanoappResponse, response.Union(), hostClientId); } void HostProtocolChre::encodeUnloadNanoappResponse( flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId, uint32_t transactionId, bool success) { auto response = fbs::CreateUnloadNanoappResponse(builder, transactionId, success); finalize(builder, fbs::ChreMessage::UnloadNanoappResponse, response.Union(), hostClientId); } void HostProtocolChre::encodeLogMessages( flatbuffers::FlatBufferBuilder& builder, const char *logBuffer, size_t bufferSize) { auto logBufferOffset = builder.CreateVector( reinterpret_cast(logBuffer), bufferSize); auto message = fbs::CreateLogMessage(builder, logBufferOffset); finalize(builder, fbs::ChreMessage::LogMessage, message.Union()); } void HostProtocolChre::encodeDebugDumpData( flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId, const char *debugStr, size_t debugStrSize) { auto debugStrOffset = builder.CreateVector( reinterpret_cast(debugStr), debugStrSize); auto message = fbs::CreateDebugDumpData(builder, debugStrOffset); finalize(builder, fbs::ChreMessage::DebugDumpData, message.Union(), hostClientId); } void HostProtocolChre::encodeDebugDumpResponse( flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId, bool success, uint32_t dataCount) { auto response = fbs::CreateDebugDumpResponse(builder, success, dataCount); finalize(builder, fbs::ChreMessage::DebugDumpResponse, response.Union(), hostClientId); } void HostProtocolChre::encodeTimeSyncRequest( flatbuffers::FlatBufferBuilder& builder) { auto request = fbs::CreateTimeSyncRequest(builder); finalize(builder, fbs::ChreMessage::TimeSyncRequest, request.Union()); } void HostProtocolChre::encodeLowPowerMicAccessRequest( flatbuffers::FlatBufferBuilder& builder) { auto request = fbs::CreateLowPowerMicAccessRequest(builder); finalize(builder, fbs::ChreMessage::LowPowerMicAccessRequest, request.Union()); } void HostProtocolChre::encodeLowPowerMicAccessRelease( flatbuffers::FlatBufferBuilder& builder) { auto request = fbs::CreateLowPowerMicAccessRelease(builder); finalize(builder, fbs::ChreMessage::LowPowerMicAccessRelease, request.Union()); } } // namespace chre