blob: 88a1075f607d828f8e46ea9b970b3ea726d41169 [file] [log] [blame]
Andrei Homescu74a54452021-12-10 05:30:21 +00001/*
2 * Copyright (C) 2022 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#define TLOG_TAG "libbinder"
18
19#include "android-base/logging.h"
20
21#include <trusty_log.h>
22#include <iostream>
23#include <string>
24
Andrei Homescu74a54452021-12-10 05:30:21 +000025#include <android-base/strings.h>
26
27namespace android {
28namespace base {
29
30static const char* GetFileBasename(const char* file) {
31 const char* last_slash = strrchr(file, '/');
32 if (last_slash != nullptr) {
33 return last_slash + 1;
34 }
35 return file;
36}
37
38// This splits the message up line by line, by calling log_function with a pointer to the start of
39// each line and the size up to the newline character. It sends size = -1 for the final line.
40template <typename F, typename... Args>
41static void SplitByLines(const char* msg, const F& log_function, Args&&... args) {
42 const char* newline;
43 while ((newline = strchr(msg, '\n')) != nullptr) {
44 log_function(msg, newline - msg, args...);
45 msg = newline + 1;
46 }
47
48 log_function(msg, -1, args...);
49}
50
51void DefaultAborter(const char* abort_message) {
52 TLOGC("aborting: %s\n", abort_message);
53 abort();
54}
55
Andrei Homescu875996f2022-08-24 04:25:11 +000056static void TrustyLogLine(const char* msg, int /*length*/, android::base::LogSeverity severity,
Andrei Homescu74a54452021-12-10 05:30:21 +000057 const char* tag) {
58 switch (severity) {
59 case VERBOSE:
60 case DEBUG:
61 TLOGD("%s: %s\n", tag, msg);
62 break;
63 case INFO:
64 TLOGI("%s: %s\n", tag, msg);
65 break;
66 case WARNING:
67 TLOGW("%s: %s\n", tag, msg);
68 break;
69 case ERROR:
70 TLOGE("%s: %s\n", tag, msg);
71 break;
72 case FATAL_WITHOUT_ABORT:
73 case FATAL:
74 TLOGC("%s: %s\n", tag, msg);
75 break;
76 }
77}
78
79void TrustyLogger(android::base::LogId, android::base::LogSeverity severity, const char* tag,
80 const char*, unsigned int, const char* full_message) {
81 SplitByLines(full_message, TrustyLogLine, severity, tag);
82}
83
84// This indirection greatly reduces the stack impact of having lots of
85// checks/logging in a function.
86class LogMessageData {
87public:
88 LogMessageData(const char* file, unsigned int line, LogSeverity severity, const char* tag,
89 int error)
90 : file_(GetFileBasename(file)),
91 line_number_(line),
92 severity_(severity),
93 tag_(tag),
94 error_(error) {}
95
96 const char* GetFile() const { return file_; }
97
98 unsigned int GetLineNumber() const { return line_number_; }
99
100 LogSeverity GetSeverity() const { return severity_; }
101
102 const char* GetTag() const { return tag_; }
103
104 int GetError() const { return error_; }
105
106 std::ostream& GetBuffer() { return buffer_; }
107
108 std::string ToString() const { return buffer_.str(); }
109
110private:
111 std::ostringstream buffer_;
112 const char* const file_;
113 const unsigned int line_number_;
114 const LogSeverity severity_;
115 const char* const tag_;
116 const int error_;
117
118 DISALLOW_COPY_AND_ASSIGN(LogMessageData);
119};
120
121LogMessage::LogMessage(const char* file, unsigned int line, LogId, LogSeverity severity,
122 const char* tag, int error)
123 : LogMessage(file, line, severity, tag, error) {}
124
125LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, const char* tag,
126 int error)
127 : data_(new LogMessageData(file, line, severity, tag, error)) {}
128
129LogMessage::~LogMessage() {
130 // Check severity again. This is duplicate work wrt/ LOG macros, but not LOG_STREAM.
131 if (!WOULD_LOG(data_->GetSeverity())) {
132 return;
133 }
134
135 // Finish constructing the message.
136 if (data_->GetError() != -1) {
137 data_->GetBuffer() << ": " << strerror(data_->GetError());
138 }
139 std::string msg(data_->ToString());
140
141 LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), data_->GetTag(),
142 msg.c_str());
143
144 // Abort if necessary.
145 if (data_->GetSeverity() == FATAL) {
146 DefaultAborter(msg.c_str());
147 }
148}
149
150std::ostream& LogMessage::stream() {
151 return data_->GetBuffer();
152}
153
154void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
155 const char* message) {
156 TrustyLogger(DEFAULT, severity, tag ?: "<unknown>", file, line, message);
157}
158
Andrei Homescu875996f2022-08-24 04:25:11 +0000159bool ShouldLog(LogSeverity /*severity*/, const char* /*tag*/) {
Andrei Homescu74a54452021-12-10 05:30:21 +0000160 // This is controlled by Trusty's log level.
161 return true;
162}
163
164} // namespace base
165} // namespace android