blob: cda69ed8a84c119d2d32c32a8a69d47b0be75efe [file] [log] [blame]
/*
* Copyright (C) 2017 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/util/system/debug_dump.h"
#include <cinttypes>
#include <cstdio>
#include "chre/platform/log.h"
namespace chre {
void DebugDumpWrapper::print(const char *formatStr, ...) {
va_list argList;
va_start(argList, formatStr);
printVaList(formatStr, argList);
va_end(argList);
}
void DebugDumpWrapper::printVaList(const char *formatStr, va_list argList) {
va_list argListCopy;
va_copy(argListCopy, argList);
if (mCurrBuff != nullptr || allocNewBuffer()) {
bool sizeValid;
size_t sizeOfStr;
if (!insertString(formatStr, argList, &sizeValid, &sizeOfStr)) {
if (!sizeValid) {
LOGE("Error inserting string into buffer in debug dump");
} else if (sizeOfStr >= kBuffSize) {
LOGE(
"String was too large to fit in a single buffer for debug dump "
"print");
} else if (allocNewBuffer()) {
// Insufficient space left in buffer, allocate a new one and it's
// guaranteed to succeed.
bool success =
insertString(formatStr, argListCopy, &sizeValid, &sizeOfStr);
CHRE_ASSERT(success);
}
}
}
va_end(argListCopy);
}
bool DebugDumpWrapper::allocNewBuffer() {
mCurrBuff = static_cast<char *>(memoryAlloc(kBuffSize));
if (mCurrBuff == nullptr) {
LOG_OOM();
} else {
mBuffers.emplace_back(mCurrBuff);
mBuffPos = 0;
mCurrBuff[0] = '\0';
}
return mCurrBuff != nullptr;
}
bool DebugDumpWrapper::insertString(const char *formatStr, va_list argList,
bool *sizeValid, size_t *sizeOfStr) {
CHRE_ASSERT(mCurrBuff != nullptr);
CHRE_ASSERT(mBuffPos <= kBuffSize);
// Buffer space left
size_t spaceLeft = kBuffSize - mBuffPos;
// Note strLen doesn't count the terminating null character.
int strLen = vsnprintf(&mCurrBuff[mBuffPos], spaceLeft, formatStr, argList);
size_t strSize = static_cast<size_t>(strLen);
bool success = false;
*sizeValid = false;
if (strLen >= 0) {
*sizeValid = true;
if (strSize >= spaceLeft) {
// Chop off the incomplete string.
mCurrBuff[mBuffPos] = '\0';
} else {
success = true;
mBuffPos += strSize;
}
}
*sizeOfStr = strSize;
return success;
}
void DebugDumpWrapper::logErrorHistogram(const uint32_t *histogram,
uint8_t histogramLength) {
print(" [");
for (int i = 0; i < histogramLength; i++) {
print("%" PRIu32, histogram[i]);
if (i < histogramLength - 1) {
print(",");
}
}
print("]\n");
}
} // namespace chre