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