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