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