• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_LOOP_H_
18 #define CHRE_CORE_EVENT_LOOP_H_
19 
20 #include <pw_function/function.h>
21 #include <stddef.h>
22 #include <optional>
23 
24 #include "chre/core/event.h"
25 #include "chre/core/nanoapp.h"
26 #include "chre/core/timer_pool.h"
27 #include "chre/platform/atomic.h"
28 #include "chre/platform/mutex.h"
29 #include "chre/platform/power_control_manager.h"
30 #include "chre/platform/system_time.h"
31 #include "chre/util/dynamic_vector.h"
32 #include "chre/util/non_copyable.h"
33 #include "chre/util/system/debug_dump.h"
34 #include "chre/util/system/message_common.h"
35 #include "chre/util/system/stats_container.h"
36 #include "chre/util/unique_ptr.h"
37 #include "chre_api/chre/event.h"
38 
39 #ifdef CHRE_STATIC_EVENT_LOOP
40 #include "chre/util/system/fixed_size_blocking_queue.h"
41 #include "chre/util/system/synchronized_memory_pool.h"
42 
43 // These default values can be overridden in the variant-specific makefile.
44 #ifndef CHRE_MAX_EVENT_COUNT
45 #define CHRE_MAX_EVENT_COUNT 96
46 #endif
47 
48 #ifndef CHRE_MAX_UNSCHEDULED_EVENT_COUNT
49 #define CHRE_MAX_UNSCHEDULED_EVENT_COUNT 96
50 #endif
51 #else
52 #include "chre/util/blocking_segmented_queue.h"
53 #include "chre/util/system/synchronized_expandable_memory_pool.h"
54 
55 // These default values can be overridden in the variant-specific makefile.
56 #ifndef CHRE_EVENT_PER_BLOCK
57 #define CHRE_EVENT_PER_BLOCK 24
58 #endif
59 
60 #ifndef CHRE_MAX_EVENT_BLOCKS
61 #define CHRE_MAX_EVENT_BLOCKS 4
62 #endif
63 
64 #endif
65 
66 namespace chre {
67 
68 /**
69  * The EventLoop represents a single thread of execution that is shared among
70  * zero or more nanoapps. As the name implies, the EventLoop is built around a
71  * loop that delivers events to the nanoapps managed within for processing.
72  */
73 class EventLoop : public NonCopyable {
74  public:
75   /**
76    * Synchronous callback used with forEachNanoapp
77    */
78   typedef void(NanoappCallbackFunction)(const Nanoapp *nanoapp, void *data);
79 
EventLoop()80   EventLoop()
81       :
82 #ifndef CHRE_STATIC_EVENT_LOOP
83         mEvents(kMaxEventBlock),
84 #endif
85         mTimeLastWakeupBucketCycled(SystemTime::getMonotonicTime()),
86         mRunning(true) {
87   }
88 
89   /**
90    * Searches the set of nanoapps managed by this EventLoop for one with the
91    * given app ID. If found, provides its instance ID, which can be used to send
92    * events to the app.
93    *
94    * This function is safe to call from any thread.
95    *
96    * @param appId The nanoapp identifier to search for.
97    * @param instanceId If this function returns true, will be populated with the
98    *        instanceId associated with the given appId; otherwise unmodified.
99    *        Must not be null.
100    * @return true if the given app ID was found and instanceId was populated
101    */
102   bool findNanoappInstanceIdByAppId(uint64_t appId, uint16_t *instanceId) const;
103 
104   /**
105    * Iterates over the list of Nanoapps managed by this EventLoop, and invokes
106    * the supplied callback for each one. This holds a lock if necessary, so it
107    * is safe to call from any thread.
108    *
109    * @param callback Function to invoke on each Nanoapp (synchronously)
110    * @param data Arbitrary data to pass to the callback
111    */
112   void forEachNanoapp(NanoappCallbackFunction *callback, void *data);
113 
114   /**
115    * Invokes a message to host free callback supplied by the given nanoapp
116    * (identified by app ID). Ensures that the calling context is updated
117    * appropriately.
118    *
119    * @param appId Identifies the nanoapp that sent this message and supplied the
120    *        free callback
121    * @param freeFunction The non-null message free callback given by the nanoapp
122    * @param message Pointer to the message data
123    * @param messageSize Size of the message
124    */
125   void invokeMessageFreeFunction(uint64_t appId,
126                                  chreMessageFreeFunction *freeFunction,
127                                  void *message, size_t messageSize);
128 
129   /**
130    * Invokes the Nanoapp's start callback, and if successful, adds it to the
131    * set of Nanoapps managed by this EventLoop. This function must only be
132    * called from the context of the thread that runs this event loop (i.e. from
133    * the same thread that will call run() or from a callback invoked within
134    * run()).
135    *
136    * @param nanoapp The nanoapp that will be started. Upon success, this
137    *        UniquePtr will become invalid, as the underlying Nanoapp instance
138    *        will have been transferred to be managed by this EventLoop.
139    * @return true if the app was started successfully
140    */
141   bool startNanoapp(UniquePtr<Nanoapp> &nanoapp);
142 
143   /**
144    * Stops and unloads a nanoapp identified by its instance ID. The end entry
145    * point will be invoked, and the chre::Nanoapp instance will be destroyed.
146    * After this function returns, all references to the Nanoapp instance are
147    * invalidated.
148    *
149    * @param instanceId The nanoapp's unique instance identifier
150    * @param allowSystemNanoappUnload If false, this function will reject
151    *        attempts to unload a system nanoapp
152    * @param nanoappStarted Indicates whether the nanoapp successfully started
153    *
154    * @return true if the nanoapp with the given instance ID was found & unloaded
155    */
156   bool unloadNanoapp(uint16_t instanceId, bool allowSystemNanoappUnload,
157                      bool nanoappStarted = true);
158 
159   /**
160    * Executes the loop that blocks on the event queue and delivers received
161    * events to nanoapps. Only returns after stop() is called (from another
162    * context).
163    */
164   void run();
165 
166   /**
167    * Signals the event loop currently executing in run() to exit gracefully at
168    * the next available opportunity. This function is thread-safe.
169    */
170   void stop();
171 
172   /**
173    * Synchronously distributes an event to all nanoapps that should receive it.
174    * The event is sent from the system to a specific nanoapp if targetInstanceId
175    * matches the nanoappId, or to all registered nanoapps if targetInstanceId
176    * is set to kBroadcastInstanceId
177    *
178    * This is intended to be used by the function provided to
179    * EventLoopManager::deferCallback in cases where pre- and post-processing are
180    * required around event delivery. This closes the gaps around event delivery
181    * and can remove the need for posting multiple events.
182    *
183    * This must only be used from the EventLoop thread, and must only be used in
184    * rare circumstances where one of the postEvent functions cannot be used. In
185    * particular, misuse of this API can break explicit and implicit event
186    * ordering guarantees and trigger subtle bugs in nanoapps, so use with
187    * caution.
188    *
189    * No freeCallback is provided. The caller is expected to manage the memory
190    * for eventData, and handle any cleanup.
191    *
192    * @param eventType Event type identifier, which implies the type of eventData
193    * @param eventData The data being posted
194    * @param targetInstanceId The instance ID of the destination of this event
195    * @param targetGroupMask Mask used to limit the recipients that are
196    *        registered to receive this event
197    */
198   bool distributeEventSync(uint16_t eventType, void *eventData,
199                            uint16_t targetInstanceId = kBroadcastInstanceId,
200                            uint16_t targetGroupMask = kDefaultTargetGroupMask);
201 
202   /**
203    * Posts an event to a nanoapp that is currently running (or all nanoapps if
204    * the target instance ID is kBroadcastInstanceId). A senderInstanceId cannot
205    * be provided to this method because it must only be used to post events
206    * sent by the system. If the event fails to post and the event loop thread is
207    * running, this is considered a fatal error. If the thread is not running
208    * (e.g. CHRE is shutting down), the event is silently dropped and the free
209    * callback is invoked prior to returning (if not null).
210    *
211    * Safe to call from any thread.
212    *
213    * @param eventType Event type identifier, which implies the type of eventData
214    * @param eventData The data being posted
215    * @param freeCallback Function to invoke to when the event has been processed
216    *        by all recipients; this must be safe to call immediately, to handle
217    *        the case where CHRE is shutting down
218    * @param targetInstanceId The instance ID of the destination of this event
219    * @param targetGroupMask Mask used to limit the recipients that are
220    *        registered to receive this event
221    *
222    * @see postLowPriorityEventOrFree
223    */
224   void postEventOrDie(uint16_t eventType, void *eventData,
225                       chreEventCompleteFunction *freeCallback,
226                       uint16_t targetInstanceId = kBroadcastInstanceId,
227                       uint16_t targetGroupMask = kDefaultTargetGroupMask);
228 
229   /**
230    * Posts an event to a nanoapp that is currently running (or all nanoapps if
231    * the target instance ID is kBroadcastInstanceId). If the event fails to
232    * post, freeCallback is invoked prior to returning (if not null).
233    *
234    * Safe to call from any thread.
235    *
236    * @param eventType Event type identifier, which implies the type of eventData
237    * @param eventData The data being posted
238    * @param freeCallback Function to invoke to when the event has been processed
239    *        by all recipients; this must be safe to call immediately, to handle
240    *        the case where CHRE is shutting down
241    * @param senderInstanceId The instance ID of the sender of this event
242    * @param targetInstanceId The instance ID of the destination of this event
243    * @param targetGroupMask Mask used to limit the recipients that are
244    *        registered to receive this event
245    *
246    * @return true if the event was successfully added to the queue.
247    *
248    * @see chreSendEvent
249    */
250   bool postLowPriorityEventOrFree(
251       uint16_t eventType, void *eventData,
252       chreEventCompleteFunction *freeCallback,
253       uint16_t senderInstanceId = kSystemInstanceId,
254       uint16_t targetInstanceId = kBroadcastInstanceId,
255       uint16_t targetGroupMask = kDefaultTargetGroupMask);
256 
257   /**
258    * Posts an event for processing by the system from within the context of the
259    * CHRE thread. Uses the same underlying event queue as is used for nanoapp
260    * events, but gives the ability to provide an additional data pointer. If the
261    * event loop is running and the system event can't be posted (i.e. queue is
262    * full), then a fatal error is raised.
263    *
264    * Safe to call from any thread.
265    *
266    * @param eventType Event type identifier, which is forwarded to the callback
267    * @param eventData Arbitrary data to pass to the callback
268    * @param callback Function to invoke from the context of the CHRE thread
269    * @param extraData Additional arbitrary data to provide to the callback
270    *
271    * @return true if successfully posted; false ONLY IF the CHRE event loop is
272    *         shutting down and not accepting any new events - in this case,
273    *         the callback will not be invoked and any allocated memory must be
274    *         cleaned up
275    *
276    * @see postEventOrDie
277    * @see EventLoopManager::deferCallback
278    */
279   bool postSystemEvent(uint16_t eventType, void *eventData,
280                        SystemEventCallbackFunction *callback, void *extraData);
281 
282   /**
283    * Returns a pointer to the currently executing Nanoapp, or nullptr if none is
284    * currently executing. Must only be called from within the thread context
285    * associated with this EventLoop.
286    *
287    * @return the currently executing nanoapp, or nullptr
288    */
getCurrentNanoapp()289   Nanoapp *getCurrentNanoapp() const {
290     return mCurrentApp;
291   }
292 
293   /**
294    * Gets the number of nanoapps currently associated with this event loop. Must
295    * only be called within the context of this EventLoop.
296    *
297    * @return The number of nanoapps managed by this event loop
298    */
getNanoappCount()299   size_t getNanoappCount() const {
300     return mNanoapps.size();
301   }
302 
303   /**
304    * Obtains the TimerPool associated with this event loop.
305    *
306    * @return The timer pool owned by this event loop.
307    */
getTimerPool()308   TimerPool &getTimerPool() {
309     return mTimerPool;
310   }
311 
312   /**
313    * Searches the set of nanoapps managed by this EventLoop for one with the
314    * given instance ID.
315    *
316    * This function is safe to call from any thread.
317    *
318    * @param instanceId The nanoapp instance ID to search for.
319    * @return a pointer to the found nanoapp or nullptr if no match was found.
320    */
321   Nanoapp *findNanoappByInstanceId(uint16_t instanceId) const;
322 
323   /**
324    * Searches the set of nanoapps managed by this EventLoop for one with the
325    * given nanoapp ID.
326    *
327    * This function is safe to call from any thread.
328    *
329    * @param appId The nanoapp ID to search for.
330    * @return a pointer to the found nanoapp or nullptr if no match was found.
331    */
332   Nanoapp *findNanoappByAppId(uint64_t appId) const;
333 
334   /**
335    * Looks for an app with the given ID and if found, populates info with its
336    * metadata. Safe to call from any thread.
337    *
338    * @see chreGetNanoappInfoByAppId
339    */
340   bool populateNanoappInfoForAppId(uint64_t appId,
341                                    struct chreNanoappInfo *info) const;
342 
343   /**
344    * Looks for an app with the given instance ID and if found, populates info
345    * with its metadata. Safe to call from any thread.
346    *
347    * @see chreGetNanoappInfoByInstanceId
348    */
349   bool populateNanoappInfoForInstanceId(uint16_t instanceId,
350                                         struct chreNanoappInfo *info) const;
351 
352   /**
353    * @return true if the current Nanoapp (or entire CHRE) is being unloaded, and
354    *         therefore it should not be allowed to send events or messages, etc.
355    */
356   bool currentNanoappIsStopping() const;
357 
358   /**
359    * Prints state in a string buffer. Must only be called from the context of
360    * the main CHRE thread.
361    *
362    * @param debugDump The debug dump wrapper where a string can be printed
363    *     into one of the buffers.
364    */
365   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
366 
367   /**
368    * Executes function for each nanoapp in the event loop. If function
369    * returns true, the iteration will stop.
370    *
371    * This function is safe to call from any thread.
372    *
373    * @param function The function to execute for each nanoapp.
374    */
375   void onMatchingNanoappEndpoint(
376       const pw::Function<bool(const message::EndpointInfo &)> &function);
377 
378   /**
379    * Executes function for each service provided by a nanoapp in the event
380    * loop. If function returns true, the iteration will stop.
381    *
382    * This function is safe to call from any thread.
383    *
384    * @param function The function to execute for each service.
385    */
386   void onMatchingNanoappService(
387       const pw::Function<bool(const message::EndpointInfo &,
388                               const message::ServiceInfo &)> &function);
389 
390   /**
391    * Returns the EndpointInfo for the given nanoapp.
392    *
393    * This function is safe to call from any thread.
394    *
395    * @param appId The nanoapp ID to search for.
396    * @return The EndpointInfo for the given nanoapp, or std::nullopt if not
397    * found.
398    */
399   std::optional<message::EndpointInfo> getEndpointInfo(uint64_t appId);
400 
401   /**
402    * Returns a reference to the power control manager. This allows power
403    * controls from subsystems outside the event loops.
404    */
getPowerControlManager()405   PowerControlManager &getPowerControlManager() {
406     return mPowerControlManager;
407   }
408 
getMaxEventQueueSize()409   inline uint32_t getMaxEventQueueSize() const {
410     return mEventPoolUsage.getMax();
411   }
412 
getNumEventsDropped()413   inline uint32_t getNumEventsDropped() const {
414     return mNumDroppedLowPriEvents;
415   }
416 
417  private:
418 #ifdef CHRE_STATIC_EVENT_LOOP
419   //! The maximum number of events that can be active in the system.
420   static constexpr size_t kMaxEventCount = CHRE_MAX_EVENT_COUNT;
421 
422   //! The maximum number of events that are awaiting to be scheduled. These
423   //! events are in a queue to be distributed to apps.
424   static constexpr size_t kMaxUnscheduledEventCount =
425       CHRE_MAX_UNSCHEDULED_EVENT_COUNT;
426 
427   //! The memory pool to allocate incoming events from.
428   SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool;
429 
430   //! The blocking queue of incoming events from the system that have not been
431   //! distributed out to apps yet.
432   FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents;
433 
434 #else
435   //! The maximum number of event that can be stored in a block in mEventPool.
436   static constexpr size_t kEventPerBlock = CHRE_EVENT_PER_BLOCK;
437 
438   //! The maximum number of event blocks that mEventPool can hold.
439   static constexpr size_t kMaxEventBlock = CHRE_MAX_EVENT_BLOCKS;
440 
441   static constexpr size_t kMaxEventCount =
442       CHRE_EVENT_PER_BLOCK * CHRE_MAX_EVENT_BLOCKS;
443 
444   //! The memory pool to allocate incoming events from.
445   SynchronizedExpandableMemoryPool<Event, kEventPerBlock, kMaxEventBlock>
446       mEventPool;
447 
448   //! The blocking queue of incoming events from the system that have not been
449   //! distributed out to apps yet.
450   BlockingSegmentedQueue<Event *, kEventPerBlock> mEvents;
451 #endif
452 
453   //! The last time wakeup buckets were pushed onto the nanoapps.
454   Nanoseconds mTimeLastWakeupBucketCycled;
455 
456   //! The timer used schedule timed events for tasks running in this event loop.
457   TimerPool mTimerPool;
458 
459   //! The list of nanoapps managed by this event loop.
460   DynamicVector<UniquePtr<Nanoapp>> mNanoapps;
461 
462   //! This lock *must* be held whenever we:
463   //!   (1) make changes to the mNanoapps vector, or
464   //!   (2) read the mNanoapps vector from a thread other than the one
465   //!       associated with this EventLoop
466   //! It is not necessary to acquire the lock when reading mNanoapps from within
467   //! the thread context of this EventLoop.
468   mutable Mutex mNanoappsLock;
469 
470   //! Indicates whether the event loop is running.
471   AtomicBool mRunning;
472 
473   //! The nanoapp that is currently executing - must be set any time we call
474   //! into the nanoapp's entry points or callbacks
475   Nanoapp *mCurrentApp = nullptr;
476 
477   //! Set to the nanoapp we are in the process of unloading in unloadNanoapp()
478   Nanoapp *mStoppingNanoapp = nullptr;
479 
480   //! The object which manages power related controls.
481   PowerControlManager mPowerControlManager;
482 
483   //! The stats collection used to collect event pool usage
484   StatsContainer<uint32_t> mEventPoolUsage;
485 
486   //! The number of events dropped due to capacity limits
487   uint32_t mNumDroppedLowPriEvents = 0;
488 
489   //! The timer used to cycle nanoapp wakeup buckets.
490   TimerHandle mCycleWakeupBucketsHandle = CHRE_TIMER_INVALID;
491 
492   /**
493    * Modifies the run loop state so it no longer iterates on new events. This
494    * should only be invoked by the event loop when it is ready to stop
495    * processing new events.
496    */
497   void onStopComplete();
498 
499   /**
500    * Allocates an event from the event pool and post it.
501    *
502    * @return true if the event has been successfully allocated and posted.
503    *
504    * @see postEventOrDie and postLowPriorityEventOrFree
505    */
506   bool allocateAndPostEvent(uint16_t eventType, void *eventData,
507                             chreEventCompleteFunction *freeCallback,
508                             bool isLowPriority, uint16_t senderInstanceId,
509                             uint16_t targetInstanceId,
510                             uint16_t targetGroupMask);
511   /**
512    * Remove some non nanoapp and low priority events from back of the queue.
513    *
514    * @param removeNum Number of low priority events to be removed.
515    * @return False if cannot remove any low priority event.
516    */
517   bool removeNonNanoappLowPriorityEventsFromBack(size_t removeNum);
518 
519   /**
520    * Determine if there are space for high priority event.
521    * During the processing of determining the vacant space, it might
522    * remove low priority events to make space for high priority event.
523    *
524    * @return true if there are no space for a new high priority event.
525    */
526   bool hasNoSpaceForHighPriorityEvent();
527 
528   /**
529    * Delivers the next event pending to the Nanoapp.
530    */
531   void deliverNextEvent(const UniquePtr<Nanoapp> &app, Event *event);
532 
533   /**
534    * Given an event pulled from the main incoming event queue (mEvents), deliver
535    * it to all Nanoapps that should receive the event, or free the event if
536    * there are no valid recipients.
537    *
538    * @param event The Event to distribute to Nanoapps
539    */
540   void distributeEvent(Event *event);
541 
542   /**
543    * Shared functionality to distributeEvent and distributeEventSync. Should
544    * only be called by those functions. Hnadles event distribution and logging
545    * without any pre- or post-processing.
546    *
547    * @param event The Event to distribute to Nanoapps
548    * @return True if the event was delivered to any nanoapps, otherwise false
549    */
550   bool distributeEventCommon(Event *event);
551 
552   /**
553    * Distribute all events pending in the inbound event queue. Note that this
554    * function only guarantees that any events in the inbound queue at the time
555    * it is called will be distributed to Nanoapp event queues - new events may
556    * still be posted during or after this function call from other threads as
557    * long as postEvent() will accept them.
558    */
559   void flushInboundEventQueue();
560 
561   /**
562    * Call after when an Event has been delivered to all intended recipients.
563    * Invokes the event's free callback (if given) and releases resources.
564    *
565    * @param event The event to be freed
566    */
567   void freeEvent(Event *event);
568 
569   /**
570    * Finds a Nanoapp with the given 64-bit appId.
571    *
572    * Only safe to call within this EventLoop's thread, or if mNanoappsLock is
573    * held.
574    *
575    * @param appId Nanoapp ID
576    * @return Pointer to Nanoapp instance in this EventLoop with the given app
577    *         ID, or nullptr if not found
578    */
579   Nanoapp *lookupAppByAppId(uint64_t appId) const;
580 
581   /**
582    * Finds a Nanoapp with the given instanceId.
583    *
584    * Only safe to call within this EventLoop's thread, or if mNanoappsLock is
585    * held.
586    *
587    * @param instanceId Nanoapp instance identifier
588    * @return Nanoapp with the given instanceId, or nullptr if not found
589    */
590   Nanoapp *lookupAppByInstanceId(uint16_t instanceId) const;
591 
592   /**
593    * Sends an event with payload struct chreNanoappInfo populated from the given
594    * Nanoapp instance to inform other nanoapps about it starting/stopping.
595    *
596    * @param eventType Should be one of CHRE_EVENT_NANOAPP_{STARTED, STOPPED}
597    * @param nanoapp The nanoapp instance whose status has changed
598    */
599   void notifyAppStatusChange(uint16_t eventType, const Nanoapp &nanoapp);
600 
601   /**
602    * Stops and unloads the Nanoapp at the given index in mNanoapps.
603    *
604    * IMPORTANT: prior to calling this function, the event queues must be in a
605    * safe condition for removal of this nanoapp. This means that there must not
606    * be any pending events in this nanoapp's queue, and there must not be any
607    * outstanding events sent by this nanoapp, as they may reference the
608    * nanoapp's own memory (even if there is no free callback).
609    *
610    * @param index Index of the nanoapp in the list of nanoapps managed by event
611    * loop.
612    * @param nanoappStarted Indicates whether the nanoapp successfully started
613    */
614   void unloadNanoappAtIndex(size_t index, bool nanoappStarted = true);
615 
616   /**
617    * Logs dangling resources when a nanoapp is unloaded.
618    *
619    * @param name The name of the resource.
620    * @param count The number of dangling resources.
621    */
622   void logDanglingResources(const char *name, uint32_t count);
623 
624   /**
625    * Returns the EndpointInfo for the given nanoapp.
626    *
627    * Only safe to call within this EventLoop's thread, or if mNanoappsLock is
628    * held.
629    *
630    * @param nanoapp The nanoapp to get the EndpointInfo for.
631    * @return The EndpointInfo for the given nanoapp
632    */
633   message::EndpointInfo getEndpointInfoFromNanoappLocked(
634       const Nanoapp &nanoapp);
635 
636   /*
637    * Pushes new wakeup buckets that need to be pushed to nanoapps.
638    */
639   void handleNanoappWakeupBuckets();
640 
641   /*
642    * Set up the timer used for calling handleNanoappWakeupBuckets() to cycle
643    * wakeup buckets once the wakeup bucket interval has been surpassed.
644    */
645   void setCycleWakeupBucketsTimer();
646 };
647 
648 }  // namespace chre
649 
650 #endif  // CHRE_CORE_EVENT_LOOP_H_
651