Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/meson_videoserver/display/DispAdptLog.cpp
T

340 lines
8.1 KiB
C++

/*
* Copyright (C) 2024 Amlogic Corporation.
*
* 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 <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstdarg>
#include <cstring>
#include <fcntl.h>
#include <sys/time.h>
#include <cstdint>
#include <sstream>
#include <unordered_map>
#ifdef DISPLAY_LOGLIB
#include <cutils/log.h>
#endif
#include "DispAdptLog.h"
#include "MesonTypes.h"
typedef struct log_info {
int active_level; // debug log level
FILE *print_out; // log output file
FILE *trace_file; // trace output file
bool alog; // output log to logcat
int trace_to_log; // trace output to logcat
int di_number; // di number
int di_log; // enable di log
} log_info_t;
log_info_t g_log = {
.active_level = DEFAULT_LOG_LEVEL,
.print_out = NULL,
.trace_file = NULL,
.alog = true,
.trace_to_log = 0,
.di_number = -1,
.di_log = -1,
};
log_info_t *getLogInfo()
{
return &g_log;
}
FILE *getDebugFile()
{
log_info_t *log = getLogInfo();
if (!log->print_out)
return stderr;
return log->print_out;
}
long long DispAdptGetCurrentTime(void)
{
long long utcCurrentTimeMillis;
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
utcCurrentTimeMillis = ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL;
return utcCurrentTimeMillis;
}
long long DispAdptGetCurrentTimeUs(void)
{
long long utcCurrentTimeUs;
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
utcCurrentTimeUs = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL;
return utcCurrentTimeUs;
}
static void FilePrint(FILE *f, const char* fmt, va_list args)
{
if (f == NULL)
return;
fprintf(f, "%lld: pid: %d ", DispAdptGetCurrentTime(), getpid());
vfprintf(f, fmt, args);
fflush(f);
}
#ifdef DISPLAY_LOGLIB
void LogPrint(FILE *f, bool alog, const char* fmt, va_list args)
{
if (alog) {
DispAdptLogPrint(ANDROID_LOG_INFO, DISPLAY_TAG, fmt, args);
} else {
FilePrint(f, fmt, args);
}
}
#else
void LogPrint(FILE *f, bool alog, const char* fmt, va_list args)
{
(void)alog;
FilePrint(f, fmt, args);
}
#endif
void DispAdptLog(int level, const char *fmt, ...)
{
log_info_t *log = getLogInfo();
if (log && level <= log->active_level) {
va_list argptr;
va_start(argptr, fmt);
LogPrint(getDebugFile(), log->alog, fmt, argptr);
va_end(argptr);
}
}
void TracePrint(const char *fmt, ...)
{
log_info_t *log = getLogInfo();
if (log == NULL)
return;
va_list argptr;
va_start(argptr, fmt);
LogPrint(log->trace_file, log->trace_to_log, fmt, argptr);
va_end(argptr);
}
void reset()
{
log_info_t *log = getLogInfo();
log->active_level = DEFAULT_LOG_LEVEL;
log->di_number = -1;
log->di_log = -1;
log->alog = true;
if (log->print_out)
fclose(log->print_out);
log->print_out = NULL;
}
void DispAdptLogInit()
{
char buf[MESON_MAX_STR_LEN] = { 0 };
char path[MESON_MAX_STR_LEN] = { 0 };
log_info_t *log = getLogInfo();
snprintf(path, sizeof(path), "%s/%s", ADPT_LISTENER_DIR, DEBUG_LOG);
if (DispAdptReadFile(path, buf, true, MESON_MAX_STR_LEN) == 0) {
reset();
DispAdptDebugSetting(buf);
}
const char *env = getenv("DISPLAY_DEBUG_FILE");
if (env && log->print_out == NULL) {
if (!strcmp(env, "stdout"))
log->print_out = stdout;
else
log->print_out = fopen(env, "w");
}
if (log->active_level < 0)
log->active_level = DEFAULT_LOG_LEVEL;
env = getenv("DISPLAY_DEBUG");
if (env) {
log->active_level = atoi(env);
}
}
int DispAdptReadFile(const char *path, char *val, bool original, int valSize)
{
char buf[MESON_MAX_STR_LEN] = { 0 };
int fd, len;
if ((fd = open(path, O_RDONLY)) < 0) {
DISPLAY_LOGE("open %s fail. Error info [%s]", path, strerror(errno));
return -errno;
}
len = read(fd, buf, MESON_MAX_STR_LEN - 1);
close(fd);
if (len < 0) {
DISPLAY_LOGE("read error: %s, %s\n", path, strerror(errno));
return -errno;
}
if (!original) {
int i, j;
for (i = 0, j = 0; i <= len - 1; i++) {
/*
* change '\0' to 0x20(spacing), otherwise the string buffer will be cut off
* if the last char is '\0' should not replace it
*/
if (0x0 == buf[i] && i < len - 1) {
buf[i] = 0x20;
DISPLAY_LOGD("read buffer index:%d is a 0x0, replace to spacing \n", i);
}
/* delete all the character of '\n' and '\r'*/
if (0x0a != buf[i] && 0x0d != buf[i]) {
buf[j++] = buf[i];
}
}
buf[j] = 0x0;
}
DISPLAY_LOGD("read %s, result length:%d, val:%s\n", path, len, buf);
strncpy(val, buf, valSize);
return 0;
}
int DispAdptWriteFile(const char *path, const char *val)
{
int fd;
if ((fd = open(path, O_RDWR)) < 0) {
DISPLAY_LOGE("open %s fail. Error info [%s]", path, strerror(errno));
return -errno;
}
DISPLAY_LOGD("%s: write (%s) to file (%s)", __func__, val, path);
if (write(fd, val, strlen(val)) != (int)strlen(val))
DISPLAY_LOGE("write %s failed!\n", path);
close(fd);
return 0;
}
int DispAdptGetDiNumber()
{
log_info_t *log = getLogInfo();
return log->di_number;
}
int DispAdptGetDiLog()
{
log_info_t *log = getLogInfo();
return log->di_log;
}
std::unordered_map<std::string, std::string> parseKeyValue(const std::string& input) {
std::unordered_map<std::string, std::string> result;
std::stringstream ss(input);
std::string key, value;
std::string kvPair;
while (ss >> kvPair) {
size_t eqPos = kvPair.find('=');
if (eqPos != std::string::npos) {
key = kvPair.substr(0, eqPos);
value = kvPair.substr(eqPos + 1);
result[key] = value;
}
}
return result;
}
int DispAdptDebugSetting(char *content)
{
auto parsed = parseKeyValue(content);
log_info_t *log = getLogInfo();
for (const auto& pair : parsed) {
if (pair.first == "DISPLAY_DEBUG")
log->active_level = atoi(pair.second.c_str());
if (pair.first == "DISPLAY_DEBUG_FILE") {
if (log->print_out == NULL)
log->print_out = fopen(pair.second.c_str(), "a");
}
if (pair.first == "DI_NUMBER")
log->di_number = atoi(pair.second.c_str());
if (pair.first == "DI_LOG")
log->di_log = atoi(pair.second.c_str());
if (pair.first == "ALOG")
log->alog = atoi(pair.second.c_str()) > 0 ? true : false;
if (pair.first == "TRACE")
log->trace_to_log = atoi(pair.second.c_str()) > 1 ? true : false;
if (pair.first == "TRACE_FILE")
log->trace_file = fopen(pair.second.c_str(), "w");
}
return 0;
}
void DispAdptLogDestroy()
{
log_info_t *log = getLogInfo();
if (log != NULL) {
if (log->print_out)
fclose(log->print_out);
log->print_out = NULL;
if (log->trace_file)
fclose(log->trace_file);
log->trace_file = NULL;
}
}
#ifdef DISPLAY_LOGLIB
void DispAdptLogPrint(int prio, const char* tag, const char* fmt, va_list args)
{
char buf[1024];
int len;
len = snprintf(buf, sizeof(buf), "[%lld] ", DispAdptGetCurrentTime());
len = vsnprintf(buf + len, sizeof(buf) - len, fmt, args);
if (len >= 0 && len < (int)sizeof(buf))
__android_log_print(prio, tag, "%s", buf);
else
__android_log_print(prio, tag, "[TRUNCATED]%s", buf);
}
#endif