• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <endian.h>
18 #include <cstdio>
19 
20 #include "chre/util/time.h"
21 #include "chre_host/log_message_parser_base.h"
22 
23 using chre::kOneMillisecondInNanoseconds;
24 using chre::kOneSecondInMilliseconds;
25 
26 namespace android {
27 namespace chre {
28 
29 namespace {
30 #if defined(LOG_NDEBUG) || LOG_NDEBUG != 0
31 constexpr bool kVerboseLoggingEnabled = true;
32 #else
33 constexpr bool kVerboseLoggingEnabled = false;
34 #endif
35 }  // anonymous namespace
36 
ChreLogMessageParserBase()37 ChreLogMessageParserBase::ChreLogMessageParserBase()
38     : mVerboseLoggingEnabled(kVerboseLoggingEnabled) {}
39 
dump(const uint8_t * buffer,size_t size)40 void ChreLogMessageParserBase::dump(const uint8_t *buffer, size_t size) {
41   if (mVerboseLoggingEnabled) {
42     char line[32];
43     char lineChars[32];
44     int offset = 0;
45     int offsetChars = 0;
46 
47     size_t orig_size = size;
48     if (size > 128) {
49       size = 128;
50       LOGV("Dumping first 128 bytes of buffer of size %zu", orig_size);
51     } else {
52       LOGV("Dumping buffer of size %zu bytes", size);
53     }
54     for (size_t i = 1; i <= size; ++i) {
55       offset += snprintf(&line[offset], sizeof(line) - offset, "%02x ",
56                          buffer[i - 1]);
57       offsetChars +=
58           snprintf(&lineChars[offsetChars], sizeof(lineChars) - offsetChars,
59                    "%c", (isprint(buffer[i - 1])) ? buffer[i - 1] : '.');
60       if ((i % 8) == 0) {
61         LOGV("  %s\t%s", line, lineChars);
62         offset = 0;
63         offsetChars = 0;
64       } else if ((i % 4) == 0) {
65         offset += snprintf(&line[offset], sizeof(line) - offset, " ");
66       }
67     }
68 
69     if (offset > 0) {
70       char tabs[8];
71       char *pos = tabs;
72       while (offset < 28) {
73         *pos++ = '\t';
74         offset += 8;
75       }
76       *pos = '\0';
77       LOGV("  %s%s%s", line, tabs, lineChars);
78     }
79   }
80 }
81 
chreLogLevelToAndroidLogPriority(uint8_t level)82 android_LogPriority ChreLogMessageParserBase::chreLogLevelToAndroidLogPriority(
83     uint8_t level) {
84   switch (level) {
85     case LogLevel::ERROR:
86       return ANDROID_LOG_ERROR;
87     case LogLevel::WARNING:
88       return ANDROID_LOG_WARN;
89     case LogLevel::INFO:
90       return ANDROID_LOG_INFO;
91     case LogLevel::DEBUG:
92       return ANDROID_LOG_DEBUG;
93     default:
94       return ANDROID_LOG_SILENT;
95   }
96 }
97 
log(const uint8_t * logBuffer,size_t logBufferSize)98 void ChreLogMessageParserBase::log(const uint8_t *logBuffer,
99                                    size_t logBufferSize) {
100   size_t bufferIndex = 0;
101   while (bufferIndex < logBufferSize) {
102     const LogMessage *message =
103         reinterpret_cast<const LogMessage *>(&logBuffer[bufferIndex]);
104     uint64_t timeNs = le64toh(message->timestampNanos);
105     emitLogMessage(message->logLevel, timeNs / kOneMillisecondInNanoseconds,
106                    message->logMessage);
107     bufferIndex += sizeof(LogMessage) +
108                    strnlen(message->logMessage, logBufferSize - bufferIndex) +
109                    1;
110   }
111 }
112 
logV2(const uint8_t * logBuffer,size_t logBufferSize,uint32_t numLogsDropped)113 void ChreLogMessageParserBase::logV2(const uint8_t *logBuffer,
114                                      size_t logBufferSize,
115                                      uint32_t numLogsDropped) {
116   size_t bufferIndex = 0;
117   if (numLogsDropped < mNumLogsDropped) {
118     LOGE(
119         "The numLogsDropped value received from CHRE is less than the last "
120         "value received. Received: %" PRIu32 " Last value: %" PRIu32,
121         numLogsDropped, mNumLogsDropped);
122   }
123   // Log the number of logs dropped once before logging remaining logs from CHRE
124   uint32_t diffLogsDropped = numLogsDropped - mNumLogsDropped;
125   mNumLogsDropped = numLogsDropped;
126   if (diffLogsDropped > 0) {
127     LOGI("# logs dropped: %" PRIu32, diffLogsDropped);
128   }
129   while (bufferIndex < logBufferSize) {
130     const LogMessageV2 *message =
131         reinterpret_cast<const LogMessageV2 *>(&logBuffer[bufferIndex]);
132     emitLogMessage(message->logLevel, le32toh(message->timestampMillis),
133                    message->logMessage);
134     bufferIndex += sizeof(LogMessageV2) +
135                    strnlen(message->logMessage, logBufferSize - bufferIndex) +
136                    1;
137   }
138 }
139 
emitLogMessage(uint8_t level,uint32_t timestampMillis,const char * logMessage)140 void ChreLogMessageParserBase::emitLogMessage(uint8_t level,
141                                               uint32_t timestampMillis,
142                                               const char *logMessage) {
143   constexpr const char kLogTag[] = "CHRE";
144   uint32_t timeSec = timestampMillis / kOneSecondInMilliseconds;
145   uint32_t timeMsRemainder = timestampMillis % kOneSecondInMilliseconds;
146   android_LogPriority priority = chreLogLevelToAndroidLogPriority(level);
147   LOG_PRI(priority, kLogTag, kHubLogFormatStr, timeSec, timeMsRemainder,
148           logMessage);
149 }
150 
151 }  // namespace chre
152 }  // namespace android
153