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 #include "chre/core/nanoapp.h" 18 19 #include "chre/core/event_loop_manager.h" 20 #include "chre/platform/assert.h" 21 #include "chre/platform/fatal_error.h" 22 #include "chre/platform/log.h" 23 #include "chre/util/system/debug_dump.h" 24 #include "chre_api/chre/version.h" 25 26 #include <algorithm> 27 28 namespace chre { 29 30 constexpr size_t Nanoapp::kMaxSizeWakeupBuckets; 31 32 Nanoapp::Nanoapp() { 33 // Push first bucket onto wakeup bucket queue 34 cycleWakeupBuckets(1); 35 } 36 37 Nanoapp::~Nanoapp() { 38 const size_t totalAllocatedBytes = getTotalAllocatedBytes(); 39 40 if (totalAllocatedBytes > 0) { 41 // TODO: Consider asserting here 42 LOGE("Nanoapp ID=0x%016" PRIx64 " still has %zu allocated bytes!", 43 getAppId(), totalAllocatedBytes); 44 } 45 } 46 47 bool Nanoapp::isRegisteredForBroadcastEvent(uint16_t eventType) const { 48 return (mRegisteredEvents.find(eventType) != mRegisteredEvents.size()); 49 } 50 51 bool Nanoapp::registerForBroadcastEvent(uint16_t eventId) { 52 if (isRegisteredForBroadcastEvent(eventId)) { 53 return false; 54 } 55 56 if (!mRegisteredEvents.push_back(eventId)) { 57 FATAL_ERROR_OOM(); 58 } 59 60 return true; 61 } 62 63 bool Nanoapp::unregisterForBroadcastEvent(uint16_t eventId) { 64 size_t registeredEventIndex = mRegisteredEvents.find(eventId); 65 if (registeredEventIndex == mRegisteredEvents.size()) { 66 return false; 67 } 68 69 mRegisteredEvents.erase(registeredEventIndex); 70 return true; 71 } 72 73 void Nanoapp::configureNanoappInfoEvents(bool enable) { 74 if (enable) { 75 registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED); 76 registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED); 77 } else { 78 unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED); 79 unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED); 80 } 81 } 82 83 void Nanoapp::configureHostSleepEvents(bool enable) { 84 if (enable) { 85 registerForBroadcastEvent(CHRE_EVENT_HOST_AWAKE); 86 registerForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP); 87 } else { 88 unregisterForBroadcastEvent(CHRE_EVENT_HOST_AWAKE); 89 unregisterForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP); 90 } 91 } 92 93 void Nanoapp::configureDebugDumpEvent(bool enable) { 94 if (enable) { 95 registerForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP); 96 } else { 97 unregisterForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP); 98 } 99 } 100 101 Event *Nanoapp::processNextEvent() { 102 Event *event = mEventQueue.pop(); 103 104 CHRE_ASSERT_LOG(event != nullptr, "Tried delivering event, but queue empty"); 105 if (event != nullptr) { 106 handleEvent(event->senderInstanceId, event->eventType, event->eventData); 107 } 108 109 return event; 110 } 111 112 void Nanoapp::blameHostWakeup() { 113 if (mWakeupBuckets.back() < UINT16_MAX) ++mWakeupBuckets.back(); 114 } 115 116 void Nanoapp::cycleWakeupBuckets(size_t numBuckets) { 117 numBuckets = std::min(numBuckets, kMaxSizeWakeupBuckets); 118 for (size_t i = 0; i < numBuckets; ++i) { 119 if (mWakeupBuckets.full()) { 120 mWakeupBuckets.erase(0); 121 } 122 mWakeupBuckets.push_back(0); 123 } 124 } 125 126 void Nanoapp::logStateToBuffer(DebugDumpWrapper &debugDump) const { 127 debugDump.print(" Id=%" PRIu32 " 0x%016" PRIx64 " ", getInstanceId(), 128 getAppId()); 129 PlatformNanoapp::logStateToBuffer(debugDump); 130 debugDump.print(" v%" PRIu32 ".%" PRIu32 ".%" PRIu32 " tgtAPI=%" PRIu32 131 ".%" PRIu32 " curAlloc=%zu peakAlloc=%zu", 132 CHRE_EXTRACT_MAJOR_VERSION(getAppVersion()), 133 CHRE_EXTRACT_MINOR_VERSION(getAppVersion()), 134 CHRE_EXTRACT_PATCH_VERSION(getAppVersion()), 135 CHRE_EXTRACT_MAJOR_VERSION(getTargetApiVersion()), 136 CHRE_EXTRACT_MINOR_VERSION(getTargetApiVersion()), 137 getTotalAllocatedBytes(), getPeakAllocatedBytes()); 138 debugDump.print(" hostWakeups=[ cur->"); 139 // Get buckets latest -> earliest except last one 140 for (size_t i = mWakeupBuckets.size() - 1; i > 0; --i) { 141 debugDump.print("%" PRIu16 ", ", mWakeupBuckets[i]); 142 } 143 // Earliest bucket gets no comma 144 debugDump.print("%" PRIu16 " ]\n", mWakeupBuckets.front()); 145 } 146 147 } // namespace chre 148