blob: 3de5002edb99931c0380ee46810a0b33d8c86c1c [file] [log] [blame]
/*
* 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 <endian.h>
#include <cstdio>
#include "chre_host/log_message_parser_base.h"
namespace android {
namespace chre {
namespace {
#if defined(LOG_NDEBUG) || LOG_NDEBUG != 0
constexpr bool kVerboseLoggingEnabled = true;
#else
constexpr bool kVerboseLoggingEnabled = false;
#endif
} // anonymous namespace
ChreLogMessageParserBase::ChreLogMessageParserBase()
: mVerboseLoggingEnabled(kVerboseLoggingEnabled) {}
void ChreLogMessageParserBase::dump(const uint8_t *buffer, size_t size) {
if (mVerboseLoggingEnabled) {
char line[32];
char lineChars[32];
int offset = 0;
int offsetChars = 0;
size_t orig_size = size;
if (size > 128) {
size = 128;
LOGV("Dumping first 128 bytes of buffer of size %zu", orig_size);
} else {
LOGV("Dumping buffer of size %zu bytes", size);
}
for (size_t i = 1; i <= size; ++i) {
offset += snprintf(&line[offset], sizeof(line) - offset, "%02x ",
buffer[i - 1]);
offsetChars +=
snprintf(&lineChars[offsetChars], sizeof(lineChars) - offsetChars,
"%c", (isprint(buffer[i - 1])) ? buffer[i - 1] : '.');
if ((i % 8) == 0) {
LOGV(" %s\t%s", line, lineChars);
offset = 0;
offsetChars = 0;
} else if ((i % 4) == 0) {
offset += snprintf(&line[offset], sizeof(line) - offset, " ");
}
}
if (offset > 0) {
char tabs[8];
char *pos = tabs;
while (offset < 28) {
*pos++ = '\t';
offset += 8;
}
*pos = '\0';
LOGV(" %s%s%s", line, tabs, lineChars);
}
}
}
android_LogPriority ChreLogMessageParserBase::chreLogLevelToAndroidLogPriority(
uint8_t level) {
switch (level) {
case LogLevel::ERROR:
return ANDROID_LOG_ERROR;
case LogLevel::WARNING:
return ANDROID_LOG_WARN;
case LogLevel::INFO:
return ANDROID_LOG_INFO;
case LogLevel::DEBUG:
return ANDROID_LOG_DEBUG;
default:
return ANDROID_LOG_SILENT;
}
}
void ChreLogMessageParserBase::log(const uint8_t *logBuffer,
size_t logBufferSize) {
size_t bufferIndex = 0;
while (bufferIndex < logBufferSize) {
const LogMessage *message =
reinterpret_cast<const LogMessage *>(&logBuffer[bufferIndex]);
emitLogMessage(message->logLevel, le64toh(message->timestampNanos),
message->logMessage);
bufferIndex += sizeof(LogMessage) +
strnlen(message->logMessage, logBufferSize - bufferIndex) +
1;
}
}
void ChreLogMessageParserBase::emitLogMessage(uint8_t level,
uint64_t timestampNanos,
const char *logMessage) {
constexpr const char kLogTag[] = "CHRE";
constexpr const uint64_t kNanosPerSec = 1e9;
constexpr const uint64_t kNanosPerMsec = 1e6;
uint32_t timeSec = timestampNanos / kNanosPerSec;
timestampNanos -= (timeSec * kNanosPerSec);
uint32_t timeMsec = timestampNanos / kNanosPerMsec;
android_LogPriority priority = chreLogLevelToAndroidLogPriority(level);
LOG_PRI(priority, kLogTag, kHubLogFormatStr, timeSec, timeMsec, logMessage);
}
} // namespace chre
} // namespace android