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 
22 #include "chre/core/event.h"
23 #include "chre/core/event_ref_queue.h"
24 #include "chre/platform/platform_nanoapp.h"
25 #include "chre/util/dynamic_vector.h"
26 #include "chre/util/fixed_size_vector.h"
27 #include "chre/util/system/debug_dump.h"
28 #include "chre/util/system/napp_permissions.h"
29 
30 namespace chre {
31 
32 /**
33  * A class that tracks the state of a Nanoapp including incoming events and
34  * event registrations.
35  *
36  * Inheritance is used to separate the common interface with common
37  * implementation part (chre::Nanoapp) from the common interface with
38  * platform-specific implementation part (chre::PlatformNanoapp) from the purely
39  * platform-specific part (chre::PlatformNanoappBase). However, this inheritance
40  * relationship does *not* imply polymorphism, and this object must only be
41  * referred to via the most-derived type, i.e. chre::Nanoapp.
42  */
43 class Nanoapp : public PlatformNanoapp {
44  public:
45   Nanoapp();
46   ~Nanoapp();
47 
48   /**
49    * @return The unique identifier for this Nanoapp instance
50    */
getInstanceId()51   uint32_t getInstanceId() const {
52     return mInstanceId;
53   }
54 
55   /**
56    * Assigns an instance ID to this Nanoapp. This must be called prior to
57    * starting this Nanoapp.
58    */
setInstanceId(uint32_t instanceId)59   void setInstanceId(uint32_t instanceId) {
60     mInstanceId = instanceId;
61   }
62 
63   /**
64    * @return The current total number of bytes the nanoapp has allocated.
65    */
getTotalAllocatedBytes()66   size_t getTotalAllocatedBytes() const {
67     return mTotalAllocatedBytes;
68   }
69 
70   /**
71    * @return The peak total number of bytes the nanoapp has allocated.
72    */
getPeakAllocatedBytes()73   size_t getPeakAllocatedBytes() const {
74     return mPeakAllocatedBytes;
75   }
76 
77   /**
78    * Sets the total number of bytes the nanoapp has allocated. Also, modifies
79    * the peak allocated bytes if the current total is higher than the peak.
80    *
81    * @param The total number of bytes the nanoapp has allocated.
82    */
setTotalAllocatedBytes(size_t totalAllocatedBytes)83   void setTotalAllocatedBytes(size_t totalAllocatedBytes) {
84     mTotalAllocatedBytes = totalAllocatedBytes;
85     if (mTotalAllocatedBytes > mPeakAllocatedBytes) {
86       mPeakAllocatedBytes = mTotalAllocatedBytes;
87     }
88   }
89 
90   /**
91    * @return true if the nanoapp should receive broadcast events with the given
92    *         type
93    */
94   bool isRegisteredForBroadcastEvent(uint16_t eventType,
95                                      uint16_t targetGroupIdMask) const;
96 
97   /**
98    * Updates the Nanoapp's registration so that it will receive broadcast events
99    * with the given event type.
100    *
101    * @param eventType The event type that the nanoapp will now be registered to
102    *     receive
103    * @param groupIdMask A mask of group IDs to register the nanoapp for. If an
104    *     event is sent that targets any of the group IDs in the mask, it will
105    *     be delivered to the nanoapp.
106    */
107   void registerForBroadcastEvent(
108       uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
109 
110   /**
111    * Updates the Nanoapp's registration so that it will not receive broadcast
112    * events with the given event type.
113    *
114    * @param eventType The event type that the nanoapp will be unregistered from
115    *    assuming the group ID also matches a valid entry.
116    * @param groupIdMask The mask of group IDs that will be unregistered from.
117    */
118   void unregisterForBroadcastEvent(
119       uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
120 
121   /**
122    * Adds an event to this nanoapp's queue of pending events.
123    */
postEvent(Event * event)124   void postEvent(Event *event) {
125     mEventQueue.push(event);
126   }
127 
128   /**
129    * Indicates whether there are any pending events in this apps queue.
130    *
131    * @return true if there are events waiting to be processed
132    */
hasPendingEvent()133   bool hasPendingEvent() {
134     return !mEventQueue.empty();
135   }
136 
137   /**
138    * Configures whether nanoapp info events will be sent to the nanoapp.
139    * Nanoapps are not sent nanoapp start/stop events by default.
140    *
141    * @param enable true if events are to be sent, false otherwise.
142    */
143   void configureNanoappInfoEvents(bool enable);
144 
145   /**
146    * Configures whether host sleep events will be sent to the nanoapp. Nanoapps
147    * are not sent sleep/awake events by default.
148    *
149    * @param enable true if events are to be sent, false otherwise.
150    */
151   void configureHostSleepEvents(bool enable);
152 
153   /**
154    * Configures whether debug dump events will be sent to the nanoapp. Nanoapps
155    * are not sent debug dump events by default.
156    *
157    * @param enable true if events are to be sent, false otherwise.
158    */
159   void configureDebugDumpEvent(bool enable);
160 
161   /**
162    * Configures whether a user settings event will be sent to the nanoapp
163    * for a specified setting (@see CHRE_USER_SETTINGS)
164    * Nanoapps are not sent user settings events by default.
165    *
166    * @param setting The user setting that the nanoapp wishes to configure
167    * events for.
168    *
169    * @param enable true if events are to be sent, false otherwise.
170    */
171   void configureUserSettingEvent(uint8_t setting, bool enable);
172 
173   /**
174    * Sends the next event in the queue to the nanoapp and returns the processed
175    * event. The hasPendingEvent() method should be tested before invoking this.
176    *
177    * @return A pointer to the processed event
178    */
179   Event *processNextEvent();
180 
181   /**
182    * Log info about a single host wakeup that this nanoapp triggered by storing
183    * the count of wakeups in mWakeupBuckets.
184    */
185   void blameHostWakeup();
186 
187   /*
188    * If buckets not full, then just pushes a 0 to back of buckets. If full, then
189    * shifts down all buckets from back to front and sets back to 0, losing the
190    * latest bucket value that was in front.
191    *
192    * @param numBuckets the number of buckets to cycle into to mWakeupBuckets
193    */
194   void cycleWakeupBuckets(size_t numBuckets);
195 
196   /**
197    * Prints state in a string buffer. Must only be called from the context of
198    * the main CHRE thread.
199    *
200    * @param debugDump The object that is printed into for debug dump logs.
201    */
202   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
203 
204   /**
205    * @return true if the nanoapp is permitted to use the provided permission.
206    */
207   bool permitPermissionUse(uint32_t permission) const;
208 
209  private:
210   uint32_t mInstanceId = kInvalidInstanceId;
211 
212   //! The total memory allocated by the nanoapp in bytes.
213   size_t mTotalAllocatedBytes = 0;
214 
215   //! The peak total number of bytes allocated by the nanoapp.
216   size_t mPeakAllocatedBytes = 0;
217 
218   //! The number of buckets for wakeup logging, adjust along with
219   //! EventLoop::kIntervalWakupBucketInMins.
220   static constexpr size_t kMaxSizeWakeupBuckets = 4;
221 
222   //! A fixed size buffer of buckets that keeps track of the number of host
223   //! wakeups over time intervals.
224   FixedSizeVector<uint16_t, kMaxSizeWakeupBuckets> mWakeupBuckets;
225 
226   //! Metadata needed for keeping track of the registered events for this
227   //! nanoapp.
228   struct EventRegistration {
EventRegistrationEventRegistration229     EventRegistration(uint16_t eventType_, uint16_t groupIdMask_)
230         : eventType(eventType_), groupIdMask(groupIdMask_) {}
231 
232     uint16_t eventType;
233     uint16_t groupIdMask;
234   };
235 
236   //! The set of broadcast events that this app is registered for.
237   // TODO: Implement a set container and replace DynamicVector here. There may
238   // also be a better way of handling this (perhaps we map event type to apps
239   // who care about them).
240   DynamicVector<EventRegistration> mRegisteredEvents;
241 
242   EventRefQueue mEventQueue;
243 
244   //! @return index of event registration if found. mRegisteredEvents.size() if
245   //!     not.
246   size_t registrationIndex(uint16_t eventType) const;
247 
248   /**
249    * A special function to deliver GNSS measurement events to nanoapps and
250    * handles version compatibility.
251    *
252    * @param event The pointer to the event
253    */
254   void handleGnssMeasurementDataEvent(const Event *event);
255 };
256 
257 }  // namespace chre
258 
259 #endif  // CHRE_CORE_NANOAPP_H_
260