blob: 88a1075f607d828f8e46ea9b970b3ea726d41169 [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#define TLOG_TAG "libbinder"
#include "android-base/logging.h"
#include <trusty_log.h>
#include <iostream>
#include <string>
#include <android-base/strings.h>
namespace android {
namespace base {
static const char* GetFileBasename(const char* file) {
const char* last_slash = strrchr(file, '/');
if (last_slash != nullptr) {
return last_slash + 1;
}
return file;
}
// This splits the message up line by line, by calling log_function with a pointer to the start of
// each line and the size up to the newline character. It sends size = -1 for the final line.
template <typename F, typename... Args>
static void SplitByLines(const char* msg, const F& log_function, Args&&... args) {
const char* newline;
while ((newline = strchr(msg, '\n')) != nullptr) {
log_function(msg, newline - msg, args...);
msg = newline + 1;
}
log_function(msg, -1, args...);
}
void DefaultAborter(const char* abort_message) {
TLOGC("aborting: %s\n", abort_message);
abort();
}
static void TrustyLogLine(const char* msg, int /*length*/, android::base::LogSeverity severity,
const char* tag) {
switch (severity) {
case VERBOSE:
case DEBUG:
TLOGD("%s: %s\n", tag, msg);
break;
case INFO:
TLOGI("%s: %s\n", tag, msg);
break;
case WARNING:
TLOGW("%s: %s\n", tag, msg);
break;
case ERROR:
TLOGE("%s: %s\n", tag, msg);
break;
case FATAL_WITHOUT_ABORT:
case FATAL:
TLOGC("%s: %s\n", tag, msg);
break;
}
}
void TrustyLogger(android::base::LogId, android::base::LogSeverity severity, const char* tag,
const char*, unsigned int, const char* full_message) {
SplitByLines(full_message, TrustyLogLine, severity, tag);
}
// This indirection greatly reduces the stack impact of having lots of
// checks/logging in a function.
class LogMessageData {
public:
LogMessageData(const char* file, unsigned int line, LogSeverity severity, const char* tag,
int error)
: file_(GetFileBasename(file)),
line_number_(line),
severity_(severity),
tag_(tag),
error_(error) {}
const char* GetFile() const { return file_; }
unsigned int GetLineNumber() const { return line_number_; }
LogSeverity GetSeverity() const { return severity_; }
const char* GetTag() const { return tag_; }
int GetError() const { return error_; }
std::ostream& GetBuffer() { return buffer_; }
std::string ToString() const { return buffer_.str(); }
private:
std::ostringstream buffer_;
const char* const file_;
const unsigned int line_number_;
const LogSeverity severity_;
const char* const tag_;
const int error_;
DISALLOW_COPY_AND_ASSIGN(LogMessageData);
};
LogMessage::LogMessage(const char* file, unsigned int line, LogId, LogSeverity severity,
const char* tag, int error)
: LogMessage(file, line, severity, tag, error) {}
LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, const char* tag,
int error)
: data_(new LogMessageData(file, line, severity, tag, error)) {}
LogMessage::~LogMessage() {
// Check severity again. This is duplicate work wrt/ LOG macros, but not LOG_STREAM.
if (!WOULD_LOG(data_->GetSeverity())) {
return;
}
// Finish constructing the message.
if (data_->GetError() != -1) {
data_->GetBuffer() << ": " << strerror(data_->GetError());
}
std::string msg(data_->ToString());
LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), data_->GetTag(),
msg.c_str());
// Abort if necessary.
if (data_->GetSeverity() == FATAL) {
DefaultAborter(msg.c_str());
}
}
std::ostream& LogMessage::stream() {
return data_->GetBuffer();
}
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
const char* message) {
TrustyLogger(DEFAULT, severity, tag ?: "<unknown>", file, line, message);
}
bool ShouldLog(LogSeverity /*severity*/, const char* /*tag*/) {
// This is controlled by Trusty's log level.
return true;
}
} // namespace base
} // namespace android