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
trigger()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
appendNanoappLog(const Nanoapp & nanoapp,const char * formatStr,va_list args)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
collectFrameworkDebugDumps()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
sendFrameworkDebugDumps()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
sendNanoappDebugDumps()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