liblog: simplify logd 'command' functions and struct logger
There are a set of functions, such as android_logger_get_log_size() and android_logger_get_prune_list() that talk to the logd command socket to perform their activities. There's a transport abstraction layer that handles these symbols to optionally route them to other transports, originally designed for pstore or local logger; however these functions fundamentally only make sense for logd. Ideally, these functions would be removed and new functions would be added that do not depend on struct logger_list or struct logger and more clearly indicate that they only work with logd. For example: android_logger_get_size(struct logger*) could be logd_get_buffer_size(log_id_t log_id). We would remove the need to 'open' the struct logger and make it clear that it only operates on logd. Since liblog is an llndk library however, we cannot change or remove these symbols. Since these symbols are not frequently used, it seems acceptable to keep them as is and not introduce improved versions. We, however, do want to simplify the code that handles them and this change removes the transport abstraction layer that handles them. They retain the behavior that unless the struct logger_list was opened for logd, that the functions return -EINVAL. The one exception to this is android_logger_clear(). If the struct logger provided to this function was opened from a struct logger_list that used pstore for its mode argument, this function will clear the entire pstore log. This function does not respect the 'logId' parameter of the struct logger, since that would not be possible. This change removes this android_logger_clear() behavior and makes it strictly for logd, for symmetry with the rest of the functions and due to the lack of clarity regarding the 'logId' parameter of its input. The only caller of this function, logcat, will clear pstore directly. struct logger was built to encapsulate the information needed to connect to a logger device from the old kernel logger. Now that we only support reading from pstore and from logd, there is much less information needed to be captured. Specifically, we only need to know the log_id and whether or not it was opened as part of a pstore or logd 'list'. Test: liblog-unit-test Test: logcat -c/-g/-G/-p/-P/-S work Test: logcat -c works with -L Test: logcat -g/-G/-p/-P/-S continue to fail with -L Change-Id: I2c549b6f8539de94510e223949ab209ecc40e2d0
This commit is contained in:
parent
828db1a901
commit
9156c534e0
10 changed files with 134 additions and 361 deletions
|
|
@ -494,7 +494,7 @@ void android_closeEventTagMap(EventTagMap* map) {
|
|||
|
||||
// Cache miss, go to logd to acquire a public reference.
|
||||
// Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map?
|
||||
static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
|
||||
static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) {
|
||||
// call event tag service to arrange for a new tag
|
||||
char* buf = NULL;
|
||||
// Can not use android::base::StringPrintf, asprintf + free instead.
|
||||
|
|
@ -515,8 +515,9 @@ static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
|
|||
} else {
|
||||
size = ret;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
// Ask event log tag service for an existing entry
|
||||
if (__send_log_msg(buf, size) >= 0) {
|
||||
if (SendLogdControlMessage(buf, size) >= 0) {
|
||||
buf[size - 1] = '\0';
|
||||
char* ep;
|
||||
unsigned long val = strtoul(buf, &ep, 10); // return size
|
||||
|
|
@ -529,6 +530,7 @@ static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(buf);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -618,8 +620,9 @@ int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char*
|
|||
} else {
|
||||
size = ret;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
// Ask event log tag service for an allocation
|
||||
if (__send_log_msg(buf, size) >= 0) {
|
||||
if (SendLogdControlMessage(buf, size) >= 0) {
|
||||
buf[size - 1] = '\0';
|
||||
unsigned long val = strtoul(buf, &cp, 10); // return size
|
||||
if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK
|
||||
|
|
@ -635,6 +638,7 @@ int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char*
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -650,10 +650,6 @@ int fakeLogOpen(const char* pathName) {
|
|||
return fd;
|
||||
}
|
||||
|
||||
ssize_t __send_log_msg(char*, size_t) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int __android_log_is_loggable(int prio, const char*, int def) {
|
||||
int logLevel = def;
|
||||
return logLevel >= 0 && prio >= logLevel;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ int fakeLogOpen(const char* pathName);
|
|||
int fakeLogClose(int fd);
|
||||
ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
|
||||
|
||||
ssize_t __send_log_msg(char*, size_t);
|
||||
int __android_log_is_loggable(int prio, const char*, int def);
|
||||
int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
|
||||
int __android_log_is_debuggable();
|
||||
|
|
|
|||
|
|
@ -40,39 +40,16 @@
|
|||
#include "logger.h"
|
||||
|
||||
static int LogdAvailable(log_id_t LogId);
|
||||
static int LogdVersion(struct logger* logger, struct android_log_transport_context* transp);
|
||||
static int LogdRead(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
struct log_msg* log_msg);
|
||||
static int LogdPoll(struct logger_list* logger_list, struct android_log_transport_context* transp);
|
||||
static void LogdClose(struct logger_list* logger_list,
|
||||
struct android_log_transport_context* transp);
|
||||
static int LogdClear(struct logger* logger, struct android_log_transport_context* transp);
|
||||
static ssize_t LogdSetSize(struct logger* logger, struct android_log_transport_context* transp,
|
||||
size_t size);
|
||||
static ssize_t LogdGetSize(struct logger* logger, struct android_log_transport_context* transp);
|
||||
static ssize_t LogdGetReadableSize(struct logger* logger,
|
||||
struct android_log_transport_context* transp);
|
||||
static ssize_t LogdGetPrune(struct logger_list* logger,
|
||||
struct android_log_transport_context* transp, char* buf, size_t len);
|
||||
static ssize_t LogdSetPrune(struct logger_list* logger,
|
||||
struct android_log_transport_context* transp, char* buf, size_t len);
|
||||
static ssize_t LogdGetStats(struct logger_list* logger,
|
||||
struct android_log_transport_context* transp, char* buf, size_t len);
|
||||
|
||||
struct android_log_transport_read logdLoggerRead = {
|
||||
.name = "logd",
|
||||
.available = LogdAvailable,
|
||||
.version = LogdVersion,
|
||||
.close = LogdClose,
|
||||
.read = LogdRead,
|
||||
.poll = LogdPoll,
|
||||
.clear = LogdClear,
|
||||
.setSize = LogdSetSize,
|
||||
.getSize = LogdGetSize,
|
||||
.getReadableSize = LogdGetReadableSize,
|
||||
.getPrune = LogdGetPrune,
|
||||
.setPrune = LogdSetPrune,
|
||||
.getStats = LogdGetStats,
|
||||
};
|
||||
|
||||
static int LogdAvailable(log_id_t logId) {
|
||||
|
|
@ -116,7 +93,7 @@ static int socket_local_client(const std::string& name, int type) {
|
|||
}
|
||||
|
||||
/* worker for sending the command to the logger */
|
||||
static ssize_t send_log_msg(struct logger* logger, const char* msg, char* buf, size_t buf_size) {
|
||||
ssize_t SendLogdControlMessage(char* buf, size_t buf_size) {
|
||||
ssize_t ret;
|
||||
size_t len;
|
||||
char* cp;
|
||||
|
|
@ -126,10 +103,6 @@ static ssize_t send_log_msg(struct logger* logger, const char* msg, char* buf, s
|
|||
return sock;
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
|
||||
}
|
||||
|
||||
len = strlen(buf) + 1;
|
||||
ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
|
||||
if (ret <= 0) {
|
||||
|
|
@ -180,10 +153,6 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
ssize_t __send_log_msg(char* buf, size_t buf_size) {
|
||||
return send_log_msg(NULL, NULL, buf, buf_size);
|
||||
}
|
||||
|
||||
static int check_log_success(char* buf, ssize_t ret) {
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
@ -197,17 +166,28 @@ static int check_log_success(char* buf, ssize_t ret) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int LogdClear(struct logger* logger, struct android_log_transport_context*) {
|
||||
int android_logger_clear(struct logger* logger) {
|
||||
if (!android_logger_is_logd(logger)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
uint32_t log_id = android_logger_get_id(logger);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "clear %" PRIu32, log_id);
|
||||
|
||||
return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
|
||||
return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
/* returns the total size of the log's ring buffer */
|
||||
static ssize_t LogdGetSize(struct logger* logger, struct android_log_transport_context*) {
|
||||
char buf[512];
|
||||
long android_logger_get_log_size(struct logger* logger) {
|
||||
if (!android_logger_is_logd(logger)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
|
||||
uint32_t log_id = android_logger_get_id(logger);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "getLogSize %" PRIu32, log_id);
|
||||
|
||||
ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -219,23 +199,32 @@ static ssize_t LogdGetSize(struct logger* logger, struct android_log_transport_c
|
|||
return atol(buf);
|
||||
}
|
||||
|
||||
static ssize_t LogdSetSize(struct logger* logger, struct android_log_transport_context*,
|
||||
size_t size) {
|
||||
int android_logger_set_log_size(struct logger* logger, unsigned long size) {
|
||||
if (!android_logger_is_logd(logger)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t log_id = android_logger_get_id(logger);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "setLogSize %" PRIu32 " %lu", log_id, size);
|
||||
|
||||
snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
|
||||
|
||||
return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
|
||||
return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the readable size of the log's ring buffer (that is, amount of the
|
||||
* log consumed)
|
||||
*/
|
||||
static ssize_t LogdGetReadableSize(struct logger* logger, struct android_log_transport_context*) {
|
||||
char buf[512];
|
||||
long android_logger_get_log_readable_size(struct logger* logger) {
|
||||
if (!android_logger_is_logd(logger)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
|
||||
uint32_t log_id = android_logger_get_id(logger);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "getLogSizeUsed %" PRIu32, log_id);
|
||||
|
||||
ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -247,20 +236,15 @@ static ssize_t LogdGetReadableSize(struct logger* logger, struct android_log_tra
|
|||
return atol(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the logger version
|
||||
*/
|
||||
static int LogdVersion(struct logger*, struct android_log_transport_context*) {
|
||||
uid_t uid = __android_log_uid();
|
||||
return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
|
||||
int android_logger_get_log_version(struct logger*) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns statistics
|
||||
*/
|
||||
static ssize_t LogdGetStats(struct logger_list* logger_list, struct android_log_transport_context*,
|
||||
char* buf, size_t len) {
|
||||
struct logger* logger;
|
||||
ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
if (logger_list->mode & ANDROID_LOG_PSTORE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
char* cp = buf;
|
||||
size_t remaining = len;
|
||||
size_t n;
|
||||
|
|
@ -270,27 +254,35 @@ static ssize_t LogdGetStats(struct logger_list* logger_list, struct android_log_
|
|||
remaining -= n;
|
||||
cp += n;
|
||||
|
||||
logger_for_each(logger, logger_list) {
|
||||
n = snprintf(cp, remaining, " %d", logger->logId);
|
||||
n = MIN(n, remaining);
|
||||
remaining -= n;
|
||||
cp += n;
|
||||
for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
|
||||
if ((1 << log_id) & logger_list->log_mask) {
|
||||
n = snprintf(cp, remaining, " %zu", log_id);
|
||||
n = MIN(n, remaining);
|
||||
remaining -= n;
|
||||
cp += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger_list->pid) {
|
||||
snprintf(cp, remaining, " pid=%u", logger_list->pid);
|
||||
}
|
||||
|
||||
return send_log_msg(NULL, NULL, buf, len);
|
||||
return SendLogdControlMessage(buf, len);
|
||||
}
|
||||
ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
if (logger_list->mode & ANDROID_LOG_PSTORE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(buf, len, "getPruneList");
|
||||
return SendLogdControlMessage(buf, len);
|
||||
}
|
||||
|
||||
static ssize_t LogdGetPrune(struct logger_list*, struct android_log_transport_context*, char* buf,
|
||||
size_t len) {
|
||||
return send_log_msg(NULL, "getPruneList", buf, len);
|
||||
}
|
||||
int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
if (logger_list->mode & ANDROID_LOG_PSTORE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t LogdSetPrune(struct logger_list*, struct android_log_transport_context*, char* buf,
|
||||
size_t len) {
|
||||
const char cmd[] = "setPruneList ";
|
||||
const size_t cmdlen = sizeof(cmd) - 1;
|
||||
|
||||
|
|
@ -301,11 +293,10 @@ static ssize_t LogdSetPrune(struct logger_list*, struct android_log_transport_co
|
|||
buf[len - 1] = '\0';
|
||||
memcpy(buf, cmd, cmdlen);
|
||||
|
||||
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
|
||||
return check_log_success(buf, SendLogdControlMessage(buf, len));
|
||||
}
|
||||
|
||||
static int logdOpen(struct logger_list* logger_list, struct android_log_transport_context* transp) {
|
||||
struct logger* logger;
|
||||
char buffer[256], *cp, c;
|
||||
int ret, remaining, sock;
|
||||
|
||||
|
|
@ -333,12 +324,15 @@ static int logdOpen(struct logger_list* logger_list, struct android_log_transpor
|
|||
cp += 5;
|
||||
c = '=';
|
||||
remaining = sizeof(buffer) - (cp - buffer);
|
||||
logger_for_each(logger, logger_list) {
|
||||
ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
|
||||
ret = MIN(ret, remaining);
|
||||
remaining -= ret;
|
||||
cp += ret;
|
||||
c = ',';
|
||||
|
||||
for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
|
||||
if ((1 << log_id) & logger_list->log_mask) {
|
||||
ret = snprintf(cp, remaining, "%c%zu", c, log_id);
|
||||
ret = MIN(ret, remaining);
|
||||
remaining -= ret;
|
||||
cp += ret;
|
||||
c = ',';
|
||||
}
|
||||
}
|
||||
|
||||
if (logger_list->tail) {
|
||||
|
|
@ -412,27 +406,6 @@ static int LogdRead(struct logger_list* logger_list, struct android_log_transpor
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int LogdPoll(struct logger_list* logger_list, struct android_log_transport_context* transp) {
|
||||
struct pollfd p;
|
||||
|
||||
int ret = logdOpen(logger_list, transp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.fd = ret;
|
||||
p.events = POLLIN;
|
||||
ret = poll(&p, 1, 20);
|
||||
if ((ret > 0) && !(p.revents & POLLIN)) {
|
||||
ret = 0;
|
||||
}
|
||||
if ((ret == -1) && errno) {
|
||||
return -errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Close all the logs */
|
||||
static void LogdClose(struct logger_list*, struct android_log_transport_context* transp) {
|
||||
int sock = atomic_exchange(&transp->context.sock, -1);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,6 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
ssize_t __send_log_msg(char* buf, size_t buf_size);
|
||||
ssize_t SendLogdControlMessage(char* buf, size_t buf_size);
|
||||
|
||||
__END_DECLS
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ struct android_log_transport_read {
|
|||
|
||||
/* Does not cause resources to be taken */
|
||||
int (*available)(log_id_t logId);
|
||||
int (*version)(struct logger* logger, struct android_log_transport_context* transp);
|
||||
/* Release resources taken by the following interfaces */
|
||||
void (*close)(struct logger_list* logger_list, struct android_log_transport_context* transp);
|
||||
/*
|
||||
|
|
@ -62,53 +61,37 @@ struct android_log_transport_read {
|
|||
*/
|
||||
int (*read)(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
struct log_msg* log_msg);
|
||||
/* Must only be called if not ANDROID_LOG_NONBLOCK (blocking) */
|
||||
int (*poll)(struct logger_list* logger_list, struct android_log_transport_context* transp);
|
||||
|
||||
int (*clear)(struct logger* logger, struct android_log_transport_context* transp);
|
||||
ssize_t (*setSize)(struct logger* logger, struct android_log_transport_context* transp,
|
||||
size_t size);
|
||||
ssize_t (*getSize)(struct logger* logger, struct android_log_transport_context* transp);
|
||||
ssize_t (*getReadableSize)(struct logger* logger, struct android_log_transport_context* transp);
|
||||
|
||||
ssize_t (*getPrune)(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
char* buf, size_t len);
|
||||
ssize_t (*setPrune)(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
char* buf, size_t len);
|
||||
ssize_t (*getStats)(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
char* buf, size_t len);
|
||||
};
|
||||
|
||||
struct android_log_transport_context {
|
||||
union android_log_context_union context; /* zero init per-transport context */
|
||||
|
||||
struct android_log_transport_read* transport;
|
||||
unsigned logMask; /* mask of requested log buffers */
|
||||
};
|
||||
|
||||
struct logger_list {
|
||||
struct listnode logger;
|
||||
android_log_transport_context transport_context;
|
||||
bool transport_initialized;
|
||||
int mode;
|
||||
unsigned int tail;
|
||||
log_time start;
|
||||
pid_t pid;
|
||||
uint32_t log_mask;
|
||||
};
|
||||
|
||||
struct logger {
|
||||
struct listnode node;
|
||||
struct logger_list* parent;
|
||||
// Format for a 'logger' entry: uintptr_t where only the bottom 32 bits are used.
|
||||
// bit 31: Set if this 'logger' is for logd.
|
||||
// bit 30: Set if this 'logger' is for pmsg
|
||||
// bits 0-2: the decimal value of the log buffer.
|
||||
// Other bits are unused.
|
||||
|
||||
log_id_t logId;
|
||||
};
|
||||
#define LOGGER_LOGD (1 << 31)
|
||||
#define LOGGER_PMSG (1 << 30)
|
||||
#define LOGGER_LOG_ID_MASK ((1 << 3) - 1)
|
||||
|
||||
/* assumes caller has structures read-locked, single threaded, or fenced */
|
||||
#define logger_for_each(logp, logger_list) \
|
||||
for ((logp) = node_to_item((logger_list)->logger.next, struct logger, node); \
|
||||
((logp) != node_to_item(&(logger_list)->logger, struct logger, node)) && \
|
||||
((logp)->parent == (logger_list)); \
|
||||
(logp) = node_to_item((logp)->node.next, struct logger, node))
|
||||
inline bool android_logger_is_logd(struct logger* logger) {
|
||||
return reinterpret_cast<uintptr_t>(logger) & LOGGER_LOGD;
|
||||
}
|
||||
|
||||
/* OS specific dribs and drabs */
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -32,211 +33,53 @@
|
|||
#include "log_portability.h"
|
||||
#include "logger.h"
|
||||
|
||||
/* android_logger_alloc unimplemented, no use case */
|
||||
/* android_logger_free not exported */
|
||||
static void android_logger_free(struct logger* logger) {
|
||||
if (!logger) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_remove(&logger->node);
|
||||
|
||||
free(logger);
|
||||
}
|
||||
|
||||
/* android_logger_alloc unimplemented, no use case */
|
||||
|
||||
/* method for getting the associated sublog id */
|
||||
log_id_t android_logger_get_id(struct logger* logger) {
|
||||
return ((struct logger*)logger)->logId;
|
||||
return static_cast<log_id_t>(reinterpret_cast<uintptr_t>(logger) & LOGGER_LOG_ID_MASK);
|
||||
}
|
||||
|
||||
static int init_transport_context(struct logger_list* logger_list) {
|
||||
static struct logger_list* android_logger_list_alloc_internal(int mode, unsigned int tail,
|
||||
log_time start, pid_t pid) {
|
||||
auto* logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(struct logger_list)));
|
||||
if (!logger_list) {
|
||||
return -EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (list_empty(&logger_list->logger)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (logger_list->transport_initialized) {
|
||||
return 0;
|
||||
}
|
||||
logger_list->mode = mode;
|
||||
logger_list->start = start;
|
||||
logger_list->tail = tail;
|
||||
logger_list->pid = pid;
|
||||
|
||||
#if (FAKE_LOG_DEVICE == 0)
|
||||
extern struct android_log_transport_read logdLoggerRead;
|
||||
extern struct android_log_transport_read pmsgLoggerRead;
|
||||
|
||||
struct android_log_transport_read* transport;
|
||||
transport = (logger_list->mode & ANDROID_LOG_PSTORE) ? &pmsgLoggerRead : &logdLoggerRead;
|
||||
|
||||
struct logger* logger;
|
||||
unsigned logMask = 0;
|
||||
|
||||
logger_for_each(logger, logger_list) {
|
||||
log_id_t logId = logger->logId;
|
||||
|
||||
if (logId == LOG_ID_SECURITY && __android_log_uid() != AID_SYSTEM) {
|
||||
continue;
|
||||
}
|
||||
if (transport->read && (!transport->available || transport->available(logId) >= 0)) {
|
||||
logMask |= 1 << logId;
|
||||
}
|
||||
}
|
||||
if (!logMask) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
logger_list->transport_context.transport = transport;
|
||||
logger_list->transport_context.logMask = logMask;
|
||||
logger_list->transport_context.transport =
|
||||
(mode & ANDROID_LOG_PSTORE) ? &pmsgLoggerRead : &logdLoggerRead;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LOGGER_FUNCTION(logger, def, func, args...) \
|
||||
ssize_t ret = -EINVAL; \
|
||||
\
|
||||
if (!logger) { \
|
||||
return ret; \
|
||||
} \
|
||||
ret = init_transport_context(logger->parent); \
|
||||
if (ret < 0) { \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
ret = (def); \
|
||||
android_log_transport_context* transport_context = &logger->parent->transport_context; \
|
||||
if (transport_context->logMask & (1 << logger->logId) && transport_context->transport && \
|
||||
transport_context->transport->func) { \
|
||||
ssize_t retval = (transport_context->transport->func)(logger, transport_context, ##args); \
|
||||
if (ret >= 0 || ret == (def)) { \
|
||||
ret = retval; \
|
||||
} \
|
||||
} \
|
||||
return ret
|
||||
|
||||
int android_logger_clear(struct logger* logger) {
|
||||
LOGGER_FUNCTION(logger, -ENODEV, clear);
|
||||
}
|
||||
|
||||
/* returns the total size of the log's ring buffer */
|
||||
long android_logger_get_log_size(struct logger* logger) {
|
||||
LOGGER_FUNCTION(logger, -ENODEV, getSize);
|
||||
}
|
||||
|
||||
int android_logger_set_log_size(struct logger* logger, unsigned long size) {
|
||||
LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the readable size of the log's ring buffer (that is, amount of the
|
||||
* log consumed)
|
||||
*/
|
||||
long android_logger_get_log_readable_size(struct logger* logger) {
|
||||
LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the logger version
|
||||
*/
|
||||
int android_logger_get_log_version(struct logger* logger) {
|
||||
LOGGER_FUNCTION(logger, 4, version);
|
||||
}
|
||||
|
||||
#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
|
||||
ssize_t ret = init_transport_context(logger_list); \
|
||||
if (ret < 0) { \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
ret = (def); \
|
||||
android_log_transport_context* transport_context = &logger_list->transport_context; \
|
||||
if (transport_context->transport && transport_context->transport->func) { \
|
||||
ssize_t retval = (transport_context->transport->func)(logger_list, transport_context, ##args); \
|
||||
if (ret >= 0 || ret == (def)) { \
|
||||
ret = retval; \
|
||||
} \
|
||||
} \
|
||||
return ret
|
||||
|
||||
/*
|
||||
* returns statistics
|
||||
*/
|
||||
ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
|
||||
}
|
||||
|
||||
ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
|
||||
}
|
||||
|
||||
int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
|
||||
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
|
||||
return logger_list;
|
||||
}
|
||||
|
||||
struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
|
||||
struct logger_list* logger_list;
|
||||
|
||||
logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(*logger_list)));
|
||||
if (!logger_list) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(&logger_list->logger);
|
||||
logger_list->mode = mode;
|
||||
logger_list->tail = tail;
|
||||
logger_list->pid = pid;
|
||||
|
||||
return logger_list;
|
||||
return android_logger_list_alloc_internal(mode, tail, log_time(0, 0), pid);
|
||||
}
|
||||
|
||||
struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid) {
|
||||
struct logger_list* logger_list;
|
||||
|
||||
logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(*logger_list)));
|
||||
if (!logger_list) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(&logger_list->logger);
|
||||
logger_list->mode = mode;
|
||||
logger_list->start = start;
|
||||
logger_list->pid = pid;
|
||||
|
||||
return logger_list;
|
||||
return android_logger_list_alloc_internal(mode, 0, start, pid);
|
||||
}
|
||||
|
||||
/* android_logger_list_register unimplemented, no use case */
|
||||
/* android_logger_list_unregister unimplemented, no use case */
|
||||
|
||||
/* Open the named log and add it to the logger list */
|
||||
struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) {
|
||||
struct logger* logger;
|
||||
|
||||
if (!logger_list || (logId >= LOG_ID_MAX)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
logger_for_each(logger, logger_list) {
|
||||
if (logger->logId == logId) {
|
||||
return reinterpret_cast<struct logger*>(logger);
|
||||
}
|
||||
}
|
||||
logger_list->log_mask |= 1 << logId;
|
||||
|
||||
logger = static_cast<struct logger*>(calloc(1, sizeof(*logger)));
|
||||
if (!logger) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
logger->logId = logId;
|
||||
list_add_tail(&logger_list->logger, &logger->node);
|
||||
logger->parent = logger_list;
|
||||
|
||||
// Reset known transport to re-evaluate, since we added a new logger.
|
||||
logger_list->transport_initialized = false;
|
||||
|
||||
return logger;
|
||||
uintptr_t logger = logId;
|
||||
logger |= (logger_list->mode & ANDROID_LOG_PSTORE) ? LOGGER_PMSG : LOGGER_LOGD;
|
||||
return reinterpret_cast<struct logger*>(logger);
|
||||
}
|
||||
|
||||
/* Open the single named log and make it part of a new logger list */
|
||||
|
|
@ -256,10 +99,14 @@ struct logger_list* android_logger_list_open(log_id_t logId, int mode, unsigned
|
|||
return logger_list;
|
||||
}
|
||||
|
||||
/* Validate log_msg packet, read function has already been null checked */
|
||||
static int android_transport_read(struct logger_list* logger_list,
|
||||
struct android_log_transport_context* transp,
|
||||
struct log_msg* log_msg) {
|
||||
int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
|
||||
if (logger_list == nullptr || logger_list->transport_context.transport == nullptr ||
|
||||
logger_list->log_mask == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
android_log_transport_context* transp = &logger_list->transport_context;
|
||||
|
||||
int ret = (*transp->transport->read)(logger_list, transp, log_msg);
|
||||
|
||||
if (ret < 0) {
|
||||
|
|
@ -285,17 +132,6 @@ static int android_transport_read(struct logger_list* logger_list,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Read from the selected logs */
|
||||
int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
|
||||
int ret = init_transport_context(logger_list);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
android_log_transport_context* transport_context = &logger_list->transport_context;
|
||||
return android_transport_read(logger_list, transport_context, log_msg);
|
||||
}
|
||||
|
||||
/* Close all the logs */
|
||||
void android_logger_list_free(struct logger_list* logger_list) {
|
||||
if (logger_list == NULL) {
|
||||
|
|
@ -308,11 +144,5 @@ void android_logger_list_free(struct logger_list* logger_list) {
|
|||
(*transport_context->transport->close)(logger_list, transport_context);
|
||||
}
|
||||
|
||||
while (!list_empty(&logger_list->logger)) {
|
||||
struct listnode* node = list_head(&logger_list->logger);
|
||||
struct logger* logger = node_to_item(node, struct logger, node);
|
||||
android_logger_free((struct logger*)logger);
|
||||
}
|
||||
|
||||
free(logger_list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,27 +27,16 @@
|
|||
#include "logger.h"
|
||||
|
||||
static int PmsgAvailable(log_id_t logId);
|
||||
static int PmsgVersion(struct logger* logger, struct android_log_transport_context* transp);
|
||||
static int PmsgRead(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
struct log_msg* log_msg);
|
||||
static void PmsgClose(struct logger_list* logger_list,
|
||||
struct android_log_transport_context* transp);
|
||||
static int PmsgClear(struct logger* logger, struct android_log_transport_context* transp);
|
||||
|
||||
struct android_log_transport_read pmsgLoggerRead = {
|
||||
.name = "pmsg",
|
||||
.available = PmsgAvailable,
|
||||
.version = PmsgVersion,
|
||||
.close = PmsgClose,
|
||||
.read = PmsgRead,
|
||||
.poll = NULL,
|
||||
.clear = PmsgClear,
|
||||
.setSize = NULL,
|
||||
.getSize = NULL,
|
||||
.getReadableSize = NULL,
|
||||
.getPrune = NULL,
|
||||
.setPrune = NULL,
|
||||
.getStats = NULL,
|
||||
};
|
||||
|
||||
static int PmsgAvailable(log_id_t logId) {
|
||||
|
|
@ -60,17 +49,6 @@ static int PmsgAvailable(log_id_t logId) {
|
|||
return -EBADF;
|
||||
}
|
||||
|
||||
static int PmsgClear(struct logger*, struct android_log_transport_context*) {
|
||||
return unlink("/sys/fs/pstore/pmsg-ramoops-0");
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the logger version
|
||||
*/
|
||||
static int PmsgVersion(struct logger*, struct android_log_transport_context*) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int PmsgRead(struct logger_list* logger_list, struct android_log_transport_context* transp,
|
||||
struct log_msg* log_msg) {
|
||||
ssize_t ret;
|
||||
|
|
@ -134,7 +112,7 @@ static int PmsgRead(struct logger_list* logger_list, struct android_log_transpor
|
|||
}
|
||||
preread_count = 0;
|
||||
|
||||
if ((transp->logMask & (1 << buf.l.id)) &&
|
||||
if ((logger_list->log_mask & (1 << buf.l.id)) &&
|
||||
((!logger_list->start.tv_sec && !logger_list->start.tv_nsec) ||
|
||||
((logger_list->start.tv_sec <= buf.l.realtime.tv_sec) &&
|
||||
((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
|
||||
|
|
@ -232,12 +210,12 @@ ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio, const char* pref
|
|||
memset(&transp, 0, sizeof(transp));
|
||||
|
||||
logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
|
||||
transp.logMask = (unsigned)-1;
|
||||
logger_list.log_mask = (unsigned)-1;
|
||||
if (logId != LOG_ID_ANY) {
|
||||
transp.logMask = (1 << logId);
|
||||
logger_list.log_mask = (1 << logId);
|
||||
}
|
||||
transp.logMask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
|
||||
if (!transp.logMask) {
|
||||
logger_list.log_mask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
|
||||
if (!logger_list.log_mask) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -913,7 +913,7 @@ static void BM_lookupEventTagNum(benchmark::State& state) {
|
|||
}
|
||||
BENCHMARK(BM_lookupEventTagNum);
|
||||
|
||||
// Must be functionally identical to liblog internal __send_log_msg.
|
||||
// Must be functionally identical to liblog internal SendLogdControlMessage()
|
||||
static void send_to_control(char* buf, size_t len) {
|
||||
int sock =
|
||||
socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM | SOCK_CLOEXEC);
|
||||
|
|
|
|||
|
|
@ -969,6 +969,16 @@ int Logcat::Run(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (mode & ANDROID_LOG_PSTORE) {
|
||||
if (clearLog) {
|
||||
unlink("/sys/fs/pstore/pmsg-ramoops-0");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
|
||||
LogcatPanic(HELP_TRUE, "-L is incompatible with -g/-G, -S, and -p/-P");
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
|
||||
nullptr, &android_logger_list_free};
|
||||
if (tail_time != log_time::EPOCH) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue