aboutsummaryrefslogtreecommitdiff
path: root/core/include/chre/core/host_comms_manager.h
blob: 22956a046be738d11970addc1858ba9151fadaa3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CHRE_CORE_HOST_COMMS_MANAGER_H_
#define CHRE_CORE_HOST_COMMS_MANAGER_H_

#include <cstddef>

#include "chre/core/event_loop.h"
#include "chre/platform/atomic.h"
#include "chre/platform/host_link.h"
#include "chre/util/buffer.h"
#include "chre/util/non_copyable.h"
#include "chre/util/synchronized_memory_pool.h"
#include "chre_api/chre/event.h"

namespace chre {

//! Only valid for messages from host to CHRE - indicates that the sender of the
//! message is not specified.
constexpr uint16_t kHostEndpointUnspecified = CHRE_HOST_ENDPOINT_UNSPECIFIED;

//! Only valid for messages from CHRE to host - delivers the message to all
//! registered clients of the Context Hub HAL, which is the default behavior.
constexpr uint16_t kHostEndpointBroadcast = CHRE_HOST_ENDPOINT_BROADCAST;

/**
 * Data associated with a message either to or from the host.
 */
struct HostMessage : public NonCopyable {
  // This union must be first, as this structure is aliased with
  // chreMessageFromHostData
  union {
    // Fields use when the message was received from the host
    struct chreMessageFromHostData fromHostData;

    // Fields used when the messsage is directed to the host
    struct {
      //! Application-specific message ID
      uint32_t messageType;

      //! Padding used to align this structure with chreMessageFromHostData
      uint32_t reserved;

      //! Message free callback supplied by the nanoapp. Must only be invoked
      //! from the EventLoop where the nanoapp runs.
      chreMessageFreeFunction *nanoappFreeFunction;

      //! Identifier for the host-side entity that should receive this message,
      //! or that which sent it
      uint16_t hostEndpoint;
    } toHostData;
  };

  //! Source/destination nanoapp ID
  uint64_t appId;

  //! Application-defined message data
  Buffer<uint8_t> message;
};

typedef HostMessage MessageFromHost;
typedef HostMessage MessageToHost;

/**
 * Manages bi-directional communications with the host. There must only be one
 * instance of this class per CHRE instance, as the HostLink is not multiplexed
 * per-EventLoop.
 */
class HostCommsManager : public NonCopyable {
 public:
  HostCommsManager() : mIsNanoappBlamedForWakeup(false) {}

  /**
   * @see HostLink::flushMessagesSentByNanoapp
   */
  void flushMessagesSentByNanoapp(uint64_t appId);

  /**
   * Sends a Log Message to the host over the HostLink
   * @see HostLink::sendLogMessage
   *
   * @param logMessage Buffer containing a (possibly encoded) log message
   * @param logMessageSize size in bytes of the logMessage buffer
   */

  void sendLogMessage(const char *logMessage, size_t logMessageSize);

  /**
   * Formulates a MessageToHost using the supplied message contents and passes
   * it to HostLink for transmission to the host.
   *
   * @param nanoapp The sender of this message
   * @param messageData Pointer to message payload. Can be null if messageSize
   *        is 0. This buffer must remain valid until freeCallback is invoked.
   * @param messageSize Size of the message to send, in bytes
   * @param messageType Application-defined identifier for the message
   * @param hostEndpoint Identifier for the entity on the host that should
   *        receive this message
   * @param freeCallback Optional callback to invoke when the messageData is no
   *        longer needed (the message has been sent or an error occurred)
   *
   * @return true if the message was accepted into the outbound message queue.
   *         If this function returns false, it does *not* invoke freeCallback.
   *         If it returns true, freeCallback will be invoked (if non-null) on
   *         either success or failure.
   *
   * @see chreSendMessageToHost
   */
  bool sendMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData,
                                    size_t messageSize, uint32_t messageType,
                                    uint16_t hostEndpoint,
                                    chreMessageFreeFunction *freeCallback);

