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_api/chre/event.h"
23 #include "chre/core/event_loop.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 
29 namespace chre {
30 
31 //! Only valid for messages from host to CHRE - indicates that the sender of the
32 //! message is not specified.
33 constexpr uint16_t kHostEndpointUnspecified = CHRE_HOST_ENDPOINT_UNSPECIFIED;
34 
35 //! Only valid for messages from CHRE to host - delivers the message to all
36 //! registered clients of the Context Hub HAL, which is the default behavior.
37 constexpr uint16_t kHostEndpointBroadcast = CHRE_HOST_ENDPOINT_BROADCAST;
38 
39 /**
40  * Data associated with a message either to or from the host.
41  */
42 struct HostMessage : public NonCopyable {
43   // This union must be first, as this structure is aliased with
44   // chreMessageFromHostData
45   union {
46     // Fields use when the message was received from the host
47     struct chreMessageFromHostData fromHostData;
48 
49     // Fields used when the messsage is directed to the host
50     struct {
51       //! Application-specific message ID
52       uint32_t messageType;
53 
54       //! Padding used to align this structure with chreMessageFromHostData
55       uint32_t reserved;
56 
57       //! Message free callback supplied by the nanoapp. Must only be invoked from
58       //! the EventLoop where the nanoapp runs.
59       chreMessageFreeFunction *nanoappFreeFunction;
60 
61       //! Identifier for the host-side entity that should receive this message, or
62       //! that which sent it
63       uint16_t hostEndpoint;
64     } toHostData;
65   };
66 
67   //! Source/destination nanoapp ID
68   uint64_t appId;
69 
70   //! Application-defined message data
71   Buffer<uint8_t> message;
72 };
73 
74 typedef HostMessage MessageFromHost;
75 typedef HostMessage MessageToHost;
76 
77 /**
78  * Manages bi-directional communications with the host. There must only be one
79  * instance of this class per CHRE instance, as the HostLink is not multiplexed
80  * per-EventLoop.
81  */
82 class HostCommsManager : public NonCopyable {
83  public:
84   /**
85    * @see HostLink::flushMessagesSentByNanoapp
86    */
87   void flushMessagesSentByNanoapp(uint64_t appId);
88 
89   /**
90    * Formulates a MessageToHost using the supplied message contents and passes
91    * it to HostLink for transmission to the host.
92    *
93    * @param nanoapp The sender of this message
94    * @param messageData Pointer to message payload. Can be null if messageSize
95    *        is 0. This buffer must remain valid until freeCallback is invoked.
96    * @param messageSize Size of the message to send, in bytes
97    * @param messageType Application-defined identifier for the message
98    * @param hostEndpoint Identifier for the entity on the host that should
99    *        receive this message
100    * @param freeCallback Optional callback to invoke when the messageData is no
101    *        longer needed (the message has been sent or an error occurred)
102    *
103    * @return true if the message was accepted into the outbound message queue.
104    *         If this function returns false, it does *not* invoke freeCallback.
105    *         If it returns true, freeCallback will be invoked (if non-null) on
106    *         either success or failure.
107    *
108    * @see chreSendMessageToHost
109    */
110   bool sendMessageToHostFromNanoapp(
111       Nanoapp *nanoapp, void *messageData, size_t messageSize,
112       uint32_t messageType, uint16_t hostEndpoint,
113       chreMessageFreeFunction *freeCallback);
114 
115   /**
116    * Makes a copy of the supplied message data and posts it to the queue for
117    * later delivery to the addressed nanoapp.
118    *
119    * This function is safe to call from any thread.
120    *
121    * @param appId Identifier for the destination nanoapp
122    * @param messageType Application-defined message identifier
123    * @param hostEndpoint Identifier for the entity on the host that sent this
124    *        message
125    * @param messageData Buffer containing application-specific message data; can
126    *        be null if messageSize is 0
127    * @param messageSize Size of messageData, in bytes
128    */
129   void sendMessageToNanoappFromHost(
130       uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
131       const void *messageData, size_t messageSize);
132 
133   /**
134    * Invoked by the HostLink platform layer when it is done with a message to
135    * the host: either it successfully sent it, or encountered an error.
136    *
137    * This function is thread-safe.
138    *
139    * @param message A message pointer previously given to HostLink::sendMessage
140    */
141   void onMessageToHostComplete(const MessageToHost *msgToHost);
142 
143  private:
144   //! The maximum number of messages we can have outstanding at any given time
145   static constexpr size_t kMaxOutstandingMessages = 32;
146 
147   //! Memory pool used to allocate message metadata (but not the contents of the
148   //! messages themselves). Must be synchronized as the same HostCommsManager
149   //! handles communications for all EventLoops, and also to support freeing
150   //! messages directly in onMessageToHostComplete.
151   SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool;
152 
153   //! The platform-specific link to the host that we manage
154   HostLink mHostLink;
155 
156   /**
157    * Allocates and populates the event structure used to notify a nanoapp of an
158    * incoming message from the host, and posts an event to the nanoapp for
159    * processing. Used to implement sendMessageToNanoappFromHost() - see that
160    * function for parameter documentation.
161    *
162    * All parameters must be sanitized before invoking this function.
163    *
164    * @param targetInstanceId Instance ID of the destination nanoapp
165    *
166    * @see sendMessageToNanoappFromHost
167    */
168   void deliverNanoappMessageFromHost(
169       uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
170       const void *messageData, uint32_t messageSize, uint32_t targetInstanceId);
171 
172   /**
173    * Releases memory associated with a message to the host, including invoking
174    * the Nanoapp's free callback (if given). Must be called from within the
175    * context of the EventLoop that contains the sending Nanoapp.
176    *
177    * @param msgToHost The message to free
178    */
179   void freeMessageToHost(MessageToHost *msgToHost);
180 
181   /**
182    * Event free callback used to release memory allocated to deliver a message
183    * to a nanoapp from the host.
184    *
185    * @param type Event type
186    * @param data Event data
187    */
188   static void freeMessageFromHostCallback(uint16_t type, void *data);
189 };
190 
191 } // namespace chre
192 
193 #endif  // CHRE_CORE_HOST_COMMS_MANAGER_H_
194