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