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