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