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