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 "chre/core/event.h"
21#include "chre/core/nanoapp.h"
22#include "chre/core/timer_pool.h"
23#include "chre/platform/mutex.h"
24#include "chre/platform/platform_nanoapp.h"
25#include "chre/platform/power_control_manager.h"
26#include "chre/util/dynamic_vector.h"
27#include "chre/util/fixed_size_blocking_queue.h"
28#include "chre/util/non_copyable.h"
29#include "chre/util/synchronized_memory_pool.h"
30#include "chre/util/unique_ptr.h"
31#include "chre_api/chre/event.h"
32
33// These default values can be overridden in the variant-specific makefile.
34#ifndef CHRE_MAX_EVENT_COUNT
35#define CHRE_MAX_EVENT_COUNT 96
36#endif
37
38#ifndef CHRE_MAX_UNSCHEDULED_EVENT_COUNT
39#define CHRE_MAX_UNSCHEDULED_EVENT_COUNT 96
40#endif
41
42namespace chre {
43
44/**
45 * The EventLoop represents a single thread of execution that is shared among
46 * zero or more nanoapps. As the name implies, the EventLoop is built around a
47 * loop that delivers events to the nanoapps managed within for processing.
48 */
49class EventLoop : public NonCopyable {
50 public:
51  /**
52   * Synchronous callback used with forEachNanoapp
53   */
54  typedef void (NanoappCallbackFunction)(const Nanoapp *nanoapp, void *data);
55
56  /**
57   * Searches the set of nanoapps managed by this EventLoop for one with the
58   * given app ID. If found, provides its instance ID, which can be used to send
59   * events to the app.
60   *
61   * This function is safe to call from any thread.
62   *
63   * @param appId The nanoapp identifier to search for.
64   * @param instanceId If this function returns true, will be populated with the
65   *        instanceId associated with the given appId; otherwise unmodified.
66   *        Must not be null.
67   * @return true if the given app ID was found and instanceId was populated
68   */
69  bool findNanoappInstanceIdByAppId(uint64_t appId, uint32_t *instanceId) const;
70
71  /**
72   * Iterates over the list of Nanoapps managed by this EventLoop, and invokes
73   * the supplied callback for each one. This holds a lock if necessary, so it
74   * is safe to call from any thread.
75   *
76   * @param callback Function to invoke on each Nanoapp (synchronously)
77   * @param data Arbitrary data to pass to the callback
78   */
79  void forEachNanoapp(NanoappCallbackFunction *callback, void *data);
80
81  /**
82   * Invokes a message to host free callback supplied by the given nanoapp
83   * (identified by app ID). Ensures that the calling context is updated
84   * appropriately.
85   *
86   * @param appId Identifies the nanoapp that sent this message and supplied the
87   *        free callback
88   * @param freeFunction The non-null message free callback given by the nanoapp
89   * @param message Pointer to the message data
90   * @param messageSize Size of the message
91   */
92  void invokeMessageFreeFunction(
93      uint64_t appId, chreMessageFreeFunction *freeFunction, void *message,
94      size_t messageSize);
95
96  /**
97   * Invokes the Nanoapp's start callback, and if successful, adds it to the
98   * set of Nanoapps managed by this EventLoop. This function must only be
99   * called from the context of the thread that runs this event loop (i.e. from
100   * the same thread that will call run() or from a callback invoked within
101   * run()).
102   *
103   * @param nanoapp The nanoapp that will be started. Upon success, this
104   *        UniquePtr will become invalid, as the underlying Nanoapp instance
105   *        will have been transferred to be managed by this EventLoop.
106   * @return true if the app was started successfully
107   */
108  bool startNanoapp(UniquePtr<Nanoapp>& nanoapp);
109
110  /**
111   * Stops and unloads a nanoapp identified by its instance ID. The end entry
112   * point will be invoked, and the chre::Nanoapp instance will be destroyed.
113   * After this function returns, all references to the Nanoapp instance are
114   * invalidated.
115   *
116   * @param instanceId The nanoapp's unique instance identifier
117   * @param allowSystemNanoappUnload If false, this function will reject
118   *        attempts to unload a system nanoapp
119   *
120   * @return true if the nanoapp with the given instance ID was found & unloaded
121   */
122  bool unloadNanoapp(uint32_t instanceId, bool allowSystemNanoappUnload);
123
124  /**
125   * Executes the loop that blocks on the event queue and delivers received
126   * events to nanoapps. Only returns after stop() is called (from another
127   * context).
128   */
129  void run();
130
131  /**
132   * Signals the event loop currently executing in run() to exit gracefully at
133   * the next available opportunity. This function is thread-safe.
134   */
135  void stop();
136
137  /**
138   * Posts an event to a nanoapp that is currently running (or all nanoapps if
139   * the target instance ID is kBroadcastInstanceId). If the senderInstanceId is
140   * kSystemInstanceId and the event fails to post, this is considered a fatal
141   * error.
142   *
143   * This function is safe to call from any thread.
144   *
145   * @param eventType The type of data being posted.
146   * @param eventData The data being posted.
147   * @param freeCallback The callback to invoke when the event is no longer
148   *        needed.
149   * @param senderInstanceId The instance ID of the sender of this event.
150   * @param targetInstanceId The instance ID of the destination of this event.
151   *
152   * @return true if the event was successfully added to the queue. Note that
153   *         unlike chreSendEvent, this does *not* invoke the free callback if
154   *         it failed to post the event.
155   *
156   * @see chreSendEvent
157   */
158  bool postEvent(uint16_t eventType, void *eventData,
159                 chreEventCompleteFunction *freeCallback,
160                 uint32_t senderInstanceId = kSystemInstanceId,
161                 uint32_t targetInstanceId = kBroadcastInstanceId);
162
163  /**
164   * Post an event to a nanoapp. If it fails, free the event with freeCallback.
165   *
166   * @see postEvent
167   */
168  bool postEventOrFree(uint16_t eventType, void *eventData,
169                       chreEventCompleteFunction *freeCallback,
170                       uint32_t senderInstanceId = kSystemInstanceId,
171                       uint32_t targetInstanceId = kBroadcastInstanceId);
172
173  /**
174   * Returns a pointer to the currently executing Nanoapp, or nullptr if none is
175   * currently executing. Must only be called from within the thread context
176   * associated with this EventLoop.
177   *
178   * @return the currently executing nanoapp, or nullptr
179   */
180  Nanoapp *getCurrentNanoapp() const {
181    return mCurrentApp;
182  }
183
184  /**
185   * Gets the number of nanoapps currently associated with this event loop. Must
186   * only be called within the context of this EventLoop.
187   *
188   * @return The number of nanoapps managed by this event loop
189   */
190  size_t getNanoappCount() const {
191    return mNanoapps.size();
192  }
193
194  /**
195   * Obtains the TimerPool associated with this event loop.
196   *
197   * @return The timer pool owned by this event loop.
198   */
199  TimerPool& getTimerPool() {
200    return mTimerPool;
201  }
202
203  /**
204   * Searches the set of nanoapps managed by this EventLoop for one with the
205   * given instance ID.
206   *
207   * This function is safe to call from any thread.
208   *
209   * @param instanceId The nanoapp instance ID to search for.
210   * @return a pointer to the found nanoapp or nullptr if no match was found.
211   */
212  Nanoapp *findNanoappByInstanceId(uint32_t instanceId) const;
213
214  /**
215   * Looks for an app with the given ID and if found, populates info with its
216   * metadata. Safe to call from any thread.
217   *
218   * @see chreGetNanoappInfoByAppId
219   */
220  bool populateNanoappInfoForAppId(uint64_t appId,
221                                   struct chreNanoappInfo *info) const;
222
223  /**
224   * Looks for an app with the given instance ID and if found, populates info
225   * with its metadata. Safe to call from any thread.
226   *
227   * @see chreGetNanoappInfoByInstanceId
228   */
229  bool populateNanoappInfoForInstanceId(uint32_t instanceId,
230                                        struct chreNanoappInfo *info) const;
231
232  /**
233   * @return true if the current Nanoapp (or entire CHRE) is being unloaded, and
234   *         therefore it should not be allowed to send events or messages, etc.
235   */
236  bool currentNanoappIsStopping() const;
237
238  /**
239   * Prints state in a string buffer. Must only be called from the context of
240   * the main CHRE thread.
241   *
242   * @param buffer Pointer to the start of the buffer.
243   * @param bufferPos Pointer to buffer position to start the print (in-out).
244   * @param size Size of the buffer in bytes.
245   *
246   * @return true if entire log printed, false if overflow or error.
247   */
248  bool logStateToBuffer(char *buffer, size_t *bufferPos,
249                        size_t bufferSize) const;
250
251
252  /**
253   * Returns a reference to the power control manager. This allows power
254   * controls from subsystems outside the event loops.
255   */
256  PowerControlManager& getPowerControlManager() {
257    return mPowerControlManager;
258  }
259
260 private:
261  //! The maximum number of events that can be active in the system.
262  static constexpr size_t kMaxEventCount = CHRE_MAX_EVENT_COUNT;
263
264  //! The minimum number of events to reserve in the event pool for system
265  //! events.
266  static constexpr size_t kMinReservedSystemEventCount = 16;
267
268  //! The maximum number of events that are awaiting to be scheduled. These
269  //! events are in a queue to be distributed to apps.
270  static constexpr size_t kMaxUnscheduledEventCount =
271      CHRE_MAX_UNSCHEDULED_EVENT_COUNT;
272
273  //! The memory pool to allocate incoming events from.
274  SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool;
275
276  //! The timer used schedule timed events for tasks running in this event loop.
277  TimerPool mTimerPool;
278
279  //! The list of nanoapps managed by this event loop.
280  DynamicVector<UniquePtr<Nanoapp>> mNanoapps;
281
282  //! This lock *must* be held whenever we:
283  //!   (1) make changes to the mNanoapps vector, or
284  //!   (2) read the mNanoapps vector from a thread other than the one
285  //!       associated with this EventLoop
286  //! It is not necessary to acquire the lock when reading mNanoapps from within
287  //! the thread context of this EventLoop.
288  mutable Mutex mNanoappsLock;
289
290  //! The blocking queue of incoming events from the system that have not been
291  //! distributed out to apps yet.
292  FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents;
293
294  // TODO: should probably be atomic to be fully correct
295  volatile bool mRunning = true;
296
297  //! The nanoapp that is currently executing - must be set any time we call
298  //! into the nanoapp's entry points or callbacks
299  Nanoapp *mCurrentApp = nullptr;
300
301  //! Set to the nanoapp we are in the process of unloading in unloadNanoapp()
302  Nanoapp *mStoppingNanoapp = nullptr;
303
304  //! The object which manages power related controls.
305  PowerControlManager mPowerControlManager;
306
307  //! The maximum number of events ever waiting in the event pool.
308  size_t mMaxEventPoolUsage = 0;
309
310  /**
311   * Allolcates an event from the event pool and post it.
312   *
313   * @return true if the event has been successfully allocated and posted.
314   *
315   * @see postEvent and postEventOrFree
316   */
317  bool allocateAndPostEvent(uint16_t eventType, void *eventData,
318    chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId,
319    uint32_t targetInstanceId);
320
321  /**
322   * Do one round of Nanoapp event delivery, only considering events in
323   * Nanoapps' own queues (not mEvents).
324   *
325   * @return true if there are more events pending in Nanoapps' own queues
326   */
327  bool deliverEvents();
328
329  /**
330   * Delivers the next event pending in the Nanoapp's queue, and takes care of
331   * freeing events once they have been delivered to all nanoapps. Must only be
332   * called after confirming that the app has at least 1 pending event.
333   *
334   * @return true if the nanoapp has another event pending in its queue
335   */
336  bool deliverNextEvent(const UniquePtr<Nanoapp>& app);
337
338  /**
339   * Given an event pulled from the main incoming event queue (mEvents), deliver
340   * it to all Nanoapps that should receive the event, or free the event if
341   * there are no valid recipients.
342   *
343   * @param event The Event to distribute to Nanoapps
344   */
345  void distributeEvent(Event *event);
346
347  /**
348   * Distribute all events pending in the inbound event queue. Note that this
349   * function only guarantees that any events in the inbound queue at the time
350   * it is called will be distributed to Nanoapp event queues - new events may
351   * still be posted during or after this function call from other threads as
352   * long as postEvent() will accept them.
353   */
354  void flushInboundEventQueue();
355
356  /**
357   * Delivers events pending in Nanoapps' own queues until they are all empty.
358   */
359  void flushNanoappEventQueues();
360
361  /**
362   * Call after when an Event has been delivered to all intended recipients.
363   * Invokes the event's free callback (if given) and releases resources.
364   *
365   * @param event The event to be freed
366   */
367  void freeEvent(Event *event);
368
369  /**
370   * Finds a Nanoapp with the given 64-bit appId.
371   *
372   * Only safe to call within this EventLoop's thread, or if mNanoappsLock is
373   * held.
374   *
375   * @param appId Nanoapp ID
376   * @return Pointer to Nanoapp instance in this EventLoop with the given app
377   *         ID, or nullptr if not found
378   */
379  Nanoapp *lookupAppByAppId(uint64_t appId) const;
380
381  /**
382   * Finds a Nanoapp with the given instanceId.
383   *
384   * Only safe to call within this EventLoop's thread, or if mNanoappsLock is
385   * held.
386   *
387   * @param instanceId Nanoapp instance identifier
388   * @return Nanoapp with the given instanceId, or nullptr if not found
389   */
390  Nanoapp *lookupAppByInstanceId(uint32_t instanceId) const;
391
392  /**
393   * Sends an event with payload struct chreNanoappInfo populated from the given
394   * Nanoapp instance to inform other nanoapps about it starting/stopping.
395   *
396   * @param eventType Should be one of CHRE_EVENT_NANOAPP_{STARTED, STOPPED}
397   * @param nanoapp The nanoapp instance whose status has changed
398   */
399  void notifyAppStatusChange(uint16_t eventType, const Nanoapp& nanoapp);
400
401  /**
402   * Stops and unloads the Nanoapp at the given index in mNanoapps.
403   *
404   * IMPORTANT: prior to calling this function, the event queues must be in a
405   * safe condition for removal of this nanoapp. This means that there must not
406   * be any pending events in this nanoapp's queue, and there must not be any
407   * outstanding events sent by this nanoapp, as they may reference the
408   * nanoapp's own memory (even if there is no free callback).
409   */
410  void unloadNanoappAtIndex(size_t index);
411};
412
413}  // namespace chre
414
415#endif  // CHRE_CORE_EVENT_LOOP_H_
416