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