• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include "chre/core/host_comms_manager.h"
18 
19 #include <cinttypes>
20 #include <cstdint>
21 #include <type_traits>
22 #include <utility>
23 
24 #include "chre/core/event_loop_manager.h"
25 #include "chre/platform/assert.h"
26 #include "chre/platform/context.h"
27 #include "chre/platform/host_link.h"
28 #include "chre/platform/log.h"
29 #include "chre/util/duplicate_message_detector.h"
30 #include "chre/util/macros.h"
31 #include "chre/util/nested_data_ptr.h"
32 #include "chre/util/optional.h"
33 #include "chre/util/system/system_callback_type.h"
34 #include "chre_api/chre.h"
35 
36 namespace chre {
37 
38 namespace {
39 
40 /**
41  * Checks if the message can be send from the nanoapp to the host.
42  *
43  * @see sendMessageToHostFromNanoapp for a description of the parameters.
44  *
45  * @return Whether the message can be send to the host.
46  */
shouldAcceptMessageToHostFromNanoapp(Nanoapp * nanoapp,void * messageData,size_t messageSize,uint16_t hostEndpoint,uint32_t messagePermissions,bool isReliable)47 bool shouldAcceptMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData,
48                                           size_t messageSize,
49                                           uint16_t hostEndpoint,
50                                           uint32_t messagePermissions,
51                                           bool isReliable) {
52   bool success = false;
53   if (messageSize > 0 && messageData == nullptr) {
54     LOGW("Rejecting malformed message (null data but non-zero size)");
55   } else if (messageSize > chreGetMessageToHostMaxSize()) {
56     LOGW("Rejecting message of size %zu bytes (max %" PRIu32 ")", messageSize,
57          chreGetMessageToHostMaxSize());
58   } else if (hostEndpoint == kHostEndpointUnspecified) {
59     LOGW("Rejecting message to invalid host endpoint");
60   } else if (isReliable && hostEndpoint == kHostEndpointBroadcast) {
61     LOGW("Rejecting reliable message to broadcast endpoint");
62   } else if (!BITMASK_HAS_VALUE(nanoapp->getAppPermissions(),
63                                 messagePermissions)) {
64     LOGE("Message perms %" PRIx32 " not subset of napp perms %" PRIx32,
65          messagePermissions, nanoapp->getAppPermissions());
66   } else {
67     success = true;
68   }
69 
70   return success;
71 }
72 
73 }  // namespace
74 
HostCommsManager()75 HostCommsManager::HostCommsManager()
76 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
77     : mDuplicateMessageDetector(kReliableMessageDuplicateDetectorTimeout),
78       mTransactionManager(
79           *this,
80           EventLoopManagerSingleton::get()->getEventLoop().getTimerPool(),
81           kReliableMessageRetryWaitTime, kReliableMessageMaxAttempts)
82 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
83 {
84 }
85 
86 // TODO(b/346345637): rename this to align it with the message delivery status
87 // terminology used elsewhere, and make it return void
completeTransaction(uint32_t transactionId,uint8_t errorCode)88 bool HostCommsManager::completeTransaction(
89     [[maybe_unused]] uint32_t transactionId,
90     [[maybe_unused]] uint8_t errorCode) {
91 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
92   auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
93     uint32_t txnId = NestedDataPtr<uint32_t>(data);
94     uint8_t err = NestedDataPtr<uint8_t>(extraData);
95     EventLoopManagerSingleton::get()
96         ->getHostCommsManager()
97         .handleMessageDeliveryStatusSync(txnId, err);
98   };
99   EventLoopManagerSingleton::get()->deferCallback(
100       SystemCallbackType::ReliableMessageEvent,
101       NestedDataPtr<uint32_t>(transactionId), callback,
102       NestedDataPtr<uint8_t>(errorCode));
103   return true;
104 #else
105   return false;
106 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
107 }
108 
removeAllTransactionsFromNanoapp(const Nanoapp & nanoapp)109 void HostCommsManager::removeAllTransactionsFromNanoapp(
110     [[maybe_unused]] const Nanoapp &nanoapp) {
111 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
112   struct FindContext {
113     decltype(mTransactionManager) &transactionManager;
114     const Nanoapp &nanoapp;
115   };
116 
117   // Cancel any pending outbound reliable messages. We leverage find() here as
118   // a forEach() method by always returning false.
119   auto transactionRemover = [](HostMessage *msg, void *data) {
120     FindContext *ctx = static_cast<FindContext *>(data);
121 
122     if (msg->isReliable && !msg->fromHost &&
123         msg->appId == ctx->nanoapp.getAppId() &&
124         !ctx->transactionManager.remove(msg->messageSequenceNumber)) {
125       LOGE("Couldn't find transaction %" PRIu32 " at flush",
126            msg->messageSequenceNumber);
127     }
128 
129     return false;
130   };
131 
132   FindContext context{mTransactionManager, nanoapp};
133   mMessagePool.find(transactionRemover, &context);
134 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
135 }
136 
freeAllReliableMessagesFromNanoapp(Nanoapp & nanoapp)137 void HostCommsManager::freeAllReliableMessagesFromNanoapp(
138     [[maybe_unused]] Nanoapp &nanoapp) {
139 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
140   auto reliableMessageFromNanoappMatcher = [](HostMessage *msg, void *data) {
141     auto *napp = static_cast<const Nanoapp *>(data);
142     return (msg->isReliable && !msg->fromHost &&
143             msg->appId == napp->getAppId());
144   };
145   MessageToHost *message;
146   while ((message = mMessagePool.find(reliableMessageFromNanoappMatcher,
147                                       &nanoapp)) != nullptr) {
148     // We don't post message delivery status to the nanoapp, since it's being
149     // unloaded and we don't actually know the final message delivery status –
150     // simply free the memory
151     onMessageToHostCompleteInternal(message);
152   }
153 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
154 }
155 
flushNanoappMessages(Nanoapp & nanoapp)156 void HostCommsManager::flushNanoappMessages(Nanoapp &nanoapp) {
157   // First we remove all of the outgoing reliable message transactions from the
158   // transaction manager, which triggers sending any pending reliable messages
159   removeAllTransactionsFromNanoapp(nanoapp);
160 
161   // This ensures that HostLink does not reference message memory (owned the
162   // nanoapp) anymore, i.e. onMessageToHostComplete() is called, which lets us
163   // free memory for any pending reliable messages
164   HostLink::flushMessagesSentByNanoapp(nanoapp.getAppId());
165   freeAllReliableMessagesFromNanoapp(nanoapp);
166 }
167 
168 // TODO(b/346345637): rename this to better reflect its true meaning, which is
169 // that HostLink doesn't reference the memory anymore
onMessageToHostComplete(const MessageToHost * message)170 void HostCommsManager::onMessageToHostComplete(const MessageToHost *message) {
171   // We do not call onMessageToHostCompleteInternal for reliable messages
172   // until the completion callback is called.
173   if (message != nullptr && !message->isReliable) {
174     onMessageToHostCompleteInternal(message);
175   }
176 }
177 
resetBlameForNanoappHostWakeup()178 void HostCommsManager::resetBlameForNanoappHostWakeup() {
179   mIsNanoappBlamedForWakeup = false;
180 }
181 
sendMessageToHostFromNanoapp(Nanoapp * nanoapp,void * messageData,size_t messageSize,uint32_t messageType,uint16_t hostEndpoint,uint32_t messagePermissions,chreMessageFreeFunction * freeCallback,bool isReliable,const void * cookie)182 bool HostCommsManager::sendMessageToHostFromNanoapp(
183     Nanoapp *nanoapp, void *messageData, size_t messageSize,
184     uint32_t messageType, uint16_t hostEndpoint, uint32_t messagePermissions,
185     chreMessageFreeFunction *freeCallback, bool isReliable,
186     const void *cookie) {
187   if (!shouldAcceptMessageToHostFromNanoapp(nanoapp, messageData, messageSize,
188                                             hostEndpoint, messagePermissions,
189                                             isReliable)) {
190     return false;
191   }
192 
193   MessageToHost *msgToHost = mMessagePool.allocate();
194   if (msgToHost == nullptr) {
195     LOG_OOM();
196     return false;
197   }
198 
199   msgToHost->appId = nanoapp->getAppId();
200   msgToHost->message.wrap(static_cast<uint8_t *>(messageData), messageSize);
201   msgToHost->toHostData.hostEndpoint = hostEndpoint;
202   msgToHost->toHostData.messageType = messageType;
203   msgToHost->toHostData.messagePermissions = messagePermissions;
204   msgToHost->toHostData.appPermissions = nanoapp->getAppPermissions();
205   msgToHost->toHostData.nanoappFreeFunction = freeCallback;
206   msgToHost->isReliable = isReliable;
207   msgToHost->cookie = cookie;
208   msgToHost->fromHost = false;
209 
210   bool success = false;
211   if (isReliable) {
212 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
213     success = mTransactionManager.add(nanoapp->getInstanceId(),
214                                       &msgToHost->messageSequenceNumber);
215 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
216   } else {
217     success = doSendMessageToHostFromNanoapp(nanoapp, msgToHost);
218   }
219 
220   if (!success) {
221     mMessagePool.deallocate(msgToHost);
222   }
223   return success;
224 }
225 
sendMessageToNanoappFromHost(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void * messageData,size_t messageSize,bool isReliable,uint32_t messageSequenceNumber)226 void HostCommsManager::sendMessageToNanoappFromHost(
227     uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
228     const void *messageData, size_t messageSize, bool isReliable,
229     uint32_t messageSequenceNumber) {
230   std::pair<chreError, MessageFromHost *> output =
231       validateAndCraftMessageFromHostToNanoapp(
232           appId, messageType, hostEndpoint, messageData, messageSize,
233           isReliable, messageSequenceNumber);
234   chreError error = output.first;
235   MessageFromHost *craftedMessage = output.second;
236 
237   if (error == CHRE_ERROR_NONE) {
238     auto callback = [](uint16_t /*type*/, void *data, void * /* extraData */) {
239       MessageFromHost *craftedMessage = static_cast<MessageFromHost *>(data);
240       EventLoopManagerSingleton::get()
241           ->getHostCommsManager()
242           .deliverNanoappMessageFromHost(craftedMessage);
243     };
244 
245     if (!EventLoopManagerSingleton::get()->deferCallback(
246             SystemCallbackType::DeferredMessageToNanoappFromHost,
247             craftedMessage, callback)) {
248       LOGE("Failed to defer callback to send message to nanoapp from host");
249       error = CHRE_ERROR_BUSY;
250     }
251   }
252 
253   if (error != CHRE_ERROR_NONE) {
254 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
255     if (isReliable) {
256       sendMessageDeliveryStatus(messageSequenceNumber, error);
257     }
258 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
259 
260     if (craftedMessage != nullptr) {
261       mMessagePool.deallocate(craftedMessage);
262     }
263   }
264 }
265 
craftNanoappMessageFromHost(uint64_t appId,uint16_t hostEndpoint,uint32_t messageType,const void * messageData,uint32_t messageSize,bool isReliable,uint32_t messageSequenceNumber)266 MessageFromHost *HostCommsManager::craftNanoappMessageFromHost(
267     uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
268     const void *messageData, uint32_t messageSize, bool isReliable,
269     uint32_t messageSequenceNumber) {
270   MessageFromHost *msgFromHost = mMessagePool.allocate();
271   if (msgFromHost == nullptr) {
272     LOG_OOM();
273   } else if (!msgFromHost->message.copy_array(
274                  static_cast<const uint8_t *>(messageData), messageSize)) {
275     LOGE("Couldn't allocate %" PRIu32
276          " bytes for message data from host (endpoint 0x%" PRIx16
277          " type %" PRIu32 ")",
278          messageSize, hostEndpoint, messageType);
279     mMessagePool.deallocate(msgFromHost);
280     msgFromHost = nullptr;
281   } else {
282     msgFromHost->appId = appId;
283     msgFromHost->fromHostData.messageType = messageType;
284     msgFromHost->fromHostData.messageSize = messageSize;
285     msgFromHost->fromHostData.message = msgFromHost->message.data();
286     msgFromHost->fromHostData.hostEndpoint = hostEndpoint;
287     msgFromHost->isReliable = isReliable;
288     msgFromHost->messageSequenceNumber = messageSequenceNumber;
289     msgFromHost->fromHost = true;
290   }
291 
292   return msgFromHost;
293 }
294 
295 /**
296  * Checks if the message can be send to the nanoapp from the host. Crafts
297  * the message to the nanoapp.
298  *
299  * @see sendMessageToNanoappFromHost for a description of the parameters.
300  *
301  * @return the error code and the crafted message
302  */
303 std::pair<chreError, MessageFromHost *>
validateAndCraftMessageFromHostToNanoapp(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void * messageData,size_t messageSize,bool isReliable,uint32_t messageSequenceNumber)304 HostCommsManager::validateAndCraftMessageFromHostToNanoapp(
305     uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
306     const void *messageData, size_t messageSize, bool isReliable,
307     uint32_t messageSequenceNumber) {
308   chreError error = CHRE_ERROR_NONE;
309   MessageFromHost *craftedMessage = nullptr;
310 
311   if (hostEndpoint == kHostEndpointBroadcast) {
312     LOGE("Received invalid message from host from broadcast endpoint");
313     error = CHRE_ERROR_INVALID_ARGUMENT;
314   } else if (messageSize > UINT32_MAX) {
315     // The current CHRE API uses uint32_t to represent the message size in
316     // struct chreMessageFromHostData. We don't expect to ever need to exceed
317     // this, but the check ensures we're on the up and up.
318     LOGE("Rejecting message of size %zu (too big)", messageSize);
319     error = CHRE_ERROR_INVALID_ARGUMENT;
320   } else {
321     craftedMessage = craftNanoappMessageFromHost(
322         appId, hostEndpoint, messageType, messageData,
323         static_cast<uint32_t>(messageSize), isReliable, messageSequenceNumber);
324     if (craftedMessage == nullptr) {
325       LOGE("Out of memory - rejecting message to app ID 0x%016" PRIx64
326            "(size %zu)",
327            appId, messageSize);
328       error = CHRE_ERROR_NO_MEMORY;
329     }
330   }
331   return std::make_pair(error, craftedMessage);
332 }
333 
deliverNanoappMessageFromHost(MessageFromHost * craftedMessage)334 void HostCommsManager::deliverNanoappMessageFromHost(
335     MessageFromHost *craftedMessage) {
336   CHRE_ASSERT_LOG(craftedMessage != nullptr,
337                   "Cannot deliver NULL pointer nanoapp message from host");
338 
339   Optional<chreError> error;
340   uint16_t targetInstanceId;
341 
342   bool foundNanoapp = EventLoopManagerSingleton::get()
343                           ->getEventLoop()
344                           .findNanoappInstanceIdByAppId(craftedMessage->appId,
345                                                         &targetInstanceId);
346   bool shouldDeliverMessage = !craftedMessage->isReliable ||
347                               shouldSendReliableMessageToNanoapp(
348                                   craftedMessage->messageSequenceNumber,
349                                   craftedMessage->fromHostData.hostEndpoint);
350   if (!foundNanoapp) {
351     error = CHRE_ERROR_DESTINATION_NOT_FOUND;
352   } else if (shouldDeliverMessage) {
353     EventLoopManagerSingleton::get()->getEventLoop().distributeEventSync(
354         CHRE_EVENT_MESSAGE_FROM_HOST, &craftedMessage->fromHostData,
355         targetInstanceId);
356     error = CHRE_ERROR_NONE;
357   }
358 
359   if (craftedMessage->isReliable && error.has_value()) {
360     handleDuplicateAndSendMessageDeliveryStatus(
361         craftedMessage->messageSequenceNumber,
362         craftedMessage->fromHostData.hostEndpoint, error.value());
363   }
364   mMessagePool.deallocate(craftedMessage);
365 
366 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
367   mDuplicateMessageDetector.removeOldEntries();
368 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
369 }
370 
doSendMessageToHostFromNanoapp(Nanoapp * nanoapp,MessageToHost * msgToHost)371 bool HostCommsManager::doSendMessageToHostFromNanoapp(
372     Nanoapp *nanoapp, MessageToHost *msgToHost) {
373   bool hostWasAwake = EventLoopManagerSingleton::get()
374                           ->getEventLoop()
375                           .getPowerControlManager()
376                           .hostIsAwake();
377   bool wokeHost = !hostWasAwake && !mIsNanoappBlamedForWakeup;
378   msgToHost->toHostData.wokeHost = wokeHost;
379 
380   if (!HostLink::sendMessage(msgToHost)) {
381     return false;
382   }
383 
384   if (wokeHost) {
385     mIsNanoappBlamedForWakeup = true;
386     nanoapp->blameHostWakeup();
387   }
388   nanoapp->blameHostMessageSent();
389   return true;
390 }
391 
findMessageToHostBySeq(uint32_t messageSequenceNumber)392 MessageToHost *HostCommsManager::findMessageToHostBySeq(
393     uint32_t messageSequenceNumber) {
394   return mMessagePool.find(
395       [](HostMessage *inputMessage, void *data) {
396         NestedDataPtr<uint32_t> targetMessageSequenceNumber(data);
397         return inputMessage->isReliable && !inputMessage->fromHost &&
398                inputMessage->messageSequenceNumber ==
399                    targetMessageSequenceNumber;
400       },
401       NestedDataPtr<uint32_t>(messageSequenceNumber));
402 }
403 
freeMessageToHost(MessageToHost * msgToHost)404 void HostCommsManager::freeMessageToHost(MessageToHost *msgToHost) {
405   if (msgToHost->toHostData.nanoappFreeFunction != nullptr) {
406     EventLoopManagerSingleton::get()->getEventLoop().invokeMessageFreeFunction(
407         msgToHost->appId, msgToHost->toHostData.nanoappFreeFunction,
408         msgToHost->message.data(), msgToHost->message.size());
409   }
410 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
411   if (msgToHost->isReliable) {
412     mTransactionManager.remove(msgToHost->messageSequenceNumber);
413   }
414 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
415   mMessagePool.deallocate(msgToHost);
416 }
417 
onTransactionAttempt(uint32_t messageSequenceNumber,uint16_t nanoappInstanceId)418 void HostCommsManager::onTransactionAttempt(uint32_t messageSequenceNumber,
419                                             uint16_t nanoappInstanceId) {
420   MessageToHost *message = findMessageToHostBySeq(messageSequenceNumber);
421   Nanoapp *nanoapp =
422       EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
423           nanoappInstanceId);
424   if (message == nullptr || nanoapp == nullptr) {
425     LOGE("Attempted to send reliable message %" PRIu32 " from nanoapp %" PRIu16
426          " but couldn't find:%s%s",
427          messageSequenceNumber, nanoappInstanceId,
428          (message == nullptr) ? " msg" : "",
429          (nanoapp == nullptr) ? " napp" : "");
430   } else {
431     bool success = doSendMessageToHostFromNanoapp(nanoapp, message);
432     LOGD("Attempted to send reliable message %" PRIu32 " from nanoapp %" PRIu16
433          " with success: %s",
434          messageSequenceNumber, nanoappInstanceId, success ? "true" : "false");
435   }
436 }
437 
onTransactionFailure(uint32_t messageSequenceNumber,uint16_t nanoappInstanceId)438 void HostCommsManager::onTransactionFailure(uint32_t messageSequenceNumber,
439                                             uint16_t nanoappInstanceId) {
440   LOGE("Reliable message %" PRIu32 " from nanoapp %" PRIu16 " timed out",
441        messageSequenceNumber, nanoappInstanceId);
442   handleMessageDeliveryStatusSync(messageSequenceNumber, CHRE_ERROR_TIMEOUT);
443 }
444 
handleDuplicateAndSendMessageDeliveryStatus(uint32_t messageSequenceNumber,uint16_t hostEndpoint,chreError error)445 void HostCommsManager::handleDuplicateAndSendMessageDeliveryStatus(
446     [[maybe_unused]] uint32_t messageSequenceNumber,
447     [[maybe_unused]] uint16_t hostEndpoint, [[maybe_unused]] chreError error) {
448 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
449   bool success = mDuplicateMessageDetector.findAndSetError(
450       messageSequenceNumber, hostEndpoint, error);
451   if (!success) {
452     LOGW(
453         "Failed to set error for message with message sequence number: %" PRIu32
454         " and host endpoint: 0x%" PRIx16,
455         messageSequenceNumber, hostEndpoint);
456   }
457   sendMessageDeliveryStatus(messageSequenceNumber, error);
458 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
459 }
460 
handleMessageDeliveryStatusSync(uint32_t messageSequenceNumber,uint8_t errorCode)461 void HostCommsManager::handleMessageDeliveryStatusSync(
462     uint32_t messageSequenceNumber, uint8_t errorCode) {
463   EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
464   uint16_t nanoappInstanceId;
465   MessageToHost *message = findMessageToHostBySeq(messageSequenceNumber);
466   if (message == nullptr) {
467     LOGW("Got message delivery status for unexpected seq %" PRIu32,
468          messageSequenceNumber);
469   } else if (!eventLoop.findNanoappInstanceIdByAppId(message->appId,
470                                                      &nanoappInstanceId)) {
471     // Expected if we unloaded the nanoapp while a message was in flight
472     LOGW("Got message delivery status seq %" PRIu32
473          " but couldn't find nanoapp 0x%" PRIx64,
474          messageSequenceNumber, message->appId);
475   } else {
476     chreAsyncResult asyncResult = {};
477     asyncResult.success = errorCode == CHRE_ERROR_NONE;
478     asyncResult.errorCode = errorCode;
479     asyncResult.cookie = message->cookie;
480 
481     onMessageToHostCompleteInternal(message);
482     eventLoop.distributeEventSync(CHRE_EVENT_RELIABLE_MSG_ASYNC_RESULT,
483                                   &asyncResult, nanoappInstanceId);
484   }
485 }
486 
onMessageToHostCompleteInternal(const MessageToHost * message)487 void HostCommsManager::onMessageToHostCompleteInternal(
488     const MessageToHost *message) {
489   // Removing const on message since we own the memory and will deallocate it;
490   // the caller (HostLink) only gets a const pointer
491   auto *msgToHost = const_cast<MessageToHost *>(message);
492 
493   // TODO(b/346345637): add an assertion that HostLink does not own the memory,
494   // which is technically possible if a reliable message timed out before it
495   // was released
496 
497   // If there's no free callback, we can free the message right away as the
498   // message pool is thread-safe; otherwise, we need to do it from within the
499   // EventLoop context.
500   if (msgToHost->toHostData.nanoappFreeFunction == nullptr) {
501     mMessagePool.deallocate(msgToHost);
502   } else if (inEventLoopThread()) {
503     // If we're already within the event loop context, it is safe to call the
504     // free callback synchronously.
505     freeMessageToHost(msgToHost);
506   } else {
507     auto freeMsgCallback = [](uint16_t /*type*/, void *data,
508                               void * /*extraData*/) {
509       EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
510           static_cast<MessageToHost *>(data));
511     };
512 
513     if (!EventLoopManagerSingleton::get()->deferCallback(
514             SystemCallbackType::MessageToHostComplete, msgToHost,
515             freeMsgCallback)) {
516       freeMessageToHost(static_cast<MessageToHost *>(msgToHost));
517     }
518   }
519 }
520 
shouldSendReliableMessageToNanoapp(uint32_t messageSequenceNumber,uint16_t hostEndpoint)521 bool HostCommsManager::shouldSendReliableMessageToNanoapp(
522     [[maybe_unused]] uint32_t messageSequenceNumber,
523     [[maybe_unused]] uint16_t hostEndpoint) {
524 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
525   bool isDuplicate;
526   Optional<chreError> pastError = mDuplicateMessageDetector.findOrAdd(
527       messageSequenceNumber, hostEndpoint, &isDuplicate);
528 
529   if (isDuplicate) {
530     bool isTransientFailure =
531         pastError.has_value() && (pastError.value() == CHRE_ERROR_BUSY ||
532                                   pastError.value() == CHRE_ERROR_TRANSIENT);
533     LOGW("Duplicate message with message sequence number: %" PRIu32
534          " and host endpoint: 0x%" PRIx16 " was detected. %s",
535          messageSequenceNumber, hostEndpoint,
536          isTransientFailure ? "Retrying." : "Not sending message to nanoapp.");
537     if (!isTransientFailure) {
538       if (pastError.has_value()) {
539         sendMessageDeliveryStatus(messageSequenceNumber, pastError.value());
540       }
541       return false;
542     }
543   }
544 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
545 
546   return true;
547 }
548 
549 }  // namespace chre
550