1 /* 2 * Copyright (C) 2016 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_EVENT_H_ 18 #define CHRE_CORE_EVENT_H_ 19 20 #include "chre/core/event_loop_common.h" 21 #include "chre/platform/assert.h" 22 #include "chre/util/non_copyable.h" 23 #include "chre_api/chre/event.h" 24 25 #include <cstdint> 26 27 namespace chre { 28 29 //! Instance ID used for events sent by the system 30 constexpr uint16_t kSystemInstanceId = 0; 31 32 //! Target instance ID used to deliver a message to all nanoapps registered for 33 //! the event 34 constexpr uint16_t kBroadcastInstanceId = UINT16_MAX; 35 36 //! This value can be used in a nanoapp's own instance ID to indicate that the 37 //! ID is invalid/not assigned yet 38 constexpr uint16_t kInvalidInstanceId = kBroadcastInstanceId; 39 40 //! Default target group mask that results in the event being sent to any app 41 //! registered for it. 42 constexpr uint16_t kDefaultTargetGroupMask = UINT16_MAX; 43 44 class Event : public NonCopyable { 45 public: 46 Event() = delete; 47 48 // Events targeted at nanoapps 49 Event(uint16_t eventType_, void *eventData_, 50 chreEventCompleteFunction *freeCallback_, bool isLowPriority_, 51 uint16_t senderInstanceId_ = kSystemInstanceId, 52 uint16_t targetInstanceId_ = kBroadcastInstanceId, 53 uint16_t targetAppGroupMask_ = kDefaultTargetGroupMask) eventType(eventType_)54 : eventType(eventType_), 55 receivedTimeMillis(getTimeMillis()), 56 eventData(eventData_), 57 freeCallback(freeCallback_), 58 senderInstanceId(senderInstanceId_), 59 targetInstanceId(targetInstanceId_), 60 targetAppGroupMask(targetAppGroupMask_), 61 isLowPriority(isLowPriority_) { 62 // Sending events to the system must only be done via the other constructor 63 CHRE_ASSERT(targetInstanceId_ != kSystemInstanceId); 64 CHRE_ASSERT(targetAppGroupMask_ > 0); 65 } 66 67 // Alternative constructor used for system-internal events (e.g. deferred 68 // callbacks) Event(uint16_t eventType_,void * eventData_,SystemEventCallbackFunction * systemEventCallback_,void * extraData_)69 Event(uint16_t eventType_, void *eventData_, 70 SystemEventCallbackFunction *systemEventCallback_, void *extraData_) 71 : eventType(eventType_), 72 receivedTimeMillis(getTimeMillis()), 73 eventData(eventData_), 74 systemEventCallback(systemEventCallback_), 75 extraData(extraData_), 76 targetInstanceId(kSystemInstanceId), 77 targetAppGroupMask(kDefaultTargetGroupMask), 78 isLowPriority(false) { 79 // Posting events to the system must always have a corresponding callback 80 CHRE_ASSERT(systemEventCallback_ != nullptr); 81 } 82 incrementRefCount()83 void incrementRefCount() { 84 mRefCount++; 85 CHRE_ASSERT(mRefCount != 0); 86 } 87 decrementRefCount()88 void decrementRefCount() { 89 CHRE_ASSERT(mRefCount > 0); 90 mRefCount--; 91 } 92 isUnreferenced()93 bool isUnreferenced() const { 94 return (mRefCount == 0); 95 } 96 97 //! @return true if this event has an associated callback which needs to be 98 //! called prior to deallocating the event hasFreeCallback()99 bool hasFreeCallback() { 100 return (targetInstanceId == kSystemInstanceId || freeCallback != nullptr); 101 } 102 103 /** 104 * Invoke the callback associated with this event with the applicable function 105 * signature (passing extraData if this is a system event). 106 * 107 * The caller MUST confirm that hasFreeCallback() is true before calling this 108 * method. 109 */ invokeFreeCallback()110 void invokeFreeCallback() { 111 if (targetInstanceId == kSystemInstanceId) { 112 systemEventCallback(eventType, eventData, extraData); 113 } else { 114 freeCallback(eventType, eventData); 115 } 116 } 117 118 const uint16_t eventType; 119 120 //! This value can serve as a proxy for how fast CHRE is processing events 121 //! in its queue by substracting the newest event timestamp by the oldest one. 122 const uint16_t receivedTimeMillis; 123 void *const eventData; 124 125 //! If targetInstanceId is kSystemInstanceId, senderInstanceId is always 126 //! kSystemInstanceId (nanoapps can't send events to the system), so we 127 //! utilize that to allow an extra 32 bits of data to be passed to the 128 //! callback, which can reduce dynamic allocation in several cases. Therefore, 129 //! if targetInstanceId == kSystemInstanceId, then we use the latter two 130 //! elements in the following two unions 131 union { 132 chreEventCompleteFunction *const freeCallback; 133 SystemEventCallbackFunction *const systemEventCallback; 134 }; 135 union { 136 const uint16_t senderInstanceId; 137 void *const extraData; 138 }; 139 const uint16_t targetInstanceId; 140 141 // Bitmask that's used to limit the event delivery to some subset of listeners 142 // registered for this type of event (useful when waking up listeners that can 143 // have different power considerations). When left as the default value 144 // (kDefaultTargetGroupMask), this has the same behavior as broadcasting to 145 // all registered listeners. 146 const uint16_t targetAppGroupMask; 147 148 const bool isLowPriority; 149 150 private: 151 uint8_t mRefCount = 0; 152 153 //! @return Monotonic time reference for initializing receivedTimeMillis 154 static uint16_t getTimeMillis(); 155 }; 156 157 } // namespace chre 158 159 #endif // CHRE_CORE_EVENT_H_ 160