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 
22 #include "chre/core/event_loop.h"
23 #include "chre/platform/atomic.h"
24 #include "chre/platform/host_link.h"
25 #include "chre/util/buffer.h"
26 #include "chre/util/non_copyable.h"
27 #include "chre/util/synchronized_memory_pool.h"
28 #include "chre_api/chre/event.h"
29 
30 namespace chre {
31 
32 //! Only valid for messages from host to CHRE - indicates that the sender of the
33 //! message is not specified.
34 constexpr uint16_t kHostEndpointUnspecified = CHRE_HOST_ENDPOINT_UNSPECIFIED;
35 
36 //! Only valid for messages from CHRE to host - delivers the message to all
37 //! registered clients of the Context Hub HAL, which is the default behavior.
38 constexpr uint16_t kHostEndpointBroadcast = CHRE_HOST_ENDPOINT_BROADCAST;
39 
40 /**
41  * Data associated with a message either to or from the host.
42  */
43 struct HostMessage : public NonCopyable {
44   // This union must be first, as this structure is aliased with
45   // chreMessageFromHostData
46   union {
47     // Fields use when the message was received from the host
48     struct chreMessageFromHostData fromHostData;
49 
50     // Fields used when the messsage is directed to the host
51     struct {
52       //! Application-specific message ID
53       uint32_t messageType;
54 
55       //! List of Android permissions declared by the nanoapp. This must be a
56       //! superset of messagePermissions.
57       uint32_t appPermissions;
58 
59       //! List of Android permissions that cover the contents of the message.
60       //! These permissions are used to record and attribute access to
61       //! permissions-controlled resources.
62       //! Note that these permissions must always be a subset of uint32_t
63       //! permissions. Otherwise, the message will be dropped.
64       uint32_t messagePermissions;
65 
66       //! Message free callback supplied by the nanoapp. Must only be invoked
67       //! from the EventLoop where the nanoapp runs.
68       chreMessageFreeFunction *nanoappFreeFunction;
69 
70       //! Identifier for the host-side entity that should receive this message,
71       //! or that which sent it
72       uint16_t hostEndpoint;
73     } toHostData;
74   };
75 
76   //! Source/destination nanoapp ID
77   uint64_t appId;
78 
79   //! Application-defined message data
80   Buffer<uint8_t> message;
81 };
82 
83 typedef HostMessage MessageFromHost;
84 typedef HostMessage MessageToHost;
85 
86 /**
87  * Common code for managing bi-directional communications between the host and
88  * nanoapps. Inherits from the platform-specific HostLink class to accomplish
89  * this, and also to provide an access point (lookup via the EventLoopManager
90  * Singleton) to the platform-specific HostLinkBase functionality for use by
91  * platform-specific code.
92  */
93 class HostCommsManager : public HostLink {
94  public:
HostCommsManager()95   HostCommsManager() : mIsNanoappBlamedForWakeup(false) {}
96 
97   /**
98    * Formulates a MessageToHost using the supplied message contents and passes
99    * it to HostLink for transmission to the host.
100    *
101    * @param nanoapp The sender of this message
102    * @param messageData Pointer to message payload. Can be null if messageSize
103    *        is 0. This buffer must remain valid until freeCallback is invoked.
104    * @param messageSize Size of the message to send, in bytes
105    * @param messageType Application-defined identifier for the message
106    * @param hostEndpoint Identifier for the entity on the host that should
107    *        receive this message
108    * @param freeCallback Optional callback to invoke when the messageData is no
109    *        longer needed (the message has been sent or an error occurred)
110    * @param messagePermissions List of Android permissions that cover the
111    *        contents of the message. These permissions are used to record and
112    *        attribute access to permissions-controlled resources.
113    *
114    * @return true if the message was accepted into the outbound message queue.
115    *         If this function returns false, it does *not* invoke freeCallback.
116    *         If it returns true, freeCallback will be invoked (if non-null) on
117    *         either success or failure.
118    *
119    * @see chreSendMessageToHost
120    */
121   bool sendMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData,
122                                     size_t messageSize, uint32_t messageType,
123                                     uint16_t hostEndpoint,
124                                     uint32_t messagePermissions,
125                                     chreMessageFreeFunction *freeCallback);
126 
127   /**
128    * Makes a copy of the supplied message data and posts it to the queue for
129    * later delivery to the addressed nanoapp.
130    *
131    * This function is safe to call from any thread.
132    *
133    * @param appId Identifier for the destination nanoapp
134    * @param messageType Application-defined message identifier
135    * @param hostEndpoint Identifier for the entity on the host that sent this
136    *        message
137    * @param messageData Buffer containing application-specific message data; can
138    *        be null if messageSize is 0
139    * @param messageSize Size of messageData, in bytes
140    */
141   void sendMessageToNanoappFromHost(uint64_t appId, uint32_t messageType,
142                                     uint16_t hostEndpoint,
143                                     const void *messageData,
144                                     size_t messageSize);
145 
146   /**
147    * This function is used by sendMessageToNanoappFromHost() for sending
148    * deferred messages. Messages are deferred when the destination nanoapp is
149    * not yet loaded.
150    *
151    * By the time this function is called through deferCallback, nanoapp load
152    * requests in the queue will have been processed and therefore all nanoapps
153    * are expected to be ready.
154    *
155    * @param craftedMessage Deferred message from host to be delivered to the
156    * destination nanoapp
157    */
158   void sendDeferredMessageToNanoappFromHost(MessageFromHost *craftedMessage);
159 
160   /*
161    * Resets mIsNanoappBlamedForWakeup to false so that
162    * nanoapp->blameHostWakeup() can be called again on next wakeup for one of
163    * the nanoapps.
164    */
165   void resetBlameForNanoappHostWakeup();
166 
167   /**
168    * Invoked by the HostLink platform layer when it is done with a message to
169    * the host: either it successfully sent it, or encountered an error.
170    *
171    * This function is thread-safe.
172    *
173    * @param message A message pointer previously given to HostLink::sendMessage
174    */
175   void onMessageToHostComplete(const MessageToHost *msgToHost);
176 
177  private:
178   //! The maximum number of messages we can have outstanding at any given time
179   static constexpr size_t kMaxOutstandingMessages = 32;
180 
181   //! Ensures that we do not blame more than once per host wakeup. This is
182   //! checked before calling host blame to make sure it is set once. The power
183   //! control managers then reset back to false on host suspend.
184   AtomicBool mIsNanoappBlamedForWakeup;
185 
186   //! Memory pool used to allocate message metadata (but not the contents of the
187   //! messages themselves). Must be synchronized as the same HostCommsManager
188   //! handles communications for all EventLoops, and also to support freeing
189   //! messages directly in onMessageToHostComplete.
190   SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool;
191 
192   /**
193    * Allocates and populates the event structure used to notify a nanoapp of an
194    * incoming message from the host.
195    *
196    * Used to implement sendMessageToNanoappFromHost() - see that
197    * function for parameter documentation.
198    *
199    * All parameters must be sanitized before invoking this function.
200    *
201    * @see sendMessageToNanoappFromHost
202    */
203   MessageFromHost *craftNanoappMessageFromHost(uint64_t appId,
204                                                uint16_t hostEndpoint,
205                                                uint32_t messageType,
206                                                const void *messageData,
207                                                uint32_t messageSize);
208 
209   /**
210    * Posts a crafted event, craftedMessage, to a nanoapp for processing, and
211    * deallocates it afterwards.
212    *
213    * Used to implement sendMessageToNanoappFromHost() and
214    * sendDeferredMessageToNanoappFromHost(). They allocate and populated the
215    * event using craftNanoappMessageFromHost().
216    *
217    * @param craftedMessage Message from host to be delivered to the destination
218    * nanoapp
219    *
220    * @return true if the message was delivered to the event queue (i.e.
221    *         destination app ID exists in the system)
222    */
223   bool deliverNanoappMessageFromHost(MessageFromHost *craftedMessage);
224 
225   /**
226    * Releases memory associated with a message to the host, including invoking
227    * the Nanoapp's free callback (if given). Must be called from within the
228    * context of the EventLoop that contains the sending Nanoapp.
229    *
230    * @param msgToHost The message to free
231    */
232   void freeMessageToHost(MessageToHost *msgToHost);
233 
234   /**
235    * Event free callback used to release memory allocated to deliver a message
236    * to a nanoapp from the host.
237    *
238    * @param type Event type
239    * @param data Event data
240    */
241   static void freeMessageFromHostCallback(uint16_t type, void *data);
242 };
243 
244 }  // namespace chre
245 
246 #endif  // CHRE_CORE_HOST_COMMS_MANAGER_H_
247