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