1a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie/* 2a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * Copyright (C) 2017 The Android Open Source Project 3a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 4a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * Licensed under the Apache License, Version 2.0 (the "License"); 5a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * you may not use this file except in compliance with the License. 6a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * You may obtain a copy of the License at 7a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 8a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * http://www.apache.org/licenses/LICENSE-2.0 9a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 10a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * Unless required by applicable law or agreed to in writing, software 11a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * distributed under the License is distributed on an "AS IS" BASIS, 12a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * See the License for the specific language governing permissions and 14a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * limitations under the License. 15a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie */ 16a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 17a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include <inttypes.h> 18a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include <limits.h> 19a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 20a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "qurt.h" 21a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 22a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "chre/core/event_loop_manager.h" 23a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "chre/core/host_comms_manager.h" 24a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie#include "chre/platform/context.h" 25a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie#include "chre/platform/memory.h" 26a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "chre/platform/log.h" 277621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie#include "chre/platform/shared/host_protocol_chre.h" 28a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "chre/platform/slpi/fastrpc.h" 29a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie#include "chre/util/fixed_size_blocking_queue.h" 307621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie#include "chre/util/macros.h" 3147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie#include "chre/util/unique_ptr.h" 327621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie#include "chre_api/chre/version.h" 337621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 347621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddieusing flatbuffers::FlatBufferBuilder; 35a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 36a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddienamespace chre { 37a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 38a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddienamespace { 39a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 40a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddieconstexpr size_t kOutboundQueueSize = 32; 41a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 42f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie//! Used to pass the client ID through the user data pointer in deferCallback 43f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddieunion HostClientIdCallbackData { 44f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie uint16_t hostClientId; 45f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie void *ptr; 46f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie}; 47f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddiestatic_assert(sizeof(uint16_t) <= sizeof(void*), 48f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie "Pointer must at least fit a u16 for passing the host client ID"); 49f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie 5047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddiestruct LoadNanoappCallbackData { 5147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie uint64_t appId; 5247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie uint32_t transactionId; 5347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie uint16_t hostClientId; 5447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie UniquePtr<Nanoapp> nanoapp = MakeUnique<Nanoapp>(); 5547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie}; 5647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 577621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddieenum class PendingMessageType { 587621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie Shutdown, 597621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie NanoappMessageToHost, 607621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie HubInfoResponse, 61a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie NanoappListResponse, 6247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LoadNanoappResponse, 637621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie}; 647621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 657621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddiestruct PendingMessage { 66f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie PendingMessage(PendingMessageType msgType, uint16_t hostClientId) { 677621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie type = msgType; 68f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie data.hostClientId = hostClientId; 69f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie } 70f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie 71f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie PendingMessage(PendingMessageType msgType, 72f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie const MessageToHost *msgToHost = nullptr) { 73f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie type = msgType; 74f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie data.msgToHost = msgToHost; 7572833b2fba97751b31b27422d117b05f718760fdBrian Duddie } 767621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 77a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie PendingMessage(PendingMessageType msgType, FlatBufferBuilder *builder) { 78a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie type = msgType; 79a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie data.builder = builder; 80a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } 81a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 827621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie PendingMessageType type; 837621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie union { 847621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie const MessageToHost *msgToHost; 85f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie uint16_t hostClientId; 86a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie FlatBufferBuilder *builder; 877621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie } data; 8872833b2fba97751b31b27422d117b05f718760fdBrian Duddie}; 89ef456c07c1738f624e95259878d41305129e64d9Brian Duddie 907621b3267fd2ff1068d7aa7d75441d68646226abBrian DuddieFixedSizeBlockingQueue<PendingMessage, kOutboundQueueSize> 917621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie gOutboundQueue; 927621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 937621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddieint copyToHostBuffer(const FlatBufferBuilder& builder, unsigned char *buffer, 947621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie size_t bufferSize, unsigned int *messageLen) { 957621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie uint8_t *data = builder.GetBufferPointer(); 967621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie size_t size = builder.GetSize(); 977621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie int result; 987621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 997621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie if (size > bufferSize) { 1007621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie LOGE("Encoded structure size %zu too big for host buffer %zu; dropping", 1017621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie size, bufferSize); 1027621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie result = CHRE_FASTRPC_ERROR; 1037621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie } else { 1047621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie memcpy(buffer, data, size); 1057621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie *messageLen = size; 1067621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie result = CHRE_FASTRPC_SUCCESS; 1077621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie } 1087621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 1097621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie return result; 1107621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie} 1117621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 112f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddievoid constructNanoappListCallback(uint16_t /*eventType*/, void *deferCbData) { 113a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie constexpr size_t kFixedOverhead = 56; 114a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie constexpr size_t kPerNanoappSize = 16; 115a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 116f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie HostClientIdCallbackData clientIdCbData; 117f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie clientIdCbData.ptr = deferCbData; 118f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie 119a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie // TODO: need to add support for getting apps from multiple event loops 120a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie bool pushed = false; 121a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie EventLoop *eventLoop = getCurrentEventLoop(); 122a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie size_t expectedNanoappCount = eventLoop->getNanoappCount(); 123a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie DynamicVector<NanoappListEntryOffset> nanoappEntries; 124a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 125a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie auto *builder = memoryAlloc<FlatBufferBuilder>( 126a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie kFixedOverhead + expectedNanoappCount * kPerNanoappSize); 127a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie if (builder == nullptr) { 128a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie LOGE("Couldn't allocate builder for nanoapp list response"); 129a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } else if (!nanoappEntries.reserve(expectedNanoappCount)) { 130a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie LOGE("Couldn't reserve space for list of nanoapp offsets"); 131a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } else { 132a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie struct CallbackData { 133a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie CallbackData(FlatBufferBuilder& builder_, 134a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie DynamicVector<NanoappListEntryOffset>& nanoappEntries_) 135a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie : builder(builder_), nanoappEntries(nanoappEntries_) {} 136a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 137a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie FlatBufferBuilder& builder; 138a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie DynamicVector<NanoappListEntryOffset>& nanoappEntries; 139a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie }; 140a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 141a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie auto callback = [](const Nanoapp *nanoapp, void *untypedData) { 142a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie auto *data = static_cast<CallbackData *>(untypedData); 143a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie HostProtocolChre::addNanoappListEntry( 144a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie data->builder, data->nanoappEntries, nanoapp->getAppId(), 145a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie nanoapp->getAppVersion(), true /*enabled*/, 146a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie nanoapp->isSystemNanoapp()); 147a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie }; 148a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 149a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie // Add a NanoappListEntry to the FlatBuffer for each nanoapp 150a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie CallbackData cbData(*builder, nanoappEntries); 151a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie eventLoop->forEachNanoapp(callback, &cbData); 152f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie HostProtocolChre::finishNanoappListResponse(*builder, nanoappEntries, 153f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie clientIdCbData.hostClientId); 154a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 155a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie pushed = gOutboundQueue.push( 156a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie PendingMessage(PendingMessageType::NanoappListResponse, builder)); 157a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie if (!pushed) { 158a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie LOGE("Couldn't push list response"); 159a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } 160a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } 161a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 162a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie if (!pushed && builder != nullptr) { 163a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie memoryFree(builder); 164a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } 165a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie} 166a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 16747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddievoid finishLoadingNanoappCallback(uint16_t /*eventType*/, void *data) { 16847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie UniquePtr<LoadNanoappCallbackData> cbData( 16947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie static_cast<LoadNanoappCallbackData *>(data)); 17047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 17147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie EventLoop *eventLoop = getCurrentEventLoop(); 17247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie bool startedSuccessfully = (cbData->nanoapp->isLoaded()) ? 17347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie eventLoop->startNanoapp(cbData->nanoapp) : false; 17447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 17547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie constexpr size_t kInitialBufferSize = 48; 17647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie auto *builder = memoryAlloc<FlatBufferBuilder>(kInitialBufferSize); 17747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie if (builder == nullptr) { 17847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LOGE("Couldn't allocate memory for load nanoapp response"); 17947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } else { 18047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie HostProtocolChre::encodeLoadNanoappResponse( 18147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie *builder, cbData->hostClientId, cbData->transactionId, 18247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie startedSuccessfully); 18347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 18447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie // TODO: if this fails, ideally we should block for some timeout until 18547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie // there's space in the queue (like up to 1 second) 18647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie if (!gOutboundQueue.push(PendingMessage( 18747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie PendingMessageType::LoadNanoappResponse, builder))) { 18847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LOGE("Couldn't push load nanoapp response to outbound queue"); 18947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie memoryFree(builder); 19047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } 19147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } 19247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie} 19347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 1947621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddieint generateMessageToHost(const MessageToHost *msgToHost, unsigned char *buffer, 1957621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie size_t bufferSize, unsigned int *messageLen) { 1967621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie // TODO: ideally we'd construct our flatbuffer directly in the 1977621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie // host-supplied buffer 198a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie constexpr size_t kFixedSizePortion = 56; 1997621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie FlatBufferBuilder builder(msgToHost->message.size() + kFixedSizePortion); 2007621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie HostProtocolChre::encodeNanoappMessage( 2017621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie builder, msgToHost->appId, msgToHost->toHostData.messageType, 2027621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie msgToHost->toHostData.hostEndpoint, msgToHost->message.data(), 2037621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie msgToHost->message.size()); 2047621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2057621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie int result = copyToHostBuffer(builder, buffer, bufferSize, messageLen); 2067621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2077621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie auto& hostCommsManager = 2087621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie EventLoopManagerSingleton::get()->getHostCommsManager(); 2097621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie hostCommsManager.onMessageToHostComplete(msgToHost); 2107621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2117621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie return result; 2127621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie} 2137621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 214f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddieint generateHubInfoResponse(uint16_t hostClientId, unsigned char *buffer, 215f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie size_t bufferSize, unsigned int *messageLen) { 2167621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr size_t kInitialBufferSize = 192; 2177621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2187621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr char kHubName[] = "CHRE on SLPI"; 2197621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr char kVendor[] = "Google"; 2207621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr char kToolchain[] = "Hexagon Tools 8.0 (clang " 2217621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie STRINGIFY(__clang_major__) "." 2227621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie STRINGIFY(__clang_minor__) "." 2237621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie STRINGIFY(__clang_patchlevel__) ")"; 2247621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr uint32_t kLegacyPlatformVersion = 0; 2257621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr uint32_t kLegacyToolchainVersion = 2267621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie ((__clang_major__ & 0xFF) << 24) | 2277621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie ((__clang_minor__ & 0xFF) << 16) | 2287621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie (__clang_patchlevel__ & 0xFFFF); 2297621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr float kPeakMips = 350; 2307621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr float kStoppedPower = 0; 2317621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr float kSleepPower = 1; 2327621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie constexpr float kPeakPower = 15; 2337621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2347621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie FlatBufferBuilder builder(kInitialBufferSize); 2357621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie HostProtocolChre::encodeHubInfoResponse( 2367621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie builder, kHubName, kVendor, kToolchain, kLegacyPlatformVersion, 2377621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie kLegacyToolchainVersion, kPeakMips, kStoppedPower, kSleepPower, 2387621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie kPeakPower, CHRE_MESSAGE_TO_HOST_MAX_SIZE, chreGetPlatformId(), 239f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie chreGetVersion(), hostClientId); 2407621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2417621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie return copyToHostBuffer(builder, buffer, bufferSize, messageLen); 2427621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie} 2437621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 24447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddieint generateMessageFromBuilder( 245a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie FlatBufferBuilder *builder, unsigned char *buffer, size_t bufferSize, 246a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie unsigned int *messageLen) { 247a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie CHRE_ASSERT(builder != nullptr); 248a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie int result = copyToHostBuffer(*builder, buffer, bufferSize, messageLen); 249a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie memoryFree(builder); 250a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie return result; 251a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie} 252a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 253ef456c07c1738f624e95259878d41305129e64d9Brian Duddie/** 254a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * FastRPC method invoked by the host to block on messages 255a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 256a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @param buffer Output buffer to populate with message data 257a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @param bufferLen Size of the buffer, in bytes 258a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @param messageLen Output parameter to populate with the size of the message 259a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * in bytes upon success 260a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 261a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @return 0 on success, nonzero on failure 262a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie */ 263a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddieextern "C" int chre_slpi_get_message_to_host( 264a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie unsigned char *buffer, int bufferLen, unsigned int *messageLen) { 265a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie CHRE_ASSERT(buffer != nullptr); 266a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie CHRE_ASSERT(bufferLen > 0); 267a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie CHRE_ASSERT(messageLen != nullptr); 2687621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie int result = CHRE_FASTRPC_ERROR; 269a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 2707621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie if (bufferLen <= 0 || buffer == nullptr || messageLen == nullptr) { 2717621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie // Note that we can't use regular logs here as they can result in sending 2727621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie // a message, leading to an infinite loop if the error is persistent 2737621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie FARF(FATAL, "Invalid buffer size %d or bad pointers (buf %d len %d)", 2747621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie bufferLen, (buffer == nullptr), (messageLen == nullptr)); 275a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } else { 2767621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie size_t bufferSize = static_cast<size_t>(bufferLen); 2777621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie PendingMessage pendingMsg = gOutboundQueue.pop(); 278a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 2797621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie switch (pendingMsg.type) { 2807621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie case PendingMessageType::Shutdown: 2817621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie result = CHRE_FASTRPC_ERROR_SHUTTING_DOWN; 2827621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie break; 2837621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2847621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie case PendingMessageType::NanoappMessageToHost: 2857621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie result = generateMessageToHost(pendingMsg.data.msgToHost, buffer, 2867621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie bufferSize, messageLen); 2877621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie break; 2887621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 2897621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie case PendingMessageType::HubInfoResponse: 290f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie result = generateHubInfoResponse(pendingMsg.data.hostClientId, buffer, 291f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie bufferSize, messageLen); 2927621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie break; 2937621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 294a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie case PendingMessageType::NanoappListResponse: 29547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie case PendingMessageType::LoadNanoappResponse: 29647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie result = generateMessageFromBuilder(pendingMsg.data.builder, 29747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie buffer, bufferSize, messageLen); 298a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie break; 299a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 3007621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie default: 3017621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie CHRE_ASSERT_LOG(false, "Unexpected pending message type"); 3027621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie } 303a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } 304a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 305f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie LOGD("Returning message to host (result %d length %u)", result, *messageLen); 306a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie return result; 307a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} 308a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 309a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie/** 310a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * FastRPC method invoked by the host to send a message to the system 311a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 312a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @param buffer 313a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @param size 314a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * 315a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie * @return 0 on success, nonzero on failure 316a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie */ 317a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddieextern "C" int chre_slpi_deliver_message_from_host(const unsigned char *message, 318a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie int messageLen) { 31918a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie CHRE_ASSERT(message != nullptr); 32018a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie CHRE_ASSERT(messageLen > 0); 32118a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie int result = CHRE_FASTRPC_ERROR; 32218a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie 32372833b2fba97751b31b27422d117b05f718760fdBrian Duddie if (message == nullptr || messageLen <= 0) { 32418a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie LOGE("Got null or invalid size (%d) message from host", messageLen); 3257621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie } else if (!HostProtocolChre::decodeMessageFromHost( 3267621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie message, static_cast<size_t>(messageLen))) { 32772833b2fba97751b31b27422d117b05f718760fdBrian Duddie LOGE("Failed to decode/handle message"); 32818a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie } else { 32972833b2fba97751b31b27422d117b05f718760fdBrian Duddie result = CHRE_FASTRPC_SUCCESS; 33018a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie } 33118a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie 33218a498cfae5841009e9cd8022f691272a6967a5dBrian Duddie return result; 333a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} 334a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 335a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} // anonymous namespace 336a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 337a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddiebool HostLink::sendMessage(const MessageToHost *message) { 3387621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie return gOutboundQueue.push( 3397621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie PendingMessage(PendingMessageType::NanoappMessageToHost, message)); 340a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} 341a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 342a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddievoid HostLinkBase::shutdown() { 343a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie constexpr qurt_timer_duration_t kPollingIntervalUsec = 5000; 344a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 345a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // Push a null message so the blocking call in chre_slpi_get_message_to_host() 346a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // returns and the host can exit cleanly. If the queue is full, try again to 347a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // avoid getting stuck (no other new messages should be entering the queue at 348a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // this time). Don't wait too long as the host-side binary may have died in 349a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // a state where it's not blocked in chre_slpi_get_message_to_host(). 350a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie int retryCount = 5; 351a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie FARF(MEDIUM, "Shutting down host link"); 3527621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie while (!gOutboundQueue.push(PendingMessage(PendingMessageType::Shutdown)) 3537621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie && --retryCount > 0) { 354a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie qurt_timer_sleep(kPollingIntervalUsec); 355a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } 356a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 357a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie if (retryCount <= 0) { 358a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // Don't use LOGE, as it may involve trying to send a message 359a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie FARF(ERROR, "No room in outbound queue for shutdown message and host not " 360a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie "draining queue!"); 361a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } else { 362a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie FARF(MEDIUM, "Draining message queue"); 363a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 364a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // We were able to push the shutdown message. Wait for the queue to 365a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie // completely flush before returning. 366a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie int waitCount = 5; 367a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie while (!gOutboundQueue.empty() && --waitCount > 0) { 368a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie qurt_timer_sleep(kPollingIntervalUsec); 369a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } 370a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 371a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie if (waitCount <= 0) { 372a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie FARF(ERROR, "Host took too long to drain outbound queue; exiting anyway"); 373a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } else { 374a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie FARF(MEDIUM, "Finished draining queue"); 375a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } 376a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie } 377a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} 378a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie 3797621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddievoid HostMessageHandlers::handleNanoappMessage( 3807621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie uint64_t appId, uint32_t messageType, uint16_t hostEndpoint, 3817621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie const void *messageData, size_t messageDataLen) { 3827621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie LOGD("Parsed nanoapp message from host: app ID 0x%016" PRIx64 ", endpoint " 3837621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie "0x%" PRIx16 ", msgType %" PRIu32 ", payload size %zu", 3847621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie appId, hostEndpoint, messageType, messageDataLen); 3857621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 3867621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie HostCommsManager& manager = 3877621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie EventLoopManagerSingleton::get()->getHostCommsManager(); 3887621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie manager.sendMessageToNanoappFromHost( 3897621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie appId, messageType, hostEndpoint, messageData, messageDataLen); 3907621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie} 3917621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 392f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddievoid HostMessageHandlers::handleHubInfoRequest(uint16_t hostClientId) { 3937621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie // We generate the response in the context of chre_slpi_get_message_to_host 394f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie LOGD("Got hub info request from client ID %" PRIu16, hostClientId); 395f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie gOutboundQueue.push(PendingMessage( 396f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie PendingMessageType::HubInfoResponse, hostClientId)); 3977621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie} 3987621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie 399f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddievoid HostMessageHandlers::handleNanoappListRequest(uint16_t hostClientId) { 400f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie LOGD("Got nanoapp list request from client ID %" PRIu16, hostClientId); 401f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie HostClientIdCallbackData cbData = {}; 402f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie cbData.hostClientId = hostClientId; 403a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie EventLoopManagerSingleton::get()->deferCallback( 404f685db3a6b34f8dd6942964ae99836bda87c8134Brian Duddie SystemCallbackType::NanoappListResponse, cbData.ptr, 405a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie constructNanoappListCallback); 406a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie} 407a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 40847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddievoid HostMessageHandlers::handleLoadNanoappRequest( 40947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie uint16_t hostClientId, uint32_t transactionId, uint64_t appId, 41047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie uint32_t appVersion, uint32_t targetApiVersion, const void *appBinary, 41147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie size_t appBinaryLen) { 41247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie auto cbData = MakeUnique<LoadNanoappCallbackData>(); 41347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 41447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LOGD("Got load nanoapp request (txnId %" PRIu32 ") for appId 0x%016" PRIx64 41547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie " version 0x%" PRIx32 " target API version 0x%08" PRIx32 " size %zu", 41647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie transactionId, appId, appVersion, targetApiVersion, appBinaryLen); 41747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie if (cbData.isNull() || cbData->nanoapp.isNull()) { 41847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LOGE("Couldn't allocate load nanoapp callback data"); 41947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } else { 42047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie cbData->transactionId = transactionId; 42147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie cbData->hostClientId = hostClientId; 42247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie cbData->appId = appId; 42347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 42447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie // Note that if this fails, we'll generate the error response in 42547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie // the normal deferred callback 42647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie cbData->nanoapp->loadFromBuffer(appId, appVersion, appBinary, appBinaryLen); 42747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie if (!EventLoopManagerSingleton::get()->deferCallback( 42847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie SystemCallbackType::FinishLoadingNanoapp, cbData.get(), 42947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie finishLoadingNanoappCallback)) { 43047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie LOGE("Couldn't post callback to finish loading nanoapp"); 43147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } else { 43247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie cbData.release(); 43347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } 43447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie } 43547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie} 43647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie 437a0ead37f82267c65e220bd08e28856dce6badf82Brian Duddie} // namespace chre 438