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/dynamic_vector.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   DynamicVector<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    * Formulates a MessageToHost using the supplied message contents and passes
86    * it to HostLink for transmission to the host.
87    *
88    * @param messageData Pointer to message payload. Can be null if messageSize
89    *        is 0. This buffer must remain valid until freeCallback is invoked.
90    * @param messageSize Size of the message to send, in bytes
91    * @param messageType Application-defined identifier for the message
92    * @param hostEndpoint Identifier for the entity on the host that should
93    *        receive this message
94    * @param freeCallback Optional callback to invoke when the messageData is no
95    *        longer needed (the message has been sent or an error occurred)
96    *
97    * @return true if the message was accepted into the outbound message queue
98    *
99    * @see chreSendMessageToHost
100    */
101   bool sendMessageToHostFromCurrentNanoapp(
102       void *messageData, size_t messageSize, uint32_t messageType,
103       uint16_t hostEndpoint, chreMessageFreeFunction *freeCallback);
104 
105   /**
106    * Makes a copy of the supplied message data and posts it to the queue for
107    * later delivery to the addressed nanoapp.
108    *
109    * This function is safe to call from any thread.
110    *
111    * @param appId Identifier for the destination nanoapp
112    * @param messageType Application-defined message identifier
113    * @param hostEndpoint Identifier for the entity on the host that sent this
114    *        message
115    * @param messageData Buffer containing application-specific message data; can
116    *        be null if messageSize is 0
117    * @param messageSize Size of messageData, in bytes
118    */
119   void sendMessageToNanoappFromHost(
120       uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
121       const void *messageData, size_t messageSize);
122 
123   /**
124    * Invoked by the HostLink platform layer when it is done with a message to
125    * the host: either it successfully sent it, or encountered an error.
126    *
127    * This function is thread-safe.
128    *
129    * @param message A message pointer previously given to HostLink::sendMessage
130    */
131   void onMessageToHostComplete(const MessageToHost *msgToHost);
132 
133  private:
134   //! The maximum number of messages we can have outstanding at any given time
135   static constexpr size_t kMaxOutstandingMessages = 32;
136 
137   //! Memory pool used to allocate message metadata (but not the contents of the
138   //! messages themselves). Must be synchronized as the same HostCommsManager
139   //! handles communications for all EventLoops, and also to support freeing
140   //! messages directly in onMessageToHostComplete.
141   SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool;
142 
143   //! The platform-specific link to the host that we manage
144   HostLink mHostLink;
145 
146   /**
147    * Allocates and populates the event structure used to notify a nanoapp of an
148    * incoming message from the host, and posts an event to the nanoapp for
149    * processing. Used to implement sendMessageToNanoappFromHost() - see that
150    * function for parameter documentation.
151    *
152    * All parameters must be sanitized before invoking this function.
153    *
154    * @param targetEventLoop EventLoop containing the target app
155    * @param targetInstanceId Instance ID of the destination nanoapp
156    *
157    * @see sendMessageToNanoappFromHost
158    */
159   void deliverNanoappMessageFromHost(
160       uint64_t appId, uint16_t hostEndpoint, uint32_t messageType,
161       const void *messageData, uint32_t messageSize, EventLoop *targetEventLoop,
162       uint32_t targetInstanceId);
163 
164   /**
165    * Releases memory associated with a message to the host, including invoking
166    * the Nanoapp's free callback (if given). Must be called from within the
167    * context of the EventLoop that contains the sending Nanoapp.
168    *
169    * @param msgToHost The message to free
170    */
171   void freeMessageToHost(MessageToHost *msgToHost);
172 
173   /**
174    * Event free callback used to release memory allocated to deliver a message
175    * to a nanoapp from the host.
176    *
177    * @param type Event type
178    * @param data Event data
179    */
180   static void freeMessageFromHostCallback(uint16_t type, void *data);
181 };
182 
183 } // namespace chre
184 
185 #endif  // CHRE_CORE_HOST_COMMS_MANAGER_H_
186