blob: e5e46a2d651753b6d98fc06e239df22a9e0161c4 [file] [log] [blame]
/*
* Copyright (C) 2016 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_EVENT_H_
#define CHRE_CORE_EVENT_H_
#include "chre/core/event_loop_common.h"
#include "chre/platform/assert.h"
#include "chre/util/non_copyable.h"
#include "chre_api/chre/event.h"
#include <cstdint>
namespace chre {
//! Instance ID used for events sent by the system
constexpr uint32_t kSystemInstanceId = 0;
//! Target instance ID used to deliver a message to all nanoapps registered for
//! the event
constexpr uint32_t kBroadcastInstanceId = UINT32_MAX;
//! This value can be used in a nanoapp's own instance ID to indicate that the
//! ID is invalid/not assigned yet
constexpr uint32_t kInvalidInstanceId = kBroadcastInstanceId;
//! Default target group mask that results in the event being sent to any app
//! registered for it.
constexpr uint16_t kDefaultTargetGroupMask = UINT16_MAX;
class Event : public NonCopyable {
public:
Event() = delete;
// Events targeted at nanoapps
Event(uint16_t eventType_, void *eventData_,
chreEventCompleteFunction *freeCallback_,
uint32_t senderInstanceId_ = kSystemInstanceId,
uint32_t targetInstanceId_ = kBroadcastInstanceId,
uint16_t targetAppGroupMask_ = kDefaultTargetGroupMask)
: eventType(eventType_),
receivedTimeMillis(getTimeMillis()),
eventData(eventData_),
freeCallback(freeCallback_),
senderInstanceId(senderInstanceId_),
targetInstanceId(targetInstanceId_),
targetAppGroupMask(targetAppGroupMask_) {
// Sending events to the system must only be done via the other constructor
CHRE_ASSERT(targetInstanceId_ != kSystemInstanceId);
CHRE_ASSERT(targetAppGroupMask_ > 0);
}
// Alternative constructor used for system-internal events (e.g. deferred
// callbacks)
Event(uint16_t eventType_, void *eventData_,
SystemEventCallbackFunction *systemEventCallback_, void *extraData_)
: eventType(eventType_),
receivedTimeMillis(getTimeMillis()),
eventData(eventData_),
systemEventCallback(systemEventCallback_),
extraData(extraData_),
targetInstanceId(kSystemInstanceId),
targetAppGroupMask(kDefaultTargetGroupMask) {
// Posting events to the system must always have a corresponding callback
CHRE_ASSERT(systemEventCallback_ != nullptr);
}
void incrementRefCount() {
mRefCount++;
CHRE_ASSERT(mRefCount != 0);
}
void decrementRefCount() {
CHRE_ASSERT(mRefCount > 0);
mRefCount--;
}
bool isUnreferenced() const {
return (mRefCount == 0);
}
//! @return true if this event has an associated callback which needs to be
//! called prior to deallocating the event
bool hasFreeCallback() {
return (targetInstanceId == kSystemInstanceId || freeCallback != nullptr);
}
/**
* Invoke the callback associated with this event with the applicable function
* signature (passing extraData if this is a system event).
*
* The caller MUST confirm that hasFreeCallback() is true before calling this
* method.
*/
void invokeFreeCallback() {
if (targetInstanceId == kSystemInstanceId) {
systemEventCallback(eventType, eventData, extraData);
} else {
freeCallback(eventType, eventData);
}
}
const uint16_t eventType;
//! This value can serve as a proxy for how fast CHRE is processing events
//! in its queue by substracting the newest event timestamp by the oldest one.
const uint16_t receivedTimeMillis;
void *const eventData;
//! If targetInstanceId is kSystemInstanceId, senderInstanceId is always
//! kSystemInstanceId (nanoapps can't send events to the system), so we
//! utilize that to allow an extra 32 bits of data to be passed to the
//! callback, which can reduce dynamic allocation in several cases. Therefore,
//! if targetInstanceId == kSystemInstanceId, then we use the latter two
//! elements in the following two unions
union {
chreEventCompleteFunction *const freeCallback;
SystemEventCallbackFunction *const systemEventCallback;
};
union {
const uint32_t senderInstanceId;
void *const extraData;
};
const uint32_t targetInstanceId;
// Bitmask that's used to limit the event delivery to some subset of listeners
// registered for this type of event (useful when waking up listeners that can
// have different power considerations). When left as the default value
// (kDefaultTargetGroupMask), this has the same behavior as broadcasting to
// all registered listeners.
const uint16_t targetAppGroupMask;
private:
uint16_t mRefCount = 0;
//! @return Monotonic time reference for initializing receivedTimeMillis
static uint16_t getTimeMillis();
};
} // namespace chre
#endif // CHRE_CORE_EVENT_H_