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 #ifndef CHRE_CORE_HOST_COMMS_MANAGER_H_
18 #define CHRE_CORE_HOST_COMMS_MANAGER_H_
19 
20 #include <cstddef>
21 #include <cstdint>
22 
23 #include "chre/core/event_loop.h"
24 #include "chre/platform/atomic.h"
25 #include "chre/platform/host_link.h"
26 #include "chre/util/buffer.h"
27 #include "chre/util/non_copyable.h"
28 #include "chre/util/synchronized_memory_pool.h"
29 #include "chre/util/time.h"
30 #include "chre/util/transaction_manager.h"
31 #include "chre_api/chre/event.h"
32 
33 namespace chre {
34 
35 //! Only valid for messages from host to CHRE - indicates that the sender of the
36 //! message is not specified.
37 constexpr uint16_t kHostEndpointUnspecified = CHRE_HOST_ENDPOINT_UNSPECIFIED;
38 
39 //! Only valid for messages from CHRE to host - delivers the message to all
40 //! registered clients of the Context Hub HAL, which is the default behavior.
41 constexpr uint16_t kHostEndpointBroadcast = CHRE_HOST_ENDPOINT_BROADCAST;
42 
43 /**
44  * Data associated with a message either to or from the host.
45  */
46 struct HostMessage : public NonCopyable {
47   // This union must be first, as this structure is aliased with
48   // chreMessageFromHostData
49   union {
50     // Fields use when the message was received from the host
51     struct chreMessageFromHostData fromHostData;
52 
53     // Fields used when the messsage is directed to the host
54     struct {
55       //! Application-specific message ID
56       uint32_t messageType;
57 
58       //! List of Android permissions declared by the nanoapp. This must be a
59       //! superset of messagePermissions.
60       uint32_t appPermissions;
61 
62       //! List of Android permissions that cover the contents of the message.
63       //! These permissions are used to record and attribute access to
64       //! permissions-controlled resources.
65       //! Note that these permissions must always be a subset of uint32_t
66       //! permissions. Otherwise, the message will be dropped.
67       uint32_t messagePermissions;
68 
69       //! Message free callback supplied by the nanoapp. Must only be invoked
70       //! from the EventLoop where the nanoapp runs.
71       chreMessageFreeFunction *nanoappFreeFunction;
72 
73       //! Identifier for the host-side entity that should receive this message,
74       //! or that which sent it
75       uint16_t hostEndpoint;
76 
77       //! true if this message results in the host transitioning from suspend
78       //! to awake.
79       bool wokeHost;
80     } toHostData;
81   };
82 
83   //! Whether the message is reliable.
84   //! Reliable messages are acknowledge by sending with a status containing
85   //! the transaction ID.
86   bool isReliable;
87 
88   //! Source/destination nanoapp ID
89   uint64_t appId;
90 
91   //! Used to report reliable message status back to the sender.
92   uint32_t messageSequenceNumber;
93 
94   //! Application-defined message data
95   Buffer<uint8_t> message;
96 };
97 
98 typedef HostMessage MessageFromHost;
99 typedef HostMessage MessageToHost;
100 
101 /**
102  * Common code for managing bi-directional communications between the host and
103  * nanoapps. Inherits from the platform-specific HostLink class to accomplish
104  * this, and also to provide an access point (lookup via the EventLoopManager
105  * Singleton) to the platform-specific HostLinkBase functionality for use by
106  * platform-specific code.
107  */
108 class HostCommsManager : public HostLink {
109  public:
110   HostCommsManager();
111 
112   /**
113    * Completes a reliable message transaction.
114    *
115    * The callback registered when starting the transaction is called with the
116    * errorCode.
117    *
118    * @param transactionId ID of the transaction to complete.
119    * @param errorCode Error code to pass to the callback.
120    * @return Whether the transaction was completed successfully.
121    */
122   bool completeTransaction(uint32_t transactionId, uint8_t errorCode);
123 
124   /**
125    * Flush (or purge) any messages sent by the given app ID that are currently
126    * pending delivery to the host. At the point that this function is called, it
127    * is guaranteed that no new messages will be generated from this nanoapp.
128    *
129    * This function also flushes any outstanding reliable message transactions
130    * for the associated nanoapp.
131    *
132    * This function must impose strict ordering constraints, such that after it
133    * returns, it is guaranteed that HostCommsManager::onMessageToHostComplete
134    * will not be invoked for the app with the given ID.
135    */
136   void flushNanoappMessagesAndTransactions(uint64_t appId);
137 
138   /**
139    * Invoked by the HostLink platform layer when it is done with a message to
140    * the host: either it successfully sent it, or encountered an error.
141    *
142    * This function is thread-safe.
143    *
144    * @param message A message pointer previously given to HostLink::sendMessage
145    */
146   void onMessageToHostComplete(const MessageToHost *msgToHost);
147 
148   /*
149    * Resets mIsNanoappBlamedForWakeup to false so that
150    * nanoapp->blameHostWakeup() can be called again on next wakeup for one of
151    * the nanoapps.
152    */
153   void resetBlameForNanoappHostWakeup();
154 
155   /**
156    * This function is used by sendMessageToNanoappFromHost() for sending
157    * deferred messages. Messages are deferred when the destination nanoapp is
158    * not yet loaded.
159    *
160    * By the time this function is called through deferCallback, nanoapp load
161    * requests in the queue will have been processed and therefore all nanoapps
162    * are expected to be ready.
163    *
164    * @param craftedMessage Deferred message from host to be delivered to the
165    * destination nanoapp
166    */
167   void sendDeferredMessageToNanoappFromHost(MessageFromHost *craftedMessage);
168 
169   /**
170    * Formulates a MessageToHost using the supplied message contents and
171    * passes it to HostLink for transmission to the host.
172    *
173    * @param nanoapp The sender of this message.
174    * @param messageData Pointer to message payload. Can be null if
175    * messageSize is 0. This buffer must remain valid until freeCallback is
176    * invoked.
177    * @param messageSize Size of the message to send, in bytes
178    * @param messageType Application-defined identifier for the message
179    * @param hostEndpoint Identifier for the entity on the host that should
180    *        receive this message
181    * @param messagePermissions List of Android permissions that cover the
182    *        contents of the message. These permissions are used to record
183    * and attribute access to permissions-controlled resources.
184    * @param freeCallback Optional callback to invoke when the messageData is
185    * no longer needed. The provided callback is only invoked when the return
186    *         value is CHRE_ERROR_NONE.
187    * @param isReliable Whether the message is reliable. The receiver
188    *        acknowledges the delivery of a reliable message by sending a
189    * status back to the sender.
190    * @param cookie The cookie to use when reporting the async status to the
191    *        nanoapp via the CHRE_EVENT_RELIABLE_MSG_ASYNC_STATUS event. Only
192    *        used when isReliable is true.
193    * @return true if the message was accepted into the outbound message
194    * queue. If this function returns false, it does *not* invoke
195    * freeCallback. If it returns true, freeCallback will be invoked (if
196    * non-null) on either success or failure.
197    *
198    * @see chreSendMessageToHost
199    */
200   bool sendMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData,
201                                     size_t messageSize, uint32_t messageType,
202                                     uint16_t hostEndpoint,
203                                     uint32_t messagePermissions,
204                                     chreMessageFreeFunction *freeCallback,
205                                     bool isReliable, const void *cookie);
206 
207   /**
208    * Makes a copy of the supplied message data and posts it to the queue for
209    * later delivery to the addressed nanoapp.
210    *
211    * This function is safe to call from any thread.
212    *
213    * @param appId Identifier for the destination nanoapp
214    * @param messageType Application-defined message identifier
215    * @param hostEndpoint Identifier for the entity on the host that sent this
216    *        message
217    * @param messageData Buffer containing application-specific message data; can
218    *        be null if messageSize is 0
219    * @param messageSize Size of messageData, in bytes
220    * @param isReliable Whether the message is reliable
221    * @param messageSequenceNumber The message sequence number for reliable
222    * messages
223    */
224   void sendMessageToNanoappFromHost(uint64_t appId, uint32_t messageType,
225                                     uint16_t hostEndpoint,
226                                     const void *messageData, size_t messageSize,
227                                     bool isReliable,
228                                     uint32_t messageSequenceNumber);
229 
230  private:
231   //! The data passed to the transaction manager for use with reliable messages.
232   struct MessageTransactionData {
233     uint32_t *messageSequenceNumberPtr;
234     uint32_t messageSequenceNumber;
235     uint16_t nanoappInstanceId;
236     const void *cookie;
237   };
238 
239   //! The maximum number of retries for a reliable message.
240   static constexpr uint16_t kReliableMessageNumRetries = 3;
241 
242   //! The retry wait time for reliable messages.
243   static constexpr Milliseconds kReliableMessageRetryWaitTime =
244       Milliseconds(250);
245 
246   //! The timeout to receive an acknowledgment for a reliable message.
247   static constexpr Seconds kReliableMessageTimeout = Seconds(1);
248 
249   //! The maximum number of messages we can have outstanding at any given time.
250   static constexpr size_t kMaxOutstandingMessages = 32;
251 
252   /**
253    * Allocates and populates the event structure used to notify a nanoapp of an
254    * incoming message from the host.
255    *
256    * Used to implement sendMessageToNanoappFromHost() - see that
257    * function for parameter documentation.
258    *
259    * All parameters must be sanitized before invoking this function.
260    *
261    * @see sendMessageToNanoappFromHost
262    */
263   MessageFromHost *craftNanoappMessageFromHost(
264       uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
265       const void *messageData, uint32_t messageSize, bool isReliable,
266       uint32_t messageSequenceNumber);
267 
268   //! @see TransactionManager::DeferCallback
269   static bool deferCallback(
270       TransactionManager<MessageTransactionData,
271                          kMaxOutstandingMessages>::DeferCallbackFunction func,
272       void *data, void *extraData, Nanoseconds delay, uint32_t *outTimerHandle);
273 
274   /**
275    * Posts a crafted event, craftedMessage, to a nanoapp for processing, and
276    * deallocates it afterwards.
277    *
278    * Used to implement sendMessageToNanoappFromHost() and
279    * sendDeferredMessageToNanoappFromHost(). They allocate and populated the
280    * event using craftNanoappMessageFromHost().
281    *
282    * @param craftedMessage Message from host to be delivered to the destination
283    * nanoapp
284    *
285    * @return true if the message was delivered to the event queue (i.e.
286    *         destination app ID exists in the system)
287    */
288   bool deliverNanoappMessageFromHost(MessageFromHost *craftedMessage);
289 
290   /**
291    * Sends a message to the host from a nanoapp. This method also
292    * appropriately blames the nanoapp for sending a message or
293    * waking up the host. This function assumes both parameters
294    * are non-nullptr.
295    *
296    * @param nanoapp The sender of this message.
297    * @param msgToHost The message to send.
298    *
299    * @return Whether the message was successfully sent.
300    */
301   bool doSendMessageToHostFromNanoapp(Nanoapp *nanoapp,
302                                       MessageToHost *msgToHost);
303 
304   /**
305    * Find the message associated with the message sequence number if it exists.
306    * Returns nullptr other wise.
307    *
308    * @param messageSequenceNumber The message sequence number.
309    * @return The message or nullptr if not found.
310    */
311   HostMessage *findMessageByMessageSequenceNumber(
312       uint32_t messageSequenceNumber);
313 
314   /**
315    * Flushes all the pending reliable message transactions for a nanoapp.
316    *
317    * The completion callback is not called. However,
318    * onMessageToHostCompleteInternal is called for every message removed.
319    *
320    * @param nanoappInstanceId The nanoapp instance ID which
321    * transactions will be flushed.
322    * @return The number of flushed transactions.
323    */
324   size_t flushNanoappTransactions(uint16_t nanoappInstanceId);
325 
326   /**
327    * Releases memory associated with a message to the host, including invoking
328    * the Nanoapp's free callback (if given). Must be called from within the
329    * context of the EventLoop that contains the sending Nanoapp.
330    *
331    * @param msgToHost The message to free
332    */
333   void freeMessageToHost(MessageToHost *msgToHost);
334 
335   /**
336    * Event free callback used to release memory allocated to deliver a message
337    * to a nanoapp from the host.
338    *
339    * @param type Event type
340    * @param data Event data
341    */
342   static void freeMessageFromHostCallback(uint16_t type, void *data);
343 
344   /**
345    * Callback used to send a reliable message.
346    *
347    * @param data The message transaction data.
348    * @return Whether the message was sent successfully.
349    */
350   static bool sendMessageWithTransactionData(MessageTransactionData &data);
351 
352   /**
353    * Called when a reliable message transaction status is reported by the host.
354    *
355    * The status is delivered to the nanoapp that sent the message by posting a
356    * CHRE_EVENT_RELIABLE_MSG_ASYNC_STATUS event.
357    *
358    * @param data The message transaction data.
359    * @param errorCode The errorCode reported by the host from enum chreError.
360    * @return Whether the event was posted successfully.
361    *
362    */
363   static bool onMessageDeliveryStatus(const MessageTransactionData &data,
364                                       uint8_t errorCode);
365 
366   /**
367    * Invoked by onMessageToHostComplete for a non-reliable message
368    * or the TransactionManager for a reliable message when either
369    * are done with a message to the host.
370    *
371    * This function is thread-safe.
372    *
373    * @param message A message pointer previously given to HostLink::sendMessage
374    */
375   void onMessageToHostCompleteInternal(const MessageToHost *msgToHost);
376 
377   //! Ensures that we do not blame more than once per host wakeup. This is
378   //! checked before calling host blame to make sure it is set once. The power
379   //! control managers then reset back to false on host suspend.
380   AtomicBool mIsNanoappBlamedForWakeup{false};
381 
382   //! Memory pool used to allocate message metadata (but not the contents of the
383   //! messages themselves). Must be synchronized as the same HostCommsManager
384   //! handles communications for all EventLoops, and also to support freeing
385   //! messages directly in onMessageToHostComplete.
386   SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool;
387 
388 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
389   //! The transaction manager for reliable messages.
390   TransactionManager<MessageTransactionData, kMaxOutstandingMessages>
391       mTransactionManager;
392 #endif  // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED
393 };
394 
395 }  // namespace chre
396 
397 #endif  // CHRE_CORE_HOST_COMMS_MANAGER_H_
398