xref: /aosp_15_r20/system/chre/core/host_comms_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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_common.h"
25 #include "chre/core/event_loop_manager.h"
26 #include "chre/platform/assert.h"
27 #include "chre/platform/context.h"
28 #include "chre/platform/host_link.h"
29 #include "chre/platform/log.h"
30 #include "chre/util/duplicate_message_detector.h"
31 #include "chre/util/macros.h"
32 #include "chre/util/nested_data_ptr.h"
33 #include "chre/util/optional.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,
324         messageSequenceNumber);
325     if (craftedMessage == nullptr) {
326       LOGE("Out of memory - rejecting message to app ID 0x%016" PRIx64
327             "(size %zu)",
328             appId, messageSize);
329       error = CHRE_ERROR_NO_MEMORY;
330     }
331   }
332   return std::make_pair(error, craftedMessage);
333 }
334 
deliverNanoappMessageFromHost(MessageFromHost * craftedMessage)335 void HostCommsManager::deliverNanoappMessageFromHost(
336     MessageFromHost *craftedMessage) {
337   CHRE_ASSERT_LOG(craftedMessage != nullptr,
338                   "Cannot deliver NULL pointer nanoapp message from host");
339 
340   Optional<chreError> error;
341   uint16_t targetInstanceId;
342 
343   bool foundNanoapp = EventLoopManagerSingleton::get()
344                           ->getEventLoop()
345                           .findNanoappInstanceIdByAppId(craftedMessage->appId,
346                                                         &targetInstanceId);
347   bool shouldDeliverMessage = !craftedMessage->isReliable ||
348                                 shouldSendReliableMessageToNanoapp(
349                                     craftedMessage->messageSequenceNumber,
350                                     craftedMessage->fromHostData.hostEndpoint);
351   if (!foundNanoapp) {
352     error = CHRE_ERROR_DESTINATION_NOT_FOUND;
353   } else if (shouldDeliverMessage) {
354     EventLoopManagerSingleton::get()->getEventLoop().distributeEventSync(
355         CHRE_EVENT_MESSAGE_FROM_HOST, &craftedMessage->fromHostData,
356         targetInstanceId);
357     error = CHRE_ERROR_NONE;
358   }
359 
360   if (craftedMessage->isReliable && error.has_value()) {
361     handleDuplicateAndSendMessageDeliveryStatus(
362         craftedMessage->messageSequenceNumber,
363         craftedMessage->fromHostData.hostEndpoint, error.value());
364   }
365   mMessagePool.deallocate(craftedMessage);
366 
367 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
368   mDuplicateMessageDetector.removeOldEntries();
369 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
370 }
371 
doSendMessageToHostFromNanoapp(Nanoapp * nanoapp,MessageToHost * msgToHost)372 bool HostCommsManager::doSendMessageToHostFromNanoapp(
373     Nanoapp *nanoapp, MessageToHost *msgToHost) {
374   bool hostWasAwake = EventLoopManagerSingleton::get()
375                           ->getEventLoop()
376                           .getPowerControlManager()
377                           .hostIsAwake();
378   bool wokeHost = !hostWasAwake && !mIsNanoappBlamedForWakeup;
379   msgToHost->toHostData.wokeHost = wokeHost;
380 
381   if (!HostLink::sendMessage(msgToHost)) {
382     return false;
383   }
384 
385   if (wokeHost) {
386     EventLoopManagerSingleton::get()
387         ->getEventLoop()
388         .handleNanoappWakeupBuckets();
389     mIsNanoappBlamedForWakeup = true;
390     nanoapp->blameHostWakeup();
391   }
392   nanoapp->blameHostMessageSent();
393   return true;
394 }
395 
findMessageToHostBySeq(uint32_t messageSequenceNumber)396 MessageToHost *HostCommsManager::findMessageToHostBySeq(
397     uint32_t messageSequenceNumber) {
398   return mMessagePool.find(
399       [](HostMessage *inputMessage, void *data) {
400         NestedDataPtr<uint32_t> targetMessageSequenceNumber(data);
401         return inputMessage->isReliable && !inputMessage->fromHost &&
402                inputMessage->messageSequenceNumber ==
403                    targetMessageSequenceNumber;
404       },
405       NestedDataPtr<uint32_t>(messageSequenceNumber));
406 }
407 
freeMessageToHost(MessageToHost * msgToHost)408 void HostCommsManager::freeMessageToHost(MessageToHost *msgToHost) {
409   if (msgToHost->toHostData.nanoappFreeFunction != nullptr) {
410     EventLoopManagerSingleton::get()->getEventLoop().invokeMessageFreeFunction(
411         msgToHost->appId, msgToHost->toHostData.nanoappFreeFunction,
412         msgToHost->message.data(), msgToHost->message.size());
413   }
414 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
415   if (msgToHost->isReliable) {
416     mTransactionManager.remove(msgToHost->messageSequenceNumber);
417   }
418 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
419   mMessagePool.deallocate(msgToHost);
420 }
421 
onTransactionAttempt(uint32_t messageSequenceNumber,uint16_t nanoappInstanceId)422 void HostCommsManager::onTransactionAttempt(uint32_t messageSequenceNumber,
423                                             uint16_t nanoappInstanceId) {
424   MessageToHost *message = findMessageToHostBySeq(messageSequenceNumber);
425   Nanoapp *nanoapp =
426       EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
427           nanoappInstanceId);
428   if (message == nullptr || nanoapp == nullptr) {
429     LOGE("Attempted to send reliable message %" PRIu32 " from nanoapp %" PRIu16
430          " but couldn't find:%s%s",
431          messageSequenceNumber, nanoappInstanceId,
432          (message == nullptr) ? " msg" : "",
433          (nanoapp == nullptr) ? " napp" : "");
434   } else {
435     bool success = doSendMessageToHostFromNanoapp(nanoapp, message);
436     LOGD("Attempted to send reliable message %" PRIu32 " from nanoapp %" PRIu16
437          " with success: %s",
438          messageSequenceNumber, nanoappInstanceId, success ? "true" : "false");
439   }
440 }
441 
onTransactionFailure(uint32_t messageSequenceNumber,uint16_t nanoappInstanceId)442 void HostCommsManager::onTransactionFailure(uint32_t messageSequenceNumber,
443                                             uint16_t nanoappInstanceId) {
444   LOGE("Reliable message %" PRIu32 " from nanoapp %" PRIu16 " timed out",
445        messageSequenceNumber, nanoappInstanceId);
446   handleMessageDeliveryStatusSync(messageSequenceNumber, CHRE_ERROR_TIMEOUT);
447 }
448 
handleDuplicateAndSendMessageDeliveryStatus(uint32_t messageSequenceNumber,uint16_t hostEndpoint,chreError error)449 void HostCommsManager::handleDuplicateAndSendMessageDeliveryStatus(
450     [[maybe_unused]] uint32_t messageSequenceNumber,
451     [[maybe_unused]] uint16_t hostEndpoint,
452     [[maybe_unused]] chreError error) {
453 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
454   bool success = mDuplicateMessageDetector.findAndSetError(
455       messageSequenceNumber, hostEndpoint, error);
456   if (!success) {
457     LOGW("Failed to set error for message with message sequence number: %"
458           PRIu32 " and host endpoint: 0x%" PRIx16,
459           messageSequenceNumber,
460           hostEndpoint);
461   }
462   sendMessageDeliveryStatus(messageSequenceNumber, error);
463 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
464 }
465 
handleMessageDeliveryStatusSync(uint32_t messageSequenceNumber,uint8_t errorCode)466 void HostCommsManager::handleMessageDeliveryStatusSync(
467     uint32_t messageSequenceNumber, uint8_t errorCode) {
468   EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
469   uint16_t nanoappInstanceId;
470   MessageToHost *message = findMessageToHostBySeq(messageSequenceNumber);
471   if (message == nullptr) {
472     LOGW("Got message delivery status for unexpected seq %" PRIu32,
473          messageSequenceNumber);
474   } else if (!eventLoop.findNanoappInstanceIdByAppId(message->appId,
475                                                      &nanoappInstanceId)) {
476     // Expected if we unloaded the nanoapp while a message was in flight
477     LOGW("Got message delivery status seq %" PRIu32
478          " but couldn't find nanoapp 0x%" PRIx64,
479          messageSequenceNumber, message->appId);
480   } else {
481     chreAsyncResult asyncResult = {};
482     asyncResult.success = errorCode == CHRE_ERROR_NONE;
483     asyncResult.errorCode = errorCode;
484     asyncResult.cookie = message->cookie;
485 
486     onMessageToHostCompleteInternal(message);
487     eventLoop.distributeEventSync(CHRE_EVENT_RELIABLE_MSG_ASYNC_RESULT,
488                                   &asyncResult, nanoappInstanceId);
489   }
490 }
491 
onMessageToHostCompleteInternal(const MessageToHost * message)492 void HostCommsManager::onMessageToHostCompleteInternal(
493     const MessageToHost *message) {
494   // Removing const on message since we own the memory and will deallocate it;
495   // the caller (HostLink) only gets a const pointer
496   auto *msgToHost = const_cast<MessageToHost *>(message);
497 
498   // TODO(b/346345637): add an assertion that HostLink does not own the memory,
499   // which is technically possible if a reliable message timed out before it
500   // was released
501 
502   // If there's no free callback, we can free the message right away as the
503   // message pool is thread-safe; otherwise, we need to do it from within the
504   // EventLoop context.
505   if (msgToHost->toHostData.nanoappFreeFunction == nullptr) {
506     mMessagePool.deallocate(msgToHost);
507   } else if (inEventLoopThread()) {
508     // If we're already within the event loop context, it is safe to call the
509     // free callback synchronously.
510     freeMessageToHost(msgToHost);
511   } else {
512     auto freeMsgCallback = [](uint16_t /*type*/, void *data,
513                               void * /*extraData*/) {
514       EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
515           static_cast<MessageToHost *>(data));
516     };
517 
518     if (!EventLoopManagerSingleton::get()->deferCallback(
519             SystemCallbackType::MessageToHostComplete, msgToHost,
520             freeMsgCallback)) {
521       freeMessageToHost(static_cast<MessageToHost *>(msgToHost));
522     }
523   }
524 }
525 
shouldSendReliableMessageToNanoapp(uint32_t messageSequenceNumber,uint16_t hostEndpoint)526 bool HostCommsManager::shouldSendReliableMessageToNanoapp(
527     [[maybe_unused]] uint32_t messageSequenceNumber,
528     [[maybe_unused]] uint16_t hostEndpoint) {
529 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
530   bool isDuplicate;
531   Optional<chreError> pastError = mDuplicateMessageDetector.findOrAdd(
532       messageSequenceNumber, hostEndpoint, &isDuplicate);
533 
534   if (isDuplicate) {
535     bool isTransientFailure =
536         pastError.has_value() && (pastError.value() == CHRE_ERROR_BUSY ||
537                                   pastError.value() == CHRE_ERROR_TRANSIENT);
538     LOGW("Duplicate message with message sequence number: %" PRIu32
539          " and host endpoint: 0x%" PRIx16 " was detected. %s",
540          messageSequenceNumber, hostEndpoint,
541          isTransientFailure ? "Retrying." : "Not sending message to nanoapp.");
542     if (!isTransientFailure) {
543       if (pastError.has_value()) {
544         sendMessageDeliveryStatus(messageSequenceNumber, pastError.value());
545       }
546       return false;
547     }
548   }
549 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
550 
551   return true;
552 }
553 
554 }  // namespace chre
555