1 /*
2 * Copyright (C) 2016 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 "log.h"
18
19 #include <cctype>
20 #include <chrono>
21 #include <cstdio>
22 #include <string>
23
24 namespace android {
25
26 Log::LogLevel Log::level_;
27 Logger* Log::logger_;
28 std::chrono::time_point<std::chrono::steady_clock> Log::init_time_;
29
Initialize(Logger * logger,LogLevel level)30 void Log::Initialize(Logger *logger, LogLevel level) {
31 if (Log::logger_) {
32 Log::Warn("Re-initializing logger");
33 }
34 Log::init_time_ = std::chrono::steady_clock::now();
35 Log::logger_ = logger;
36 Log::SetLevel(level);
37 }
38
SetLevel(LogLevel level)39 void Log::SetLevel(LogLevel level) {
40 Log::level_ = level;
41 }
42
43 #define LOG_EX_VARARGS(level, format) \
44 do { \
45 va_list arg_list; \
46 va_start(arg_list, format); \
47 Log::LogEx(level, format, arg_list); \
48 va_end(arg_list); \
49 } while (0)
50
Error(const char * format,...)51 void Log::Error(const char *format, ...) {
52 LOG_EX_VARARGS(LogLevel::Error, format);
53 }
54
Warn(const char * format,...)55 void Log::Warn(const char *format, ...) {
56 LOG_EX_VARARGS(LogLevel::Warn, format);
57 }
58
Info(const char * format,...)59 void Log::Info(const char *format, ...) {
60 LOG_EX_VARARGS(LogLevel::Info, format);
61 }
62
Debug(const char * format,...)63 void Log::Debug(const char *format, ...) {
64 LOG_EX_VARARGS(LogLevel::Debug, format);
65 }
66
DebugBuf(std::vector<uint8_t> vec)67 void Log::DebugBuf(std::vector<uint8_t> vec) {
68 Log::DebugBuf(vec.data(), vec.size());
69 }
70
DebugBuf(const uint8_t * buffer,size_t size)71 void Log::DebugBuf(const uint8_t *buffer, size_t size) {
72 if (Log::level_ < LogLevel::Debug) {
73 return;
74 }
75
76 char line[32];
77 int offset = 0;
78 char line_chars[32];
79 int offset_chars = 0;
80
81 Log::Debug("Dumping buffer of size %zu bytes", size);
82 for (size_t i = 1; i <= size; ++i) {
83 offset += snprintf(&line[offset], sizeof(line) - offset, "%02x ",
84 buffer[i - 1]);
85 offset_chars += snprintf(
86 &line_chars[offset_chars], sizeof(line_chars) - offset_chars,
87 "%c", (isprint(buffer[i - 1])) ? buffer[i - 1] : '.');
88 if ((i % 8) == 0) {
89 Log::Debug(" %s\t%s", line, line_chars);
90 offset = 0;
91 offset_chars = 0;
92 } else if ((i % 4) == 0) {
93 offset += snprintf(&line[offset], sizeof(line) - offset, " ");
94 }
95 }
96
97 if (offset > 0) {
98 std::string tabs;
99 while (offset < 28) {
100 tabs += "\t";
101 offset += 8;
102 }
103 Log::Debug(" %s%s%s", line, tabs.c_str(), line_chars);
104 }
105 }
106
LevelAbbrev(LogLevel level)107 char Log::LevelAbbrev(LogLevel level) {
108 switch (level) {
109 case LogLevel::Error:
110 return 'E';
111 case LogLevel::Warn:
112 return 'W';
113 case LogLevel::Info:
114 return 'I';
115 case LogLevel::Debug:
116 return 'D';
117 default:
118 return '?';
119 }
120 }
121
LogEx(LogLevel level,const char * format,va_list arg_list)122 void Log::LogEx(LogLevel level, const char *format, va_list arg_list) {
123 if (Log::level_ < level) {
124 return;
125 }
126
127 std::chrono::duration<float> log_time =
128 (std::chrono::steady_clock::now() - Log::init_time_);
129
130 // Can add colorization here if desired (should be configurable)
131 char prefix[20];
132 snprintf(prefix, sizeof(prefix), "%c %6.03f: ", Log::LevelAbbrev(level),
133 log_time.count());
134
135 Log::logger_->Output(prefix);
136 Log::logger_->Output(format, arg_list);
137 Log::logger_->Output("\n");
138 }
139
Output(const char * str)140 void PrintfLogger::Output(const char *str) {
141 printf("%s", str);
142 }
143
Output(const char * format,va_list arg_list)144 void PrintfLogger::Output(const char *format, va_list arg_list) {
145 vprintf(format, arg_list);
146 }
147
148 } // namespace android
149