134 lines
4.9 KiB
C++
134 lines
4.9 KiB
C++
/*
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "chre/core/debug_dump_manager.h"
|
|
|
|
#include <cstring>
|
|
|
|
#include "chre/core/event_loop_manager.h"
|
|
#include "chre/core/settings.h"
|
|
|
|
namespace chre {
|
|
|
|
void DebugDumpManager::trigger() {
|
|
auto callback = [](uint16_t /*type*/, void * /*data*/, void * /*extraData*/) {
|
|
DebugDumpManager &debugDumpManager =
|
|
EventLoopManagerSingleton::get()->getDebugDumpManager();
|
|
debugDumpManager.collectFrameworkDebugDumps();
|
|
debugDumpManager.sendFrameworkDebugDumps();
|
|
};
|
|
|
|
// Collect CHRE framework debug dumps.
|
|
EventLoopManagerSingleton::get()->deferCallback(
|
|
SystemCallbackType::PerformDebugDump, nullptr /*data*/, callback);
|
|
|
|
auto nappCallback = [](uint16_t /*eventType*/, void * /*eventData*/) {
|
|
EventLoopManagerSingleton::get()
|
|
->getDebugDumpManager()
|
|
.sendNanoappDebugDumps();
|
|
};
|
|
|
|
// Notify nanoapps to collect debug dumps.
|
|
EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
|
|
CHRE_EVENT_DEBUG_DUMP, nullptr /*eventData*/, nappCallback);
|
|
}
|
|
|
|
void DebugDumpManager::appendNanoappLog(const Nanoapp &nanoapp,
|
|
const char *formatStr, va_list args) {
|
|
uint16_t instanceId = nanoapp.getInstanceId();
|
|
|
|
// Note this check isn't exact as it's possible that the nanoapp isn't
|
|
// handling CHRE_EVENT_DEBUG_DUMP. This approximate check is used for its low
|
|
// complexity as it doesn't introduce any real harms.
|
|
if (!mCollectingNanoappDebugDumps) {
|
|
LOGW("Nanoapp instance %" PRIu16
|
|
" logging debug data while not in an active debug dump session",
|
|
instanceId);
|
|
} else if (formatStr != nullptr) {
|
|
// Log nanoapp info the first time it adds debug data in this session.
|
|
if (!mLastNanoappId.has_value() || mLastNanoappId.value() != instanceId) {
|
|
mLastNanoappId = instanceId;
|
|
mDebugDump.print("\n\n %s 0x%016" PRIx64 ":\n", nanoapp.getAppName(),
|
|
nanoapp.getAppId());
|
|
}
|
|
|
|
mDebugDump.printVaList(formatStr, args);
|
|
}
|
|
}
|
|
|
|
void DebugDumpManager::collectFrameworkDebugDumps() {
|
|
auto *eventLoopManager = EventLoopManagerSingleton::get();
|
|
eventLoopManager->getMemoryManager().logStateToBuffer(mDebugDump);
|
|
eventLoopManager->getEventLoop().handleNanoappWakeupBuckets();
|
|
eventLoopManager->getEventLoop().logStateToBuffer(mDebugDump);
|
|
#ifdef CHRE_SENSORS_SUPPORT_ENABLED
|
|
eventLoopManager->getSensorRequestManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_SENSORS_SUPPORT_ENABLED
|
|
#ifdef CHRE_GNSS_SUPPORT_ENABLED
|
|
eventLoopManager->getGnssManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_GNSS_SUPPORT_ENABLED
|
|
#ifdef CHRE_WIFI_SUPPORT_ENABLED
|
|
eventLoopManager->getWifiRequestManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_WIFI_SUPPORT_ENABLED
|
|
#ifdef CHRE_WWAN_SUPPORT_ENABLED
|
|
eventLoopManager->getWwanRequestManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_WWAN_SUPPORT_ENABLED
|
|
#ifdef CHRE_AUDIO_SUPPORT_ENABLED
|
|
eventLoopManager->getAudioRequestManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_AUDIO_SUPPORT_ENABLED
|
|
#ifdef CHRE_BLE_SUPPORT_ENABLED
|
|
eventLoopManager->getBleRequestManager().logStateToBuffer(mDebugDump);
|
|
#endif // CHRE_BLE_SUPPORT_ENABLED
|
|
eventLoopManager->getSettingManager().logStateToBuffer(mDebugDump);
|
|
logStateToBuffer(mDebugDump);
|
|
}
|
|
|
|
void DebugDumpManager::sendFrameworkDebugDumps() {
|
|
for (size_t i = 0; i < mDebugDump.getBuffers().size(); i++) {
|
|
const auto &buff = mDebugDump.getBuffers()[i];
|
|
sendDebugDump(buff.get(), false /*complete*/);
|
|
}
|
|
|
|
// Clear out buffers before nanoapp debug dumps to reduce peak memory usage.
|
|
mDebugDump.clear();
|
|
|
|
// Mark the beginning of nanoapp debug dumps
|
|
mDebugDump.print("\n\nNanoapp debug dumps:");
|
|
mCollectingNanoappDebugDumps = true;
|
|
}
|
|
|
|
void DebugDumpManager::sendNanoappDebugDumps() {
|
|
// Avoid buffer underflow when mDebugDump failed to allocate buffers.
|
|
size_t numBuffers = mDebugDump.getBuffers().size();
|
|
if (numBuffers > 0) {
|
|
for (size_t i = 0; i < numBuffers - 1; i++) {
|
|
const auto &buff = mDebugDump.getBuffers()[i];
|
|
sendDebugDump(buff.get(), false /*complete*/);
|
|
}
|
|
}
|
|
|
|
const char *debugStr =
|
|
(numBuffers > 0) ? mDebugDump.getBuffers().back().get() : "";
|
|
sendDebugDump(debugStr, true /*complete*/);
|
|
|
|
// Clear current session debug dumps and release memory.
|
|
mDebugDump.clear();
|
|
mLastNanoappId.reset();
|
|
mCollectingNanoappDebugDumps = false;
|
|
}
|
|
|
|
} // namespace chre
|