  /**
   * Makes a copy of the supplied message data and posts it to the queue for
   * later delivery to the addressed nanoapp.
   *
   * This function is safe to call from any thread.
   *
   * @param appId Identifier for the destination nanoapp
   * @param messageType Application-defined message identifier
   * @param hostEndpoint Identifier for the entity on the host that sent this
   *        message
   * @param messageData Buffer containing application-specific message data; can
   *        be null if messageSize is 0
   * @param messageSize Size of messageData, in bytes
   */
  void sendMessageToNanoappFromHost(uint64_t appId, uint32_t messageType,
                                    uint16_t hostEndpoint,
                                    const void *messageData,
                                    size_t messageSize);

  /**
   * This function is used by sendMessageToNanoappFromHost() for sending
   * deferred messages. Messages are deferred when the destination nanoapp is
   * not yet loaded.
   *
   * By the time this function is called through deferCallback, nanoapp load
   * requests in the queue will have been processed and therefore all nanoapps
   * are expected to be ready.
   *
   * @param craftedMessage Deferred message from host to be delivered to the
   * destination nanoapp
   */
  void sendDeferredMessageToNanoappFromHost(MessageFromHost *craftedMessage);

  /*
   * Resets mIsNanoappBlamedForWakeup to false so that
   * nanoapp->blameHostWakeup() can be called again on next wakeup for one of
   * the nanoapps.
   */
  void resetBlameForNanoappHostWakeup();

  /**
   * Invoked by the HostLink platform layer when it is done with a message to
   * the host: either it successfully sent it, or encountered an error.
   *
   * This function is thread-safe.
   *
   * @param message A message pointer previously given to HostLink::sendMessage
   */
  void onMessageToHostComplete(const MessageToHost *msgToHost);

 private:
  //! The maximum number of messages we can have outstanding at any given time
  static constexpr size_t kMaxOutstandingMessages = 32;

  //! Ensures that we do not blame more than once per host wakeup. This is
  //! checked before calling host blame to make sure it is set once. The power
  //! control managers then reset back to false on host suspend.
  AtomicBool mIsNanoappBlamedForWakeup;

  //! Memory pool used to allocate message metadata (but not the contents of the
  //! messages themselves). Must be synchronized as the same HostCommsManager
  //! handles communications for all EventLoops, and also to support freeing
  //! messages directly in onMessageToHostComplete.
  SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool;

  //! The platform-specific link to the host that we manage
  HostLink mHostLink;

  /**
   * Allocates and populates the event structure used to notify a nanoapp of an
   * incoming message from the host.
   *
   * Used to implement sendMessageToNanoappFromHost() - see that
   * function for parameter documentation.
   *
   * All parameters must be sanitized before invoking this function.
   *
   * @see sendMessageToNanoappFromHost
   */
  MessageFromHost *craftNanoappMessageFromHost(uint64_t appId,
                                               uint16_t hostEndpoint,
                                               uint32_t messageType,
                                               const void *messageData,
                                               uint32_t messageSize);

  /**
   * Posts a crafted event, craftedMessage, to a nanoapp for processing, and
   * deallocates it afterwards.
   *
   * Used to implement sendMessageToNanoappFromHost() and
   * sendDeferredMessageToNanoappFromHost(). They allocate and populated the
   * event using craftNanoappMessageFromHost().
   *
   * @param craftedMessage Message from host to be delivered to the destination
   * nanoapp
   */
  bool deliverNanoappMessageFromHost(MessageFromHost *craftedMessage);

  /**
   * Releases memory associated with a message to the host, including invoking
   * the Nanoapp's free callback (if given). Must be called from within the
   * context of the EventLoop that contains the sending Nanoapp.
   *
   * @param msgToHost The message to free
   */
  void freeMessageToHost(MessageToHost *msgToHost);

  /**
   * Event free callback used to release memory allocated to deliver a message
   * to a nanoapp from the host.
   *
   * @param type Event type
   * @param data Event data
   */
  static void freeMessageFromHostCallback(uint16_t type, void *data);
};

}  // namespace chre

#endif  // CHRE_CORE_HOST_COMMS_MANAGER_H_