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 #include <cstdint> 22 23 #include "chre/core/nanoapp.h" 24 #include "chre/core/timer_pool.h" 25 #include "chre/platform/atomic.h" 26 #include "chre/platform/host_link.h" 27 #include "chre/util/buffer.h" 28 #include "chre/util/duplicate_message_detector.h" 29 #include "chre/util/non_copyable.h" 30 #include "chre/util/system/synchronized_memory_pool.h" 31 #include "chre/util/system/transaction_manager.h" 32 #include "chre/util/time.h" 33 #include "chre_api/chre/event.h" 34 35 namespace chre { 36 37 //! Only valid for messages from host to CHRE - indicates that the sender of the 38 //! message is not specified. 39 constexpr uint16_t kHostEndpointUnspecified = CHRE_HOST_ENDPOINT_UNSPECIFIED; 40 41 //! Only valid for messages from CHRE to host - delivers the message to all 42 //! registered clients of the Context Hub HAL, which is the default behavior. 43 constexpr uint16_t kHostEndpointBroadcast = CHRE_HOST_ENDPOINT_BROADCAST; 44 45 /** 46 * Data associated with a message either to or from the host. 47 */ 48 struct HostMessage : public NonCopyable { 49 // This union must be first, as this structure is aliased with 50 // chreMessageFromHostData 51 union { 52 // Fields use when the message was received from the host 53 struct chreMessageFromHostData fromHostData; 54 55 // Fields used when the messsage is directed to the host 56 struct { 57 //! Application-specific message ID 58 uint32_t messageType; 59 60 //! List of Android permissions declared by the nanoapp. This must be a 61 //! superset of messagePermissions. 62 uint32_t appPermissions; 63 64 //! List of Android permissions that cover the contents of the message. 65 //! These permissions are used to record and attribute access to 66 //! permissions-controlled resources. 67 //! Note that these permissions must always be a subset of uint32_t 68 //! permissions. Otherwise, the message will be dropped. 69 uint32_t messagePermissions; 70 71 //! Message free callback supplied by the nanoapp. Must only be invoked 72 //! from the EventLoop where the nanoapp runs. 73 chreMessageFreeFunction *nanoappFreeFunction; 74 75 //! Identifier for the host-side entity that should receive this message. 76 uint16_t hostEndpoint; 77 78 //! true if this message resulted in the host transitioning from suspend 79 //! to awake. 80 bool wokeHost; 81 } toHostData; 82 }; 83 84 //! Distinguishes whether this is a message from the host or to the host, 85 //! which dictates whether fromHostData or toHostData are used. 86 bool fromHost; 87 88 //! Whether the message is reliable. 89 //! Reliable messages are acknowledge by sending with a status containing 90 //! the transaction ID. 91 bool isReliable; 92 93 //! Used to report reliable message status back to the sender. 94 uint32_t messageSequenceNumber; 95 96 //! Opaque nanoapp-supplied cookie associated with reliable messages. 97 const void *cookie; 98 99 //! Source/destination nanoapp ID. 100 uint64_t appId; 101 102 //! Application-defined message data. 103 Buffer<uint8_t> message; 104 }; 105 106 typedef HostMessage MessageFromHost; 107 typedef HostMessage MessageToHost; 108 109 /** 110 * Common code for managing bi-directional communications between the host and 111 * nanoapps. Inherits from the platform-specific HostLink class to accomplish 112 * this, and also to provide an access point (lookup via the EventLoopManager 113 * Singleton) to the platform-specific HostLinkBase functionality for use by 114 * platform-specific code. 115 */ 116 class HostCommsManager : public HostLink, private TransactionManagerCallback { 117 public: 118 HostCommsManager(); 119 120 /** 121 * Completes a reliable message transaction. 122 * 123 * The callback registered when starting the transaction is called with the 124 * errorCode. 125 * 126 * @param transactionId ID of the transaction to complete. 127 * @param errorCode Error code to pass to the callback. 128 * @return Whether the transaction was completed successfully. 129 */ 130 bool completeTransaction(uint32_t transactionId, uint8_t errorCode); 131 132 /** 133 * Flush (or purge) any messages sent by the given app ID that are currently 134 * pending delivery to the host. At the point that this function is called, it 135 * is guaranteed that no new messages will be generated from this nanoapp. 136 * 137 * This function also flushes any outstanding reliable message transactions, 138 * by ensuring at least one attempt to send to the host is made, and not 139 * providing a message delivery status event to the nanoapp. 140 * 141 * This function must impose strict ordering constraints, such that after it 142 * returns, it is guaranteed that HostCommsManager::onMessageToHostComplete 143 * will not be invoked for the app with the given ID. 144 */ 145 void flushNanoappMessages(Nanoapp &nanoapp); 146 147 /** 148 * Invoked by the HostLink platform layer when it is done with a message to 149 * the host: either it successfully sent it, or encountered an error. 150 * 151 * This function is thread-safe. 152 * 153 * @param message A message pointer previously given to HostLink::sendMessage 154 */ 155 void onMessageToHostComplete(const MessageToHost *msgToHost); 156 157 /* 158 * Resets mIsNanoappBlamedForWakeup to false so that 159 * nanoapp->blameHostWakeup() can be called again on next wakeup for one of 160 * the nanoapps. 161 */ 162 void resetBlameForNanoappHostWakeup(); 163 164 /** 165 * Formulates a MessageToHost using the supplied message contents and 166 * passes it to HostLink for transmission to the host. 167 * 168 * @param nanoapp The sender of this message. 169 * @param messageData Pointer to message payload. Can be null if 170 * messageSize is 0. This buffer must remain valid until freeCallback is 171 * invoked. 172 * @param messageSize Size of the message to send, in bytes 173 * @param messageType Application-defined identifier for the message 174 * @param hostEndpoint Identifier for the entity on the host that should 175 * receive this message 176 * @param messagePermissions List of Android permissions that cover the 177 * contents of the message. These permissions are used to record 178 * and attribute access to permissions-controlled resources. 179 * @param freeCallback Optional callback to invoke when the messageData is 180 * no longer needed. The provided callback is only invoked when the return 181 * value is CHRE_ERROR_NONE. 182 * @param isReliable Whether the message is reliable. The receiver 183 * acknowledges the delivery of a reliable message by sending a 184 * status back to the sender. 185 * @param cookie The cookie to use when reporting the async status to the 186 * nanoapp via the CHRE_EVENT_RELIABLE_MSG_ASYNC_STATUS event. Only 187 * used when isReliable is true. 188 * @return true if the message was accepted into the outbound message 189 * queue. If this function returns false, it does *not* invoke 190 * freeCallback. If it returns true, freeCallback will be invoked (if 191 * non-null) on either success or failure. 192 * 193 * @see chreSendMessageToHost 194 */ 195 bool sendMessageToHostFromNanoapp(Nanoapp *nanoapp, void *messageData, 196 size_t messageSize, uint32_t messageType, 197 uint16_t hostEndpoint, 198 uint32_t messagePermissions, 199 chreMessageFreeFunction *freeCallback, 200 bool isReliable, const void *cookie); 201 202 /** 203 * Makes a copy of the supplied message data and posts it to the queue for 204 * later delivery to the addressed nanoapp. 205 * 206 * This function is safe to call from any thread. 207 * 208 * @param appId Identifier for the destination nanoapp 209 * @param messageType Application-defined message identifier 210 * @param hostEndpoint Identifier for the entity on the host that sent this 211 * message 212 * @param messageData Buffer containing application-specific message data; can 213 * be null if messageSize is 0 214 * @param messageSize Size of messageData, in bytes 215 * @param isReliable Whether the message is reliable 216 * @param messageSequenceNumber The message sequence number for reliable 217 * messages 218 */ 219 void sendMessageToNanoappFromHost(uint64_t appId, uint32_t messageType, 220 uint16_t hostEndpoint, 221 const void *messageData, size_t messageSize, 222 bool isReliable, 223 uint32_t messageSequenceNumber); 224 225 private: 226 //! How many times we'll try sending a reliable message before giving up. 227 static constexpr uint16_t kReliableMessageMaxAttempts = 4; 228 229 //! How long we'll wait after sending a reliable message which doesn't receive 230 //! an ACK before trying again. 231 static constexpr Milliseconds kReliableMessageRetryWaitTime = 232 Milliseconds(250); 233 234 //! How long we'll wait before timing out a reliable message. 235 static constexpr Nanoseconds kReliableMessageTimeout = 236 kReliableMessageRetryWaitTime * kReliableMessageMaxAttempts; 237 238 //! How long we'll wait before removing a duplicate message record from the 239 //! duplicate message detector. 240 static constexpr Nanoseconds kReliableMessageDuplicateDetectorTimeout = 241 kReliableMessageTimeout * 3; 242 243 //! The maximum number of messages we can have outstanding at any given time. 244 static constexpr size_t kMaxOutstandingMessages = 32; 245 246 //! Ensures that we do not blame more than once per host wakeup. This is 247 //! checked before calling host blame to make sure it is set once. The power 248 //! control managers then reset back to false on host suspend. 249 AtomicBool mIsNanoappBlamedForWakeup{false}; 250 251 //! Memory pool used to allocate message metadata (but not the contents of the 252 //! messages themselves). Must be synchronized as the same HostCommsManager 253 //! handles communications for all EventLoops, and also to support freeing 254 //! messages directly in onMessageToHostComplete. 255 SynchronizedMemoryPool<HostMessage, kMaxOutstandingMessages> mMessagePool; 256 257 #ifdef CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED 258 //! The duplicate message detector for reliable messages. 259 DuplicateMessageDetector mDuplicateMessageDetector; 260 261 //! The transaction manager for reliable messages. 262 TransactionManager<kMaxOutstandingMessages, TimerPool> mTransactionManager; 263 #endif // CHRE_RELIABLE_MESSAGE_SUPPORT_ENABLED 264 265 /** 266 * Allocates and populates the event structure used to notify a nanoapp of an 267 * incoming message from the host. 268 * 269 * Used to implement sendMessageToNanoappFromHost() - see that 270 * function for parameter documentation. 271 * 272 * All parameters must be sanitized before invoking this function. 273 * 274 * @see sendMessageToNanoappFromHost 275 */ 276 MessageFromHost *craftNanoappMessageFromHost( 277 uint64_t appId, uint16_t hostEndpoint, uint32_t messageType, 278 const void *messageData, uint32_t messageSize, bool isReliable, 279 uint32_t messageSequenceNumber); 280 281 /** 282 * Checks if the message could be sent to the nanoapp from the host. Crafts 283 * the message to the nanoapp. 284 * 285 * @see sendMessageToNanoappFromHost for a description of the parameters. 286 * 287 * @return the error code and the crafted message. The message is dynamically 288 * allocated and must be freed by the caller. 289 */ 290 std::pair<chreError, MessageFromHost *> 291 validateAndCraftMessageFromHostToNanoapp(uint64_t appId, uint32_t messageType, 292 uint16_t hostEndpoint, 293 const void *messageData, 294 size_t messageSize, bool isReliable, 295 uint32_t messageSequenceNumber); 296 297 /** 298 * Posts a crafted event, craftedMessage, to a nanoapp for processing, and 299 * deallocates it afterwards. 300 * 301 * Used to implement sendMessageToNanoappFromHost(). It allocates and 302 * populates the event using craftNanoappMessageFromHost(). 303 * 304 * @param craftedMessage Message from host to be delivered to the 305 * destination nanoapp 306 */ 307 void deliverNanoappMessageFromHost(MessageFromHost *craftedMessage); 308 309 /** 310 * Sends a message to the host from a nanoapp. This method also 311 * appropriately blames the nanoapp for sending a message or 312 * waking up the host. This function assumes both parameters 313 * are non-nullptr. 314 * 315 * @param nanoapp The sender of this message. 316 * @param msgToHost The message to send. 317 * 318 * @return Whether the message was successfully sent. 319 */ 320 bool doSendMessageToHostFromNanoapp(Nanoapp *nanoapp, 321 MessageToHost *msgToHost); 322 323 /** 324 * Find the message to the host associated with the message sequence number, 325 * if it exists. Returns nullptr otherwise. 326 * 327 * @param messageSequenceNumber The message sequence number. 328 * @return The message or nullptr if not found. 329 */ 330 MessageToHost *findMessageToHostBySeq(uint32_t messageSequenceNumber); 331 332 /** 333 * Releases memory associated with a message to the host, including invoking 334 * the Nanoapp's free callback (if given). Must be called from within the 335 * context of the EventLoop that contains the sending Nanoapp. 336 * 337 * @param msgToHost The message to free 338 */ 339 void freeMessageToHost(MessageToHost *msgToHost); 340 341 /** 342 * Callback used to send a reliable message. 343 * @see TransactionManagerCallback 344 */ 345 void onTransactionAttempt(uint32_t messageSequenceNumber, 346 uint16_t nanoappInstanceId) final; 347 348 /** 349 * Callback invoked when a transaction has timed out after the maximum 350 * number of retries. 351 * @see TransactionManagerCallback 352 */ 353 void onTransactionFailure(uint32_t messageSequenceNumber, 354 uint16_t nanoappInstanceId) final; 355 356 /** 357 * Handles a duplicate message from the host by setting the error in the 358 * duplicate message detector and sends a message delivery status to the 359 * nanoapp. 360 * 361 * @param messageSequenceNumber The message sequence number. 362 * @param hostEndpoint The host endpoint. 363 * @param error The error from sending the message to the nanoapp. 364 */ 365 void handleDuplicateAndSendMessageDeliveryStatus( 366 uint32_t messageSequenceNumber, uint16_t hostEndpoint, chreError error); 367 368 /** 369 * Called when a reliable message transaction status is reported by the 370 * host. 371 * 372 * The status is delivered to the nanoapp that sent the message by posting a 373 * CHRE_EVENT_RELIABLE_MSG_ASYNC_STATUS event. 374 * 375 * @param data The message transaction data. 376 * @param errorCode The errorCode reported by the host from enum chreError. 377 * @return Whether the event was posted successfully. 378 * 379 */ 380 void handleMessageDeliveryStatusSync(uint32_t messageSequenceNumber, 381 uint8_t errorCode); 382 383 /** 384 * Invoked by onMessageToHostComplete for a non-reliable message 385 * or the TransactionManager for a reliable message when either 386 * are done with a message to the host. 387 * 388 * This function is thread-safe. 389 * 390 * @param message A message pointer previously given to 391 * HostLink::sendMessage 392 */ 393 void onMessageToHostCompleteInternal(const MessageToHost *msgToHost); 394 395 /** 396 * Calls TransactionManager::remove for all pending reliable messages sent 397 * by this nanoapp, normally used as part of nanoapp unload flow. 398 */ 399 void removeAllTransactionsFromNanoapp(const Nanoapp &nanoapp); 400 401 /** 402 * Releases memory for all pending reliable messages sent by this nanoapp. 403 * The data must have already been flushed through HostLink, and the 404 * transactions must have already been cleaned up. 405 */ 406 void freeAllReliableMessagesFromNanoapp(Nanoapp &nanoapp); 407 408 /** 409 * Returns whether to send the reliable message to the nanoapp. This 410 * function returns true, indicating to the caller to send the message, when 411 * the message is not a duplicate or when the duplicate message was sent 412 * previously with a transient error. When this function returns false, the 413 * error is sent to the host using sendMessageDeliveryStatus. 414 * 415 * @param messageSequenceNumber The message sequence number. 416 * @param hostEndpoint The host endpoint. 417 * @return Whether to send the message to the nanoapp. 418 */ 419 bool shouldSendReliableMessageToNanoapp(uint32_t messageSequenceNumber, 420 uint16_t hostEndpoint); 421 }; 422 423 } // namespace chre 424 425 #endif // CHRE_CORE_HOST_COMMS_MANAGER_H_ 426