• 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_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    * @return true if the nanoapp has the provided RPC service.
284    */
285   bool hasRpcService(uint64_t serviceId) const;
286 
287   /**
288    * Adds a block of memory to the linked list of headers.
289    *
290    * @see getFirstHeapBlock
291    * @see chreHeapAlloc
292    */
293   void linkHeapBlock(HeapBlockHeader *header);
294 
295   /**
296    * Removes a block of memory from the linked list of headers.
297    *
298    * @see getFirstHeapBlock
299    * @see chreHeapFree
300    */
301   void unlinkHeapBlock(HeapBlockHeader *header);
302 
303   /**
304    * @return A pointer to the first allocated heap block.
305    */
getFirstHeapBlock()306   HeapBlockHeader *getFirstHeapBlock() {
307     return mFirstHeader;
308   }
309 
310   /**
311    * @return whether the nanoapp has the provided permissions.
312    */
hasPermissions(uint32_t permissions)313   bool hasPermissions(uint32_t permissions) const {
314     return permissions == 0 ||
315            (supportsAppPermissions() &&
316             (getAppPermissions() & permissions) == permissions);
317   }
318 
319  private:
320   uint16_t mInstanceId = kInvalidInstanceId;
321 
322   //! The total number of wakeup counts for a nanoapp.
323   uint32_t mNumWakeupsSinceBoot = 0;
324 
325   //! The total number of messages sent to host by this nanoapp.
326   uint32_t mNumMessagesSentSinceBoot = 0;
327 
328   //! The total time in ms spend processing events by this nanoapp.
329   uint64_t mEventProcessTimeSinceBoot = 0;
330 
331   /**
332    * Head of the singly linked list of heap block headers.
333    *
334    * The list is used to free all the memory allocated by the nanoapp.
335    *
336    * @see MemoryManager
337    */
338   HeapBlockHeader *mFirstHeader = nullptr;
339 
340   //! The total memory allocated by the nanoapp in bytes.
341   size_t mTotalAllocatedBytes = 0;
342 
343   //! The peak total number of bytes allocated by the nanoapp.
344   size_t mPeakAllocatedBytes = 0;
345 
346   //! Container for "bucketed" stats associated with wakeup logging
347   struct BucketedStats {
BucketedStatsBucketedStats348     BucketedStats(uint16_t wakeupCount_, uint16_t hostMessageCount_,
349                   uint64_t eventProcessTime_, uint64_t creationTimestamp_)
350         : wakeupCount(wakeupCount_),
351           hostMessageCount(hostMessageCount_),
352           eventProcessTime(eventProcessTime_),
353           creationTimestamp(creationTimestamp_) {}
354 
355     uint16_t wakeupCount = 0;
356     uint16_t hostMessageCount = 0;
357     uint64_t eventProcessTime = 0;
358     uint64_t creationTimestamp = 0;
359   };
360 
361   //! The number of buckets for wakeup logging, adjust along with
362   //! EventLoop::kIntervalWakeupBucket.
363   static constexpr size_t kMaxSizeWakeupBuckets = 5;
364 
365   //! A fixed size buffer of buckets that keeps track of the number of host
366   //! wakeups over time intervals.
367   FixedSizeVector<BucketedStats, kMaxSizeWakeupBuckets> mWakeupBuckets;
368 
369   //! Collects process time in nanoseconds of each event
370   StatsContainer<uint64_t> mEventProcessTime;
371 
372   //! Metadata needed for keeping track of the registered events for this
373   //! nanoapp.
374   struct EventRegistration {
EventRegistrationEventRegistration375     EventRegistration(uint16_t eventType_, uint16_t groupIdMask_)
376         : eventType(eventType_), groupIdMask(groupIdMask_) {}
377 
378     uint16_t eventType;
379     uint16_t groupIdMask;
380   };
381 
382   //! The set of broadcast events that this app is registered for.
383   // TODO: Implement a set container and replace DynamicVector here. There may
384   // also be a better way of handling this (perhaps we map event type to apps
385   // who care about them).
386   DynamicVector<EventRegistration> mRegisteredEvents;
387 
388   //! The registered host endpoints to receive notifications for.
389   DynamicVector<uint16_t> mRegisteredHostEndpoints;
390 
391   //! The list of RPC services for this nanoapp.
392   DynamicVector<struct chreNanoappRpcService> mRpcServices;
393 
394   //! Whether nanoappStart is being executed.
395   bool mIsInNanoappStart = false;
396 
397   //! @return index of event registration if found. mRegisteredEvents.size() if
398   //!     not.
399   size_t registrationIndex(uint16_t eventType) const;
400 
401   /**
402    * A special function to deliver GNSS measurement events to nanoapps and
403    * handles version compatibility.
404    *
405    * @param event The pointer to the event
406    */
407   void handleGnssMeasurementDataEvent(const Event *event);
408 
isRegisteredForHostEndpointNotifications(uint16_t hostEndpointId)409   bool isRegisteredForHostEndpointNotifications(uint16_t hostEndpointId) const {
410     return mRegisteredHostEndpoints.find(hostEndpointId) !=
411            mRegisteredHostEndpoints.size();
412   }
413 };
414 
415 }  // namespace chre
416 
417 #endif  // CHRE_CORE_NANOAPP_H_
418