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