1 /* 2 * Copyright (C) 2020 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/debug_dump_manager.h" 18 19 #include <cstring> 20 21 #include "chre/core/event_loop_manager.h" 22 #include "chre/core/settings.h" 23 24 namespace chre { 25 26 void DebugDumpManager::trigger() { 27 auto callback = [](uint16_t /*eventType*/, void * /*eventData*/) { 28 DebugDumpManager &debugDumpManager = 29 EventLoopManagerSingleton::get()->getDebugDumpManager(); 30 debugDumpManager.collectFrameworkDebugDumps(); 31 debugDumpManager.sendFrameworkDebugDumps(); 32 }; 33 34 // Collect CHRE framework debug dumps. 35 EventLoopManagerSingleton::get()->deferCallback( 36 SystemCallbackType::PerformDebugDump, nullptr /*data*/, callback); 37 38 auto nappCallback = [](uint16_t /*eventType*/, void * /*eventData*/) { 39 EventLoopManagerSingleton::get() 40 ->getDebugDumpManager() 41 .sendNanoappDebugDumps(); 42 }; 43 44 // Notify nanoapps to collect debug dumps. 45 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 46 CHRE_EVENT_DEBUG_DUMP, nullptr /*eventData*/, nappCallback); 47 } 48 49 void DebugDumpManager::appendNanoappLog(const Nanoapp &nanoapp, 50 const char *formatStr, va_list args) { 51 uint32_t instanceId = nanoapp.getInstanceId(); 52 53 // Note this check isn't exact as it's possible that the nanoapp isn't 54 // handling CHRE_EVENT_DEBUG_DUMP. This approximate check is used for its low 55 // complexity as it doesn't introduce any real harms. 56 if (!mCollectingNanoappDebugDumps) { 57 LOGW("Nanoapp instance %" PRIu32 58 " logging debug data while not in an active debug dump session", 59 instanceId); 60 } else if (formatStr != nullptr) { 61 // Log nanoapp info the first time it adds debug data in this session. 62 if (!mLastNanoappId.has_value() || mLastNanoappId.value() != instanceId) { 63 mLastNanoappId = instanceId; 64 mDebugDump.print("\n\n %s 0x%016" PRIx64 ":\n", nanoapp.getAppName(), 65 nanoapp.getAppId()); 66 } 67 68 mDebugDump.print(formatStr, args); 69 } 70 } 71 72 void DebugDumpManager::collectFrameworkDebugDumps() { 73 auto *eventLoopManager = EventLoopManagerSingleton::get(); 74 eventLoopManager->getMemoryManager().logStateToBuffer(mDebugDump); 75 eventLoopManager->getEventLoop().handleNanoappWakeupBuckets(); 76 eventLoopManager->getEventLoop().logStateToBuffer(mDebugDump); 77 eventLoopManager->getSensorRequestManager().logStateToBuffer(mDebugDump); 78 #ifdef CHRE_GNSS_SUPPORT_ENABLED 79 eventLoopManager->getGnssManager().logStateToBuffer(mDebugDump); 80 #endif // CHRE_GNSS_SUPPORT_ENABLED 81 #ifdef CHRE_WIFI_SUPPORT_ENABLED 82 eventLoopManager->getWifiRequestManager().logStateToBuffer(mDebugDump); 83 #endif // CHRE_WIFI_SUPPORT_ENABLED 84 #ifdef CHRE_WWAN_SUPPORT_ENABLED 85 eventLoopManager->getWwanRequestManager().logStateToBuffer(mDebugDump); 86 #endif // CHRE_WWAN_SUPPORT_ENABLED 87 #ifdef CHRE_AUDIO_SUPPORT_ENABLED 88 eventLoopManager->getAudioRequestManager().logStateToBuffer(mDebugDump); 89 #endif // CHRE_AUDIO_SUPPORT_ENABLED 90 logSettingStateToBuffer(mDebugDump); 91 } 92 93 void DebugDumpManager::sendFrameworkDebugDumps() { 94 for (size_t i = 0; i < mDebugDump.getBuffers().size(); i++) { 95 const auto &buff = mDebugDump.getBuffers()[i]; 96 sendDebugDump(buff.get(), false /*complete*/); 97 } 98 99 // Clear out buffers before nanoapp debug dumps to reduce peak memory usage. 100 mDebugDump.clear(); 101 102 // Mark the beginning of nanoapp debug dumps 103 mDebugDump.print("\n\nNanoapp debug dumps:"); 104 mCollectingNanoappDebugDumps = true; 105 } 106 107 void DebugDumpManager::sendNanoappDebugDumps() { 108 // Avoid buffer underflow when mDebugDump failed to allocate buffers. 109 size_t numBuffers = mDebugDump.getBuffers().size(); 110 if (numBuffers > 0) { 111 for (size_t i = 0; i < numBuffers - 1; i++) { 112 const auto &buff = mDebugDump.getBuffers()[i]; 113 sendDebugDump(buff.get(), false /*complete*/); 114 } 115 } 116 117 const char *debugStr = 118 (numBuffers > 0) ? mDebugDump.getBuffers().back().get() : ""; 119 sendDebugDump(debugStr, true /*complete*/); 120 121 // Clear current session debug dumps and release memory. 122 mDebugDump.clear(); 123 mLastNanoappId.reset(); 124 mCollectingNanoappDebugDumps = false; 125 } 126 127 } // namespace chre 128