host_comms_manager.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <cinttypes>
  17. #include <type_traits>
  18. #include "chre/core/event_loop_manager.h"
  19. #include "chre/core/host_comms_manager.h"
  20. #include "chre/platform/assert.h"
  21. #include "chre/platform/host_link.h"
  22. namespace chre {
  23. constexpr uint32_t kMessageToHostReservedFieldValue = UINT32_MAX;
  24. void HostCommsManager::flushMessagesSentByNanoapp(uint64_t appId) {
  25. mHostLink.flushMessagesSentByNanoapp(appId);
  26. }
  27. bool HostCommsManager::sendMessageToHostFromNanoapp(
  28. Nanoapp *nanoapp, void *messageData, size_t messageSize,
  29. uint32_t messageType, uint16_t hostEndpoint,
  30. chreMessageFreeFunction *freeCallback) {
  31. bool success = false;
  32. if (messageSize > 0 && messageData == nullptr) {
  33. LOGW("Rejecting malformed message (null data but non-zero size)");
  34. } else if (messageSize > CHRE_MESSAGE_TO_HOST_MAX_SIZE) {
  35. LOGW("Rejecting message of size %zu bytes (max %d)",
  36. messageSize, CHRE_MESSAGE_TO_HOST_MAX_SIZE);
  37. } else if (hostEndpoint == kHostEndpointUnspecified) {
  38. LOGW("Rejecting message to invalid host endpoint");
  39. } else {
  40. MessageToHost *msgToHost = mMessagePool.allocate();
  41. if (msgToHost == nullptr) {
  42. LOG_OOM();
  43. } else {
  44. msgToHost->appId = nanoapp->getAppId();
  45. msgToHost->message.wrap(static_cast<uint8_t *>(messageData), messageSize);
  46. msgToHost->toHostData.hostEndpoint = hostEndpoint;
  47. msgToHost->toHostData.messageType = messageType;
  48. msgToHost->toHostData.nanoappFreeFunction = freeCallback;
  49. // Populate a special value to help disambiguate message direction when
  50. // debugging
  51. msgToHost->toHostData.reserved = kMessageToHostReservedFieldValue;
  52. success = mHostLink.sendMessage(msgToHost);
  53. if (!success) {
  54. mMessagePool.deallocate(msgToHost);
  55. }
  56. }
  57. }
  58. return success;
  59. }
  60. void HostCommsManager::deliverNanoappMessageFromHost(
  61. uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
  62. const void *messageData, uint32_t messageSize, uint32_t targetInstanceId) {
  63. bool success = false;
  64. MessageFromHost *msgFromHost = mMessagePool.allocate();
  65. if (msgFromHost == nullptr) {
  66. LOG_OOM();
  67. } else if (!msgFromHost->message.copy_array(
  68. static_cast<const uint8_t *>(messageData), messageSize)) {
  69. LOGE("Couldn't allocate %" PRIu32 " bytes for message data from host "
  70. "(endpoint 0x%" PRIx16 " type %" PRIu32 ")", messageSize,
  71. hostEndpoint, messageType);
  72. } else {
  73. msgFromHost->appId = appId;
  74. msgFromHost->fromHostData.messageType = messageType;
  75. msgFromHost->fromHostData.messageSize = static_cast<uint32_t>(
  76. messageSize);
  77. msgFromHost->fromHostData.message = msgFromHost->message.data();
  78. msgFromHost->fromHostData.hostEndpoint = hostEndpoint;
  79. success = EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  80. CHRE_EVENT_MESSAGE_FROM_HOST, &msgFromHost->fromHostData,
  81. freeMessageFromHostCallback, targetInstanceId);
  82. }
  83. if (!success && msgFromHost != nullptr) {
  84. mMessagePool.deallocate(msgFromHost);
  85. }
  86. }
  87. void HostCommsManager::sendMessageToNanoappFromHost(
  88. uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
  89. const void *messageData, size_t messageSize) {
  90. const EventLoop& eventLoop = EventLoopManagerSingleton::get()
  91. ->getEventLoop();
  92. uint32_t targetInstanceId;
  93. if (hostEndpoint == kHostEndpointBroadcast) {
  94. LOGE("Received invalid message from host from broadcast endpoint");
  95. } else if (messageSize > ((UINT32_MAX))) {
  96. // The current CHRE API uses uint32_t to represent the message size in
  97. // struct chreMessageFromHostData. We don't expect to ever need to exceed
  98. // this, but the check ensures we're on the up and up.
  99. LOGE("Rejecting message of size %zu (too big)", messageSize);
  100. } else if (!eventLoop.findNanoappInstanceIdByAppId(appId,
  101. &targetInstanceId)) {
  102. LOGE("Dropping message; destination app ID 0x%016" PRIx64 " not found",
  103. appId);
  104. } else {
  105. deliverNanoappMessageFromHost(appId, hostEndpoint, messageType, messageData,
  106. static_cast<uint32_t>(messageSize),
  107. targetInstanceId);
  108. }
  109. }
  110. void HostCommsManager::onMessageToHostComplete(const MessageToHost *message) {
  111. // Removing const on message since we own the memory and will deallocate it;
  112. // the caller (HostLink) only gets a const pointer
  113. auto *msgToHost = const_cast<MessageToHost *>(message);
  114. // If there's no free callback, we can free the message right away as the
  115. // message pool is thread-safe; otherwise, we need to do it from within the
  116. // EventLoop context.
  117. if (msgToHost->toHostData.nanoappFreeFunction == nullptr) {
  118. mMessagePool.deallocate(msgToHost);
  119. } else {
  120. auto freeMsgCallback = [](uint16_t /*type*/, void *data) {
  121. EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
  122. static_cast<MessageToHost *>(data));
  123. };
  124. EventLoopManagerSingleton::get()->deferCallback(
  125. SystemCallbackType::MessageToHostComplete, msgToHost, freeMsgCallback);
  126. }
  127. }
  128. void HostCommsManager::freeMessageToHost(MessageToHost *msgToHost) {
  129. if (msgToHost->toHostData.nanoappFreeFunction != nullptr) {
  130. EventLoopManagerSingleton::get()->getEventLoop().invokeMessageFreeFunction(
  131. msgToHost->appId, msgToHost->toHostData.nanoappFreeFunction,
  132. msgToHost->message.data(), msgToHost->message.size());
  133. }
  134. mMessagePool.deallocate(msgToHost);
  135. }
  136. void HostCommsManager::freeMessageFromHostCallback(uint16_t /*type*/,
  137. void *data) {
  138. // We pass the chreMessageFromHostData structure to the nanoapp as the event's
  139. // data pointer, but we need to return to the enclosing HostMessage pointer.
  140. // As long as HostMessage is standard-layout, and fromHostData is the first
  141. // field, we can convert between these two pointers via reinterpret_cast.
  142. // These static assertions ensure this assumption is held.
  143. static_assert(std::is_standard_layout<HostMessage>::value,
  144. "HostMessage* is derived from HostMessage::fromHostData*, "
  145. "therefore it must be standard layout");
  146. static_assert(offsetof(MessageFromHost, fromHostData) == 0,
  147. "fromHostData must be the first field in HostMessage");
  148. auto *eventData = static_cast<chreMessageFromHostData *>(data);
  149. auto *msgFromHost = reinterpret_cast<MessageFromHost *>(eventData);
  150. auto& hostCommsMgr = EventLoopManagerSingleton::get()->getHostCommsManager();
  151. hostCommsMgr.mMessagePool.deallocate(msgFromHost);
  152. }
  153. } // namespace chre