aboutsummaryrefslogtreecommitdiff
path: root/core/debug_dump_manager.cc
blob: a82478b697b1372209ec8dba4bd66fa0f5f2c614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * 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) {
  uint32_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 %" PRIu32
         " 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
  logSettingStateToBuffer(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