blob: d84ceaef6d876241b46be92d9caa786ddaa45927 [file] [log] [blame]
/*
* 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;
/**
* Common code for managing bi-directional communications between the host and
* nanoapps. Inherits from the platform-specific HostLink class to accomplish
* this, and also to provide an access point (lookup via the EventLoopManager
* Singleton) to the platform-specific HostLinkBase functionality for use by
* platform-specific code.
*/
class HostCommsManager : public HostLink {
public:
HostCommsManager() : mIsNanoappBlamedForWakeup(false) {}
/**
* 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);
/**
* @return A reference to the platform's host link implementation giving the
* ability to communicate to the host AP.
*/
HostLink &getHostLink() {
return mHostLink;
}
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;
/**
* 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_