xref: /aosp_15_r20/system/chre/core/include/chre/core/nanoapp.h (revision 84e339476a462649f82315436d70fd732297a399)
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_NANOAPP_H_
18 #define CHRE_CORE_NANOAPP_H_
19 
20 #include <cinttypes>
21 #include <cstdint>
22 #include <limits>
23 
24 #include "chre/core/event.h"
25 #include "chre/core/event_ref_queue.h"
26 #include "chre/platform/heap_block_header.h"
27 #include "chre/platform/platform_nanoapp.h"
28 #include "chre/platform/system_time.h"
29 #include "chre/util/dynamic_vector.h"
30 #include "chre/util/fixed_size_vector.h"
31 #include "chre/util/system/debug_dump.h"
32 #include "chre/util/system/napp_permissions.h"
33 #include "chre/util/system/stats_container.h"
34 #include "chre_api/chre/event.h"
35 
36 namespace chre {
37 
38 /**
39  * A class that tracks the state of a Nanoapp including incoming events and
40  * event registrations.
41  *
42  * Inheritance is used to separate the common interface with common
43  * implementation part (chre::Nanoapp) from the common interface with
44  * platform-specific implementation part (chre::PlatformNanoapp) from the purely
45  * platform-specific part (chre::PlatformNanoappBase). However, this inheritance
46  * relationship does *not* imply polymorphism, and this object must only be
47  * referred to via the most-derived type, i.e. chre::Nanoapp.
48  */
49 class Nanoapp : public PlatformNanoapp {
50  public:
51   /** @see chrePublishRpcServices */
52   static constexpr size_t kMaxRpcServices = UINT8_MAX;
53   static_assert(
54       std::numeric_limits<decltype(chreNanoappInfo::rpcServiceCount)>::max() >=
55           kMaxRpcServices,
56       "Revisit the constant");
57 
58   Nanoapp();
59 
60   // The nanoapp instance ID should only come from the event loop manager. This
61   // constructor should never be called except for use in unit tests.
62   Nanoapp(uint16_t instanceId);
63 
64   /**
65    * Calls the start function of the nanoapp. For dynamically loaded nanoapps,
66    * this must also result in calling through to any of the nanoapp's static
67    * global constructors/init functions, etc., prior to invoking the
68    * nanoappStart.
69    *
70    * @return true if the app was able to start successfully
71    *
72    * @see nanoappStart
73    */
74   bool start();
75 
76   /**
77    * @return The unique identifier for this Nanoapp instance
78    */
getInstanceId()79   uint16_t getInstanceId() const {
80     return mInstanceId;
81   }
82 
83   /**
84    * @return The current total number of bytes the nanoapp has allocated.
85    */
getTotalAllocatedBytes()86   size_t getTotalAllocatedBytes() const {
87     return mTotalAllocatedBytes;
88   }
89 
90   /**
91    * @return The peak total number of bytes the nanoapp has allocated.
92    */
getPeakAllocatedBytes()93   size_t getPeakAllocatedBytes() const {
94     return mPeakAllocatedBytes;
95   }
96 
97   /**
98    * Sets the total number of bytes the nanoapp has allocated. Also, modifies
99    * the peak allocated bytes if the current total is higher than the peak.
100    *
101    * @param The total number of bytes the nanoapp has allocated.
102    */
setTotalAllocatedBytes(size_t totalAllocatedBytes)103   void setTotalAllocatedBytes(size_t totalAllocatedBytes) {
104     mTotalAllocatedBytes = totalAllocatedBytes;
105     if (mTotalAllocatedBytes > mPeakAllocatedBytes) {
106       mPeakAllocatedBytes = mTotalAllocatedBytes;
107     }
108   }
109 
110   /**
111    * @return true if the nanoapp should receive broadcast event
112    */
113   bool isRegisteredForBroadcastEvent(const Event *event) const;
114 
115   /**
116    * Updates the Nanoapp's registration so that it will receive broadcast events
117    * with the given event type.
118    *
119    * @param eventType The event type that the nanoapp will now be registered to
120    *     receive
121    * @param groupIdMask A mask of group IDs to register the nanoapp for. If an
122    *     event is sent that targets any of the group IDs in the mask, it will
123    *     be delivered to the nanoapp.
124    */
125   void registerForBroadcastEvent(
126       uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
127 
128   /**
129    * Updates the Nanoapp's registration so that it will not receive broadcast
130    * events with the given event type.
131    *
132    * @param eventType The event type that the nanoapp will be unregistered from
133    *    assuming the group ID also matches a valid entry.
134    * @param groupIdMask The mask of group IDs that will be unregistered from.
135    */
136   void unregisterForBroadcastEvent(
137       uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
138 
139   /**
140    * Configures whether nanoapp info events will be sent to the nanoapp.
141    * Nanoapps are not sent nanoapp start/stop events by default.
142    *
143    * @param enable true if events are to be sent, false otherwise.
144    */
145   void configureNanoappInfoEvents(bool enable);
146 
147   /**
148    * Configures whether host sleep events will be sent to the nanoapp. Nanoapps
149    * are not sent sleep/awake events by default.
150    *
151    * @param enable true if events are to be sent, false otherwise.
152    */
153   void configureHostSleepEvents(bool enable);
154 
155   /**
156    * Configures whether debug dump events will be sent to the nanoapp. Nanoapps
157    * are not sent debug dump events by default.
158    *
159    * @param enable true if events are to be sent, false otherwise.
160    */
161   void configureDebugDumpEvent(bool enable);
162 
163   /**
164    * Configures whether a user settings event will be sent to the nanoapp
165    * for a specified setting (@see CHRE_USER_SETTINGS)
166    * Nanoapps are not sent user settings events by default.
167    *
168    * @param setting The user setting that the nanoapp wishes to configure
169    * events for.
170    *
171    * @param enable true if events are to be sent, false otherwise.
172    */
173   void configureUserSettingEvent(uint8_t setting, bool enable);
174 
175   /**
176    * Sends an event to the nanoapp to be processed.
177    *
178    * @param event A pointer to the event to be processed
179    */
180   void processEvent(Event *event);
181 
182   /**
183    * Log info about a single host wakeup that this nanoapp triggered by storing
184    * the count of wakeups in mWakeupBuckets.
185    */
186   void blameHostWakeup();
187 
188   /**
189    * Log info about a single message sent to the host that this nanoapp
190    * triggered by storing the count of messages in mNumMessagesSentSinceBoot.
191    */
192   void blameHostMessageSent();
193 
194   /*
195    * If buckets not full, then just pushes a 0 to back of buckets. If full, then
196    * shifts down all buckets from back to front and sets back to 0, losing the
197    * latest bucket value that was in front.
198    *
199    * With nanoapps tracking their cycling time, there is no reason to ever
200    * cycle more than one bucket at a time. Doing more wastes valuable data
201    *
202    * @param timestamp the current time when this bucket was created
203    */
204   void cycleWakeupBuckets(Nanoseconds timestamp);
205 
206   /**
207    * Prints state in a string buffer. Must only be called from the context of
208    * the main CHRE thread.
209    *
210    * @param debugDump The object that is printed into for debug dump logs.
211    */
212   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
213 
214   /**
215    * Prints header for memory allocation and event processing time stats table
216    * in a string buffer. Must only be called from the context of the main CHRE
217    * thread.
218    *
219    * @param debugDump The object that is printed into for debug dump logs.
220    */
221   void logMemAndComputeHeader(DebugDumpWrapper &debugDump) const;
222 
223   /**
224    * Prints memory allocation and event processing time stats in a string
225    * buffer. Must only be called from the context of the main CHRE thread.
226    *
227    * @param debugDump The object that is printed into for debug dump logs.
228    */
229   void logMemAndComputeEntry(DebugDumpWrapper &debugDump) const;
230 
231   /**
232    * Prints header for wakeup and host message stats table in a string buffer.
233    * Must only be called from the context of the main CHRE thread.
234    *
235    * @param debugDump The object that is printed into for debug dump logs.
236    */
237   void logMessageHistoryHeader(DebugDumpWrapper &debugDump) const;
238 
239   /**
240    * Prints wakeup and host message stats in a string buffer. Must only be
241    * called from the context of the main CHRE thread.
242    *
243    * @param debugDump The object that is printed into for debug dump logs.
244    */
245   void logMessageHistoryEntry(DebugDumpWrapper &debugDump) const;
246 
247   /**
248    * @return true if the nanoapp is permitted to use the provided permission.
249    */
250   bool permitPermissionUse(uint32_t permission) const;
251 
252   /**
253    * Configures notification updates for a given host endpoint.
254    *
255    * @param hostEndpointId The ID of the host endpoint.
256    * @param enable true to enable notifications.
257    *
258    * @return true if the configuration is successful.
259    */
260   bool configureHostEndpointNotifications(uint16_t hostEndpointId, bool enable);
261 
262   /**
263    * Publishes RPC services for this nanoapp.
264    *
265    * @param services A pointer to the list of RPC services to publish.
266    *   Can be null if numServices is 0.
267    * @param numServices The number of services to publish, i.e. the length of
268    * the services array.
269    *
270    * @return true if the publishing is successful.
271    */
272   bool publishRpcServices(struct chreNanoappRpcService *services,
273                           size_t numServices);
274 
275   /**
276    * @return The list of RPC services published by this nanoapp.
277    */
getRpcServices()278   const DynamicVector<struct chreNanoappRpcService> &getRpcServices() const {
279     return mRpcServices;
280   }
281 
282   /**
283    * Adds a block of memory to the linked list of headers.
284    *
285    * @see getFirstHeapBlock
286    * @see chreHeapAlloc
287    */
288   void linkHeapBlock(HeapBlockHeader *header);
289 
290   /**
291    * Removes a block of memory from the linked list of headers.
292    *
293    * @see getFirstHeapBlock
294    * @see chreHeapFree
295    */
296   void unlinkHeapBlock(HeapBlockHeader *header);
297 
298   /**
299    * @return A pointer to the first allocated heap block.
300    */
getFirstHeapBlock()301   HeapBlockHeader *getFirstHeapBlock() {
302     return mFirstHeader;
303   }
304 
305   /**
306    * @return whether the nanoapp has the provided permissions.
307    */
hasPermissions(uint32_t permissions)308   bool hasPermissions(uint32_t permissions) const {
309     return permissions == 0 ||
310            (supportsAppPermissions() &&
311             (getAppPermissions() & permissions) == permissions);
312   }
313 
314  private:
315   uint16_t mInstanceId = kInvalidInstanceId;
316 
317   //! The total number of wakeup counts for a nanoapp.
318   uint32_t mNumWakeupsSinceBoot = 0;
319 
320   //! The total number of messages sent to host by this nanoapp.
321   uint32_t mNumMessagesSentSinceBoot = 0;
322 
323   //! The total time in ms spend processing events by this nanoapp.
324   uint64_t mEventProcessTimeSinceBoot = 0;
325 
326   /**
327    * Head of the singly linked list of heap block headers.
328    *
329    * The list is used to free all the memory allocated by the nanoapp.
330    *
331    * @see MemoryManager
332    */
333   HeapBlockHeader *mFirstHeader = nullptr;
334 
335   //! The total memory allocated by the nanoapp in bytes.
336   size_t mTotalAllocatedBytes = 0;
337 
338   //! The peak total number of bytes allocated by the nanoapp.
339   size_t mPeakAllocatedBytes = 0;
340 
341   //! Container for "bucketed" stats associated with wakeup logging
342   struct BucketedStats {
BucketedStatsBucketedStats343     BucketedStats(uint16_t wakeupCount_, uint16_t hostMessageCount_,
344                   uint64_t eventProcessTime_, uint64_t creationTimestamp_)
345         : wakeupCount(wakeupCount_),
346           hostMessageCount(hostMessageCount_),
347           eventProcessTime(eventProcessTime_),
348           creationTimestamp(creationTimestamp_) {}
349 
350     uint16_t wakeupCount = 0;
351     uint16_t hostMessageCount = 0;
352     uint64_t eventProcessTime = 0;
353     uint64_t creationTimestamp = 0;
354   };
355 
356   //! The number of buckets for wakeup logging, adjust along with
357   //! EventLoop::kIntervalWakeupBucket.
358   static constexpr size_t kMaxSizeWakeupBuckets = 5;
359 
360   //! A fixed size buffer of buckets that keeps track of the number of host
361   //! wakeups over time intervals.
362   FixedSizeVector<BucketedStats, kMaxSizeWakeupBuckets> mWakeupBuckets;
363 
364   //! Collects process time in nanoseconds of each event
365   StatsContainer<uint64_t> mEventProcessTime;
366 
367   //! Metadata needed for keeping track of the registered events for this
368   //! nanoapp.
369   struct EventRegistration {
EventRegistrationEventRegistration370     EventRegistration(uint16_t eventType_, uint16_t groupIdMask_)
371         : eventType(eventType_), groupIdMask(groupIdMask_) {}
372 
373     uint16_t eventType;
374     uint16_t groupIdMask;
375   };
376 
377   //! The set of broadcast events that this app is registered for.
378   // TODO: Implement a set container and replace DynamicVector here. There may
379   // also be a better way of handling this (perhaps we map event type to apps
380   // who care about them).
381   DynamicVector<EventRegistration> mRegisteredEvents;
382 
383   //! The registered host endpoints to receive notifications for.
384   DynamicVector<uint16_t> mRegisteredHostEndpoints;
385 
386   //! The list of RPC services for this nanoapp.
387   DynamicVector<struct chreNanoappRpcService> mRpcServices;
388 
389   //! Whether nanoappStart is being executed.
390   bool mIsInNanoappStart = false;
391 
392   //! @return index of event registration if found. mRegisteredEvents.size() if
393   //!     not.
394   size_t registrationIndex(uint16_t eventType) const;
395 
396   /**
397    * A special function to deliver GNSS measurement events to nanoapps and
398    * handles version compatibility.
399    *
400    * @param event The pointer to the event
401    */
402   void handleGnssMeasurementDataEvent(const Event *event);
403 
isRegisteredForHostEndpointNotifications(uint16_t hostEndpointId)404   bool isRegisteredForHostEndpointNotifications(uint16_t hostEndpointId) const {
405     return mRegisteredHostEndpoints.find(hostEndpointId) !=
406            mRegisteredHostEndpoints.size();
407   }
408 };
409 
410 }  // namespace chre
411 
412 #endif  // CHRE_CORE_NANOAPP_H_
413