14d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro/* 24d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Copyright (C) 2016 The Android Open Source Project 34d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * 44d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Licensed under the Apache License, Version 2.0 (the "License"); 54d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * you may not use this file except in compliance with the License. 64d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * You may obtain a copy of the License at 74d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * 84d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * http://www.apache.org/licenses/LICENSE-2.0 94d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * 104d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Unless required by applicable law or agreed to in writing, software 114d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * distributed under the License is distributed on an "AS IS" BASIS, 124d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * See the License for the specific language governing permissions and 144d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * limitations under the License. 154d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro */ 164d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 174d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/send_message.h> 184d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 194d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <inttypes.h> 204d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 214d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/abort.h> 224d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/dumb_allocator.h> 234d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/nano_endian.h> 244d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/nano_string.h> 254d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 264d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <chre.h> 274d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 284d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguronamespace nanoapp_testing { 294d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 304d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguroconstexpr size_t kAllocSize = 128; 314d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 324d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic DumbAllocator<kAllocSize, 4> gDumbAlloc; 334d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 344d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void freeDumbAllocMessage(void *message, size_t messageSize) { 354d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (messageSize > kAllocSize) { 364d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint32_t localSize = uint32_t(messageSize); 374d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendFatalFailureToHost("freeDumbAllocMessage given oversized message:", 384d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro &localSize); 394d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 404d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (!gDumbAlloc.free(message)) { 414d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint32_t localPtr = 424d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro reinterpret_cast<size_t>(message) & UINT32_C(0xFFFFFFFF); 434d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendFatalFailureToHost("freeDumbAllocMessage given bad pointer:", 444d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro &localPtr); 454d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 464d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 474d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 484d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void freeHeapMessage(void *message, size_t /* messageSize */) { 494d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (gDumbAlloc.contains(message)) { 504d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint32_t localPtr = 514d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro reinterpret_cast<size_t>(message) & UINT32_C(0xFFFFFFFF); 524d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendFatalFailureToHost("freeHeapMessage given DumbAlloc pointer:", 534d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro &localPtr); 544d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 554d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro chreHeapFree(message); 564d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 574d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 584d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void fatalError() { 594d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Attempt to send a context-less failure message, in the hopes that 604d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // might get through. 614d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro chreSendMessageToHost(nullptr, 0, 624d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro static_cast<uint32_t>(MessageType::kFailure), 634d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro nullptr); 644d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Whether or not that made it through, unambigiously fail this test 654d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // by aborting. 664d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro nanoapp_testing::abort(); 674d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 684d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 694d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// TODO(b/32114261): Remove this method. 704d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic bool needToPrependMessageType() { 714d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // TODO: When we have a new API that properly send the messageType, 724d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // this method should get the API version and return appropriately. 734d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Eventually we should remove this hacky method. 744d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro return true; 754d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 764d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 774d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void *getMessageMemory(size_t *size, bool *dumbAlloc) { 784d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (needToPrependMessageType()) { 794d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *size += sizeof(uint32_t); 804d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 814d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro void *ret = gDumbAlloc.alloc(*size); 824d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (ret != nullptr) { 834d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *dumbAlloc = true; 844d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } else { 854d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Not expected, but possible if the CHRE is lagging in freeing 864d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // these messages, or if we're sending a huge message. 874d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *dumbAlloc = false; 884d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro ret = chreHeapAlloc(*size); 894d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (ret == nullptr) { 904d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro fatalError(); 914d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 924d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 934d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro return ret; 944d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 954d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 964d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// TODO(b/32114261): Remove this method. 974d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void *prependMessageType(MessageType messageType, void *memory) { 984d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (!needToPrependMessageType()) { 994d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro return memory; 1004d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1014d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint32_t type = static_cast<uint32_t>(messageType); 1024d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro nanoapp_testing::hostToLittleEndian(&type); 1034d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro memcpy(memory, &type, sizeof(type)); 1044d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint8_t *ptr = static_cast<uint8_t*>(memory); 1054d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro ptr += sizeof(type); 1064d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro return ptr; 1074d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1084d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1094d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void internalSendMessage(MessageType messageType, void *data, 1104d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro size_t dataSize, bool dumbAlloc) { 1114d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Note that if the CHRE implementation occasionally drops a message 1124d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // here, then tests will become flaky. For now, we consider that to 1134d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // be a flaky CHRE implementation which should fail testing. 1144d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (!chreSendMessageToHost(data, dataSize, 1154d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro static_cast<uint32_t>(messageType), 1164d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro dumbAlloc ? freeDumbAllocMessage : 1174d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro freeHeapMessage)) { 1184d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro fatalError(); 1194d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1204d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1214d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1224d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid sendMessageToHost(MessageType messageType, const void *data, 1234d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro size_t dataSize) { 1244d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if ((dataSize == 0) && (data != nullptr)) { 1254d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendInternalFailureToHost("Bad sendMessageToHost args"); 1264d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1274d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro bool dumbAlloc = true; 1284d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro size_t fullMessageSize = dataSize; 1294d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro void *myMessageBase = getMessageMemory(&fullMessageSize, &dumbAlloc); 1304d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro void *ptr = prependMessageType(messageType, myMessageBase); 1314d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro memcpy(ptr, data, dataSize); 1324d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro internalSendMessage(messageType, myMessageBase, fullMessageSize, dumbAlloc); 1334d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1344d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1354d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid sendStringToHost(MessageType messageType, const char *message, 1364d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro const uint32_t *value) { 1374d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (message == nullptr) { 1384d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendInternalFailureToHost("sendStringToHost 'message' is NULL"); 1394d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1404d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro bool dumbAlloc = true; 1414d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro const size_t messageStrlen = strlen(message); 1424d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro size_t myMessageLen = messageStrlen; 1434d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (value != nullptr) { 1444d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro myMessageLen += kUint32ToHexAsciiBufferMinLen; 1454d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1464d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Add null terminator 1474d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro myMessageLen++; 1484d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1494d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro size_t fullMessageLen = myMessageLen; 1504d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro char *fullMessage = 1514d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro static_cast<char*>(getMessageMemory(&fullMessageLen, &dumbAlloc)); 1524d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro char *ptr = static_cast<char*>(prependMessageType(messageType, 1534d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro fullMessage)); 1544d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro memcpy(ptr, message, messageStrlen); 1554d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro ptr += messageStrlen; 1564d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (value != nullptr) { 1574d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro uint32ToHexAscii(ptr, fullMessageLen - (ptr - fullMessage), *value); 1584d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1594d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro // Add the terminator. 1604d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro fullMessage[fullMessageLen - 1] = '\0'; 1614d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1624d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro internalSendMessage(messageType, fullMessage, fullMessageLen, dumbAlloc); 1634d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1644d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1654d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// Before we abort the nanoapp, we also put this message in the chreLog(). 1664d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// We have no assurance our message will make it to the Host (not required 1674d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// for CHRE implementations), but this will at least make sure our message 1684d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// hits the log. 1694d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void logFatalMessage(const char *message, const uint32_t *value) { 1704d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro if (value != nullptr) { 1714d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro chreLog(CHRE_LOG_ERROR, "TEST ABORT: %s0x%08" PRIX32, message, *value); 1724d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } else { 1734d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro chreLog(CHRE_LOG_ERROR, "TEST ABORT: %s", message); 1744d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro } 1754d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1764d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1774d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid sendFatalFailureToHost(const char *message, const uint32_t *value, 1784d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro AbortBlame reason) { 1794d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendFailureToHost(message, value); 1804d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro logFatalMessage(message, value); 1814d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro nanoapp_testing::abort(reason); 1824d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1834d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1844d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid sendInternalFailureToHost(const char *message, const uint32_t *value, 1854d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro AbortBlame reason) { 1864d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro sendStringToHost(MessageType::kInternalFailure, message, value); 1874d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro logFatalMessage(message, value); 1884d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro nanoapp_testing::abort(reason); 1894d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} 1904d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro 1914d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro} // namespace nanoapp_testing 192