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
23 #include "chre/core/event_loop_manager.h"
24 #include "chre/platform/assert.h"
25 #include "chre/platform/context.h"
26 #include "chre/platform/host_link.h"
27 #include "chre/util/macros.h"
28 #include "chre/util/nested_data_ptr.h"
29 #include "chre/util/system/event_callbacks.h"
30 #include "chre_api/chre.h"
31
32 namespace chre {
33
34 namespace {
35
36 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
37 //! @see TransactionManager::DeferCancelCallback
deferCancelCallback(uint32_t timerHandle)38 bool deferCancelCallback(uint32_t timerHandle) {
39 return EventLoopManagerSingleton::get()->cancelDelayedCallback(timerHandle);
40 }
41 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
42
43 /**
44 * Checks if the message can be send from the nanoapp to the host.
45 *
46 * @see sendMessageToHostFromNanoapp for a description of the parameter.
47 *
48 * @return Whether the message can be send to the host.
49 */
shouldAcceptMessageToHostFromNanoapp(Nanoapp * nanoapp,void * messageData,size_t messageSize,uint16_t hostEndpoint,uint32_t messagePermissions,bool isReliable)50 bool shouldAcceptMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData,
51 size_t messageSize,
52 uint16_t hostEndpoint,
53 uint32_t messagePermissions,
54 bool isReliable) {
55 bool success = false;
56 if (messageSize > 0 && messageData == nullptr) {
57 LOGW("Rejecting malformed message (null data but non-zero size)");
58 } else if (messageSize > chreGetMessageToHostMaxSize()) {
59 LOGW("Rejecting message of size %zu bytes (max %" PRIu32 ")", messageSize,
60 chreGetMessageToHostMaxSize());
61 } else if (hostEndpoint == kHostEndpointUnspecified) {
62 LOGW("Rejecting message to invalid host endpoint");
63 } else if (isReliable && hostEndpoint == kHostEndpointBroadcast) {
64 LOGW("Rejecting reliable message to broadcast endpoint");
65 } else if (!BITMASK_HAS_VALUE(nanoapp->getAppPermissions(),
66 messagePermissions)) {
67 LOGE("Message perms %" PRIx32 " not subset of napp perms %" PRIx32,
68 messagePermissions, nanoapp->getAppPermissions());
69 } else {
70 success = true;
71 }
72
73 return success;
74 }
75
76 } // namespace
77
HostCommsManager()78 HostCommsManager::HostCommsManager()
79 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
80 : mTransactionManager(sendMessageWithTransactionData,
81 onMessageDeliveryStatus, deferCallback,
82 deferCancelCallback, kReliableMessageRetryWaitTime,
83 kReliableMessageTimeout, kReliableMessageNumRetries)
84 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
85 {
86 }
87
completeTransaction(uint32_t transactionId,uint8_t errorCode)88 bool HostCommsManager::completeTransaction(uint32_t transactionId,
89 uint8_t errorCode) {
90 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
91 return mTransactionManager.completeTransaction(transactionId, errorCode);
92 #else
93 UNUSED_VAR(transactionId);
94 UNUSED_VAR(errorCode);
95 return false;
96 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
97 }
98
flushNanoappMessagesAndTransactions(uint64_t appId)99 void HostCommsManager::flushNanoappMessagesAndTransactions(uint64_t appId) {
100 uint16_t nanoappInstanceId;
101 bool nanoappFound =
102 EventLoopManagerSingleton::get()
103 ->getEventLoop()
104 .findNanoappInstanceIdByAppId(appId, &nanoappInstanceId);
105 if (nanoappFound) {
106 flushNanoappTransactions(nanoappInstanceId);
107 } else {
108 LOGE("Could not find nanoapp 0x%016" PRIx64 " to flush transactions",
109 appId);
110 }
111
112 HostLink::flushMessagesSentByNanoapp(appId);
113 }
114
onMessageToHostComplete(const MessageToHost * message)115 void HostCommsManager::onMessageToHostComplete(const MessageToHost *message) {
116 // We do not call onMessageToHostCompleteInternal for reliable messages
117 // until the completion callback is called.
118 if (message == nullptr || message->isReliable) {
119 return;
120 }
121
122 onMessageToHostCompleteInternal(message);
123 }
124
resetBlameForNanoappHostWakeup()125 void HostCommsManager::resetBlameForNanoappHostWakeup() {
126 mIsNanoappBlamedForWakeup = false;
127 }
128
sendDeferredMessageToNanoappFromHost(MessageFromHost * craftedMessage)129 void HostCommsManager::sendDeferredMessageToNanoappFromHost(
130 MessageFromHost *craftedMessage) {
131 CHRE_ASSERT_LOG(craftedMessage != nullptr,
132 "Deferred message from host is a NULL pointer");
133
134 if (!deliverNanoappMessageFromHost(craftedMessage)) {
135 LOGE("Dropping deferred message; destination app ID 0x%016" PRIx64
136 " still not found",
137 craftedMessage->appId);
138 if (craftedMessage->isReliable) {
139 sendMessageDeliveryStatus(craftedMessage->messageSequenceNumber,
140 CHRE_ERROR_DESTINATION_NOT_FOUND);
141 }
142 mMessagePool.deallocate(craftedMessage);
143 } else {
144 LOGD("Deferred message to app ID 0x%016" PRIx64 " delivered",
145 craftedMessage->appId);
146 }
147 }
148
sendMessageToHostFromNanoapp(Nanoapp * nanoapp,void * messageData,size_t messageSize,uint32_t messageType,uint16_t hostEndpoint,uint32_t messagePermissions,chreMessageFreeFunction * freeCallback,bool isReliable,const void * cookie)149 bool HostCommsManager::sendMessageToHostFromNanoapp(
150 Nanoapp *nanoapp, void *messageData, size_t messageSize,
151 uint32_t messageType, uint16_t hostEndpoint, uint32_t messagePermissions,
152 chreMessageFreeFunction *freeCallback, bool isReliable,
153 const void *cookie) {
154 if (!shouldAcceptMessageToHostFromNanoapp(nanoapp, messageData, messageSize,
155 hostEndpoint, messagePermissions,
156 isReliable)) {
157 return false;
158 }
159
160 MessageToHost *msgToHost = mMessagePool.allocate();
161 if (msgToHost == nullptr) {
162 LOG_OOM();
163 return false;
164 }
165
166 msgToHost->appId = nanoapp->getAppId();
167 msgToHost->message.wrap(static_cast<uint8_t *>(messageData), messageSize);
168 msgToHost->toHostData.hostEndpoint = hostEndpoint;
169 msgToHost->toHostData.messageType = messageType;
170 msgToHost->toHostData.messagePermissions = messagePermissions;
171 msgToHost->toHostData.appPermissions = nanoapp->getAppPermissions();
172 msgToHost->toHostData.nanoappFreeFunction = freeCallback;
173 msgToHost->isReliable = isReliable;
174
175 bool success;
176 if (isReliable) {
177 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
178 MessageTransactionData data = {
179 .messageSequenceNumberPtr = &msgToHost->messageSequenceNumber,
180 .messageSequenceNumber = static_cast<uint32_t>(-1),
181 .nanoappInstanceId = nanoapp->getInstanceId(),
182 .cookie = cookie,
183 };
184 success = mTransactionManager.startTransaction(
185 data, nanoapp->getInstanceId(), &msgToHost->messageSequenceNumber);
186 #else
187 UNUSED_VAR(cookie);
188 success = false;
189 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
190 } else {
191 success = doSendMessageToHostFromNanoapp(nanoapp, msgToHost);
192 }
193
194 if (!success) {
195 mMessagePool.deallocate(msgToHost);
196 }
197 return success;
198 }
199
sendMessageToNanoappFromHost(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void * messageData,size_t messageSize,bool isReliable,uint32_t messageSequenceNumber)200 void HostCommsManager::sendMessageToNanoappFromHost(
201 uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
202 const void *messageData, size_t messageSize, bool isReliable,
203 uint32_t messageSequenceNumber) {
204 if (hostEndpoint == kHostEndpointBroadcast) {
205 LOGE("Received invalid message from host from broadcast endpoint");
206 } else if (messageSize > ((UINT32_MAX))) {
207 // The current CHRE API uses uint32_t to represent the message size in
208 // struct chreMessageFromHostData. We don't expect to ever need to exceed
209 // this, but the check ensures we're on the up and up.
210 LOGE("Rejecting message of size %zu (too big)", messageSize);
211 } else {
212 MessageFromHost *craftedMessage = craftNanoappMessageFromHost(
213 appId, hostEndpoint, messageType, messageData,
214 static_cast<uint32_t>(messageSize), isReliable, messageSequenceNumber);
215 if (craftedMessage == nullptr) {
216 LOGE("Out of memory - rejecting message to app ID 0x%016" PRIx64
217 "(size %zu)",
218 appId, messageSize);
219 if (isReliable) {
220 sendMessageDeliveryStatus(messageSequenceNumber, CHRE_ERROR_NO_MEMORY);
221 }
222 } else if (!deliverNanoappMessageFromHost(craftedMessage)) {
223 LOGV("Deferring message; destination app ID 0x%016" PRIx64
224 " not found at this time",
225 appId);
226
227 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
228 EventLoopManagerSingleton::get()
229 ->getHostCommsManager()
230 .sendDeferredMessageToNanoappFromHost(
231 static_cast<MessageFromHost *>(data));
232 };
233 if (!EventLoopManagerSingleton::get()->deferCallback(
234 SystemCallbackType::DeferredMessageToNanoappFromHost,
235 craftedMessage, callback)) {
236 mMessagePool.deallocate(craftedMessage);
237 }
238 }
239 }
240 }
241
craftNanoappMessageFromHost(uint64_t appId,uint16_t hostEndpoint,uint32_t messageType,const void * messageData,uint32_t messageSize,bool isReliable,uint32_t messageSequenceNumber)242 MessageFromHost *HostCommsManager::craftNanoappMessageFromHost(
243 uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
244 const void *messageData, uint32_t messageSize, bool isReliable,
245 uint32_t messageSequenceNumber) {
246 MessageFromHost *msgFromHost = mMessagePool.allocate();
247 if (msgFromHost == nullptr) {
248 LOG_OOM();
249 } else if (!msgFromHost->message.copy_array(
250 static_cast<const uint8_t *>(messageData), messageSize)) {
251 LOGE("Couldn't allocate %" PRIu32
252 " bytes for message data from host "
253 "(endpoint 0x%" PRIx16 " type %" PRIu32 ")",
254 messageSize, hostEndpoint, messageType);
255 mMessagePool.deallocate(msgFromHost);
256 msgFromHost = nullptr;
257 } else {
258 msgFromHost->appId = appId;
259 msgFromHost->fromHostData.messageType = messageType;
260 msgFromHost->fromHostData.messageSize = messageSize;
261 msgFromHost->fromHostData.message = msgFromHost->message.data();
262 msgFromHost->fromHostData.hostEndpoint = hostEndpoint;
263 msgFromHost->isReliable = isReliable;
264 msgFromHost->messageSequenceNumber = messageSequenceNumber;
265 }
266
267 return msgFromHost;
268 }
269
deferCallback(TransactionManager<MessageTransactionData,kMaxOutstandingMessages>::DeferCallbackFunction func,void * data,void * extraData,Nanoseconds delay,uint32_t * outTimerHandle)270 bool HostCommsManager::deferCallback(
271 TransactionManager<MessageTransactionData,
272 kMaxOutstandingMessages>::DeferCallbackFunction func,
273 void *data, void *extraData, Nanoseconds delay, uint32_t *outTimerHandle) {
274 if (delay.toRawNanoseconds() == 0) {
275 CHRE_ASSERT(outTimerHandle == nullptr);
276 return EventLoopManagerSingleton::get()->deferCallback(
277 SystemCallbackType::ReliableMessageEvent, data, func, extraData);
278 }
279
280 CHRE_ASSERT(outTimerHandle != nullptr);
281 *outTimerHandle = EventLoopManagerSingleton::get()->setDelayedCallback(
282 SystemCallbackType::ReliableMessageEvent, data, func, delay);
283 return true;
284 }
285
deliverNanoappMessageFromHost(MessageFromHost * craftedMessage)286 bool HostCommsManager::deliverNanoappMessageFromHost(
287 MessageFromHost *craftedMessage) {
288 const EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
289 uint16_t targetInstanceId;
290 bool nanoappFound = false;
291
292 CHRE_ASSERT_LOG(craftedMessage != nullptr,
293 "Cannot deliver NULL pointer nanoapp message from host");
294
295 if (eventLoop.findNanoappInstanceIdByAppId(craftedMessage->appId,
296 &targetInstanceId)) {
297 nanoappFound = true;
298 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
299 CHRE_EVENT_MESSAGE_FROM_HOST, &craftedMessage->fromHostData,
300 freeMessageFromHostCallback, targetInstanceId);
301 if (craftedMessage->isReliable) {
302 sendMessageDeliveryStatus(craftedMessage->messageSequenceNumber,
303 CHRE_ERROR_NONE);
304 }
305 }
306
307 return nanoappFound;
308 }
309
doSendMessageToHostFromNanoapp(Nanoapp * nanoapp,MessageToHost * msgToHost)310 bool HostCommsManager::doSendMessageToHostFromNanoapp(
311 Nanoapp *nanoapp, MessageToHost *msgToHost) {
312 bool hostWasAwake = EventLoopManagerSingleton::get()
313 ->getEventLoop()
314 .getPowerControlManager()
315 .hostIsAwake();
316 bool wokeHost = !hostWasAwake && !mIsNanoappBlamedForWakeup;
317 msgToHost->toHostData.wokeHost = wokeHost;
318
319 if (!HostLink::sendMessage(msgToHost)) {
320 return false;
321 }
322
323 if (wokeHost) {
324 EventLoopManagerSingleton::get()
325 ->getEventLoop()
326 .handleNanoappWakeupBuckets();
327 mIsNanoappBlamedForWakeup = true;
328 nanoapp->blameHostWakeup();
329 }
330 nanoapp->blameHostMessageSent();
331 return true;
332 }
333
findMessageByMessageSequenceNumber(uint32_t messageSequenceNumber)334 HostMessage *HostCommsManager::findMessageByMessageSequenceNumber(
335 uint32_t messageSequenceNumber) {
336 return mMessagePool.find(
337 [](HostMessage *inputMessage, void *data) {
338 NestedDataPtr<uint32_t> targetMessageSequenceNumber(data);
339 return inputMessage->isReliable &&
340 inputMessage->messageSequenceNumber ==
341 targetMessageSequenceNumber;
342 },
343 NestedDataPtr<uint32_t>(messageSequenceNumber));
344 }
345
flushNanoappTransactions(uint16_t nanoappInstanceId)346 size_t HostCommsManager::flushNanoappTransactions(uint16_t nanoappInstanceId) {
347 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
348 return mTransactionManager.flushTransactions(
349 [](const MessageTransactionData &data, void *callbackData) {
350 NestedDataPtr<uint16_t> innerNanoappInstanceId(callbackData);
351 if (innerNanoappInstanceId == data.nanoappInstanceId) {
352 HostMessage *message = EventLoopManagerSingleton::get()
353 ->getHostCommsManager()
354 .findMessageByMessageSequenceNumber(
355 data.messageSequenceNumber);
356 if (message != nullptr) {
357 EventLoopManagerSingleton::get()
358 ->getHostCommsManager()
359 .onMessageToHostCompleteInternal(message);
360 }
361 return true;
362 }
363 return false;
364 },
365 NestedDataPtr<uint16_t>(nanoappInstanceId));
366 #else
367 UNUSED_VAR(nanoappInstanceId);
368 return 0;
369 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
370 }
371
freeMessageToHost(MessageToHost * msgToHost)372 void HostCommsManager::freeMessageToHost(MessageToHost *msgToHost) {
373 if (msgToHost->toHostData.nanoappFreeFunction != nullptr) {
374 EventLoopManagerSingleton::get()->getEventLoop().invokeMessageFreeFunction(
375 msgToHost->appId, msgToHost->toHostData.nanoappFreeFunction,
376 msgToHost->message.data(), msgToHost->message.size());
377 }
378 mMessagePool.deallocate(msgToHost);
379 }
380
freeMessageFromHostCallback(uint16_t,void * data)381 void HostCommsManager::freeMessageFromHostCallback(uint16_t /*type*/,
382 void *data) {
383 // We pass the chreMessageFromHostData structure to the nanoapp as the event's
384 // data pointer, but we need to return to the enclosing HostMessage pointer.
385 // As long as HostMessage is standard-layout, and fromHostData is the first
386 // field, we can convert between these two pointers via reinterpret_cast.
387 // These static assertions ensure this assumption is held.
388 static_assert(std::is_standard_layout<HostMessage>::value,
389 "HostMessage* is derived from HostMessage::fromHostData*, "
390 "therefore it must be standard layout");
391 static_assert(offsetof(MessageFromHost, fromHostData) == 0,
392 "fromHostData must be the first field in HostMessage");
393
394 auto *eventData = static_cast<chreMessageFromHostData *>(data);
395 auto *msgFromHost = reinterpret_cast<MessageFromHost *>(eventData);
396 auto &hostCommsMgr = EventLoopManagerSingleton::get()->getHostCommsManager();
397 hostCommsMgr.mMessagePool.deallocate(msgFromHost);
398 }
399
sendMessageWithTransactionData(MessageTransactionData & data)400 bool HostCommsManager::sendMessageWithTransactionData(
401 MessageTransactionData &data) {
402 // Set the message sequence number now that TransactionManager has set it.
403 // The message should still be available right now, but might not be later,
404 // so the pointer could be invalid at a later time.
405 data.messageSequenceNumber = *data.messageSequenceNumberPtr;
406
407 HostMessage *message =
408 EventLoopManagerSingleton::get()
409 ->getHostCommsManager()
410 .findMessageByMessageSequenceNumber(data.messageSequenceNumber);
411 Nanoapp *nanoapp =
412 EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
413 data.nanoappInstanceId);
414 return nanoapp != nullptr && message != nullptr &&
415 EventLoopManagerSingleton::get()
416 ->getHostCommsManager()
417 .doSendMessageToHostFromNanoapp(nanoapp, message);
418 }
419
onMessageDeliveryStatus(const MessageTransactionData & data,uint8_t errorCode)420 bool HostCommsManager::onMessageDeliveryStatus(
421 const MessageTransactionData &data, uint8_t errorCode) {
422 chreAsyncResult *asyncResult = memoryAlloc<chreAsyncResult>();
423 if (asyncResult == nullptr) {
424 LOG_OOM();
425 return false;
426 }
427
428 asyncResult->requestType = 0;
429 asyncResult->cookie = data.cookie;
430 asyncResult->errorCode = errorCode;
431 asyncResult->reserved = 0;
432 asyncResult->success = errorCode == CHRE_ERROR_NONE;
433
434 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
435 CHRE_EVENT_RELIABLE_MSG_ASYNC_RESULT, asyncResult, freeEventDataCallback,
436 data.nanoappInstanceId);
437
438 HostMessage *message =
439 EventLoopManagerSingleton::get()
440 ->getHostCommsManager()
441 .findMessageByMessageSequenceNumber(data.messageSequenceNumber);
442 if (message != nullptr) {
443 EventLoopManagerSingleton::get()
444 ->getHostCommsManager()
445 .onMessageToHostCompleteInternal(message);
446 }
447
448 return true;
449 }
450
onMessageToHostCompleteInternal(const MessageToHost * message)451 void HostCommsManager::onMessageToHostCompleteInternal(
452 const MessageToHost *message) {
453 // Removing const on message since we own the memory and will deallocate it;
454 // the caller (HostLink) only gets a const pointer
455 auto *msgToHost = const_cast<MessageToHost *>(message);
456
457 // If there's no free callback, we can free the message right away as the
458 // message pool is thread-safe; otherwise, we need to do it from within the
459 // EventLoop context.
460 if (msgToHost->toHostData.nanoappFreeFunction == nullptr) {
461 mMessagePool.deallocate(msgToHost);
462 } else if (inEventLoopThread()) {
463 // If we're already within the event loop context, it is safe to call the
464 // free callback synchronously.
465 EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
466 msgToHost);
467 } else {
468 auto freeMsgCallback = [](uint16_t /*type*/, void *data,
469 void * /*extraData*/) {
470 EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
471 static_cast<MessageToHost *>(data));
472 };
473
474 if (!EventLoopManagerSingleton::get()->deferCallback(
475 SystemCallbackType::MessageToHostComplete, msgToHost,
476 freeMsgCallback)) {
477 EventLoopManagerSingleton::get()->getHostCommsManager().freeMessageToHost(
478 static_cast<MessageToHost *>(msgToHost));
479 }
480 }
481 }
482
483 } // namespace chre
484