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