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 uint32_t kSystemInstanceId = 0;
31 
32 //! Target instance ID used to deliver a message to all nanoapps registered for
33 //! the event
34 constexpr uint32_t kBroadcastInstanceId = UINT32_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 uint32_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_,
51         uint32_t senderInstanceId_ = kSystemInstanceId,
52         uint32_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     // Sending events to the system must only be done via the other constructor
62     CHRE_ASSERT(targetInstanceId_ != kSystemInstanceId);
63     CHRE_ASSERT(targetAppGroupMask_ > 0);
64   }
65 
66   // Alternative constructor used for system-internal events (e.g. deferred
67   // callbacks)
Event(uint16_t eventType_,void * eventData_,SystemEventCallbackFunction * systemEventCallback_,void * extraData_)68   Event(uint16_t eventType_, void *eventData_,
69         SystemEventCallbackFunction *systemEventCallback_, void *extraData_)
70       : eventType(eventType_),
71         receivedTimeMillis(getTimeMillis()),
72         eventData(eventData_),
73         systemEventCallback(systemEventCallback_),
74         extraData(extraData_),
75         targetInstanceId(kSystemInstanceId),
76         targetAppGroupMask(kDefaultTargetGroupMask) {
77     // Posting events to the system must always have a corresponding callback
78     CHRE_ASSERT(systemEventCallback_ != nullptr);
79   }
80 
incrementRefCount()81   void incrementRefCount() {
82     mRefCount++;
83     CHRE_ASSERT(mRefCount != 0);
84   }
85 
decrementRefCount()86   void decrementRefCount() {
87     CHRE_ASSERT(mRefCount > 0);
88     mRefCount--;
89   }
90 
isUnreferenced()91   bool isUnreferenced() const {
92     return (mRefCount == 0);
93   }
94 
95   //! @return true if this event has an associated callback which needs to be
96   //! called prior to deallocating the event
hasFreeCallback()97   bool hasFreeCallback() {
98     return (targetInstanceId == kSystemInstanceId || freeCallback != nullptr);
99   }
100 
101   /**
102    * Invoke the callback associated with this event with the applicable function
103    * signature (passing extraData if this is a system event).
104    *
105    * The caller MUST confirm that hasFreeCallback() is true before calling this
106    * method.
107    */
invokeFreeCallback()108   void invokeFreeCallback() {
109     if (targetInstanceId == kSystemInstanceId) {
110       systemEventCallback(eventType, eventData, extraData);
111     } else {
112       freeCallback(eventType, eventData);
113     }
114   }
115 
116   const uint16_t eventType;
117 
118   //! This value can serve as a proxy for how fast CHRE is processing events
119   //! in its queue by substracting the newest event timestamp by the oldest one.
120   const uint16_t receivedTimeMillis;
121   void *const eventData;
122 
123   //! If targetInstanceId is kSystemInstanceId, senderInstanceId is always
124   //! kSystemInstanceId (nanoapps can't send events to the system), so we
125   //! utilize that to allow an extra 32 bits of data to be passed to the
126   //! callback, which can reduce dynamic allocation in several cases. Therefore,
127   //! if targetInstanceId == kSystemInstanceId, then we use the latter two
128   //! elements in the following two unions
129   union {
130     chreEventCompleteFunction *const freeCallback;
131     SystemEventCallbackFunction *const systemEventCallback;
132   };
133   union {
134     const uint32_t senderInstanceId;
135     void *const extraData;
136   };
137   const uint32_t targetInstanceId;
138 
139   // Bitmask that's used to limit the event delivery to some subset of listeners
140   // registered for this type of event (useful when waking up listeners that can
141   // have different power considerations). When left as the default value
142   // (kDefaultTargetGroupMask), this has the same behavior as broadcasting to
143   // all registered listeners.
144   const uint16_t targetAppGroupMask;
145 
146  private:
147   uint16_t mRefCount = 0;
148 
149   //! @return Monotonic time reference for initializing receivedTimeMillis
150   static uint16_t getTimeMillis();
151 };
152 
153 }  // namespace chre
154 
155 #endif  // CHRE_CORE_EVENT_H_
156