You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
7.5 KiB
263 lines
7.5 KiB
#include <dirent.h> |
|
#include <errno.h> |
|
#include <fcntl.h> |
|
#include <poll.h> |
|
#include <sched.h> |
|
#include <semaphore.h> |
|
#include <signal.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <sys/capability.h> |
|
#include <sys/klog.h> |
|
#include <sys/prctl.h> |
|
#include <sys/resource.h> |
|
#include <sys/stat.h> |
|
#include <sys/types.h> |
|
#include <syslog.h> |
|
#include <unistd.h> |
|
|
|
#include <cstdbool> |
|
#include <memory> |
|
|
|
#include <android-base/macros.h> |
|
#include <cutils/android_get_control_file.h> |
|
#include <cutils/properties.h> |
|
#include <cutils/sched_policy.h> |
|
#include <cutils/sockets.h> |
|
#include <log/event_tag_map.h> |
|
#include <packagelistparser/packagelistparser.h> |
|
#include <private/android_filesystem_config.h> |
|
#include <private/android_logger.h> |
|
#include <utils/threads.h> |
|
|
|
#include "CommandListener.h" |
|
#include "LogAudit.h" |
|
#include "LogBuffer.h" |
|
#include "LogKlog.h" |
|
#include "LogListener.h" |
|
#include "LogUtils.h" |
|
|
|
#ifdef MTK_LOGD_ENHANCE |
|
#define INTERVAL 5LL |
|
#define MAX_COUNT 25 |
|
void prdebug_ratelimit(const char* fmt, ...) { |
|
static int cnt = 0; |
|
static int miss_cnt = 0; |
|
static struct timespec ts_0 = {0, 0}; |
|
struct timespec ts_1; |
|
int64_t differ = 0; |
|
|
|
if (cnt == 0) { |
|
clock_gettime(CLOCK_MONOTONIC, &ts_0); |
|
} |
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts_1); |
|
|
|
differ = ts_1.tv_sec - ts_0.tv_sec; |
|
|
|
// if more than MAX_COUNT entry msg during (INTERVAL - 1, INTERVAL + 1), then drop |
|
if (cnt >= MAX_COUNT && differ < INTERVAL) { |
|
miss_cnt++; |
|
return; |
|
} |
|
|
|
char buffer[192]; |
|
va_list ap; |
|
va_start(ap, fmt); |
|
int n = vsnprintf(buffer, sizeof(buffer), fmt, ap); |
|
va_end(ap); |
|
if (n > 0) { |
|
buffer[sizeof(buffer) - 1] = '\0'; |
|
|
|
if (cnt < MAX_COUNT) { |
|
android::prdebug("%s", buffer); |
|
cnt++; |
|
} else if(differ >= INTERVAL) { |
|
// write dropped statistic info |
|
if (miss_cnt != 0) |
|
android::prdebug("dropped %d its own logs by limitation.\n", miss_cnt); |
|
|
|
// write normal log |
|
android::prdebug("%s", buffer); |
|
clock_gettime(CLOCK_MONOTONIC, &ts_0); // update ts_0 |
|
cnt = 1; // cnt = 1 |
|
miss_cnt = 0; // reset to Zero |
|
} |
|
} |
|
} |
|
|
|
#if defined(MTK_LOGD_FILTER) |
|
int log_reader_count = 0; |
|
void logd_reader_del(void) { |
|
char property[PROPERTY_VALUE_MAX]; |
|
|
|
if (log_reader_count == 1) { |
|
property_get("persist.log.tag", property, "I"); |
|
property_set("log.tag", property); |
|
prdebug_ratelimit("logd no log reader, set log level to %s!\n", property); |
|
} |
|
log_reader_count--; |
|
} |
|
|
|
void logd_reader_add(void) { |
|
char property[PROPERTY_VALUE_MAX]; |
|
|
|
if (log_reader_count == 0) { |
|
property_get("persist.log.tag", property, "M"); |
|
property_set("log.tag", property); |
|
prdebug_ratelimit("logd first log reader, set log level to %s!\n", property); |
|
} |
|
log_reader_count++; |
|
} |
|
|
|
#endif |
|
|
|
#if defined(HAVE_AEE_FEATURE) && defined(ANDROID_LOG_MUCH_COUNT) |
|
|
|
sem_t logmuch_sem; |
|
|
|
int log_detect_value; |
|
int log_much_delay_detect = 0; // log much detect pause, may use double detect value |
|
int build_type; // eng:0, userdebug:1 user:2 |
|
int detect_time = 1; |
|
|
|
// adjust logmuch feature |
|
void* logmuch_adjust_thread_start(void* /*obj*/) { |
|
prctl(PR_SET_NAME, "logd.logmuch.D"); |
|
|
|
set_sched_policy(0, SP_FOREGROUND); |
|
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND); |
|
|
|
cap_t caps = cap_init(); |
|
(void)cap_clear(caps); |
|
(void)cap_set_proc(caps); |
|
(void)cap_free(caps); |
|
|
|
// If we are AID_ROOT, we should drop to AID_LOGD+AID_SYSTEM, if we are |
|
// anything else, we have even lesser privileges and accept our fate. Not |
|
// worth checking for error returns setting this thread's privileges. |
|
(void)setgid(AID_SYSTEM); // readonly access to /data/system/packages.list |
|
(void)setuid(AID_LOGD); // access to everything logd, eg /data/misc/logd |
|
|
|
|
|
char property[PROPERTY_VALUE_MAX]; |
|
bool value; |
|
int count; |
|
int delay; |
|
|
|
while (!sem_wait(&logmuch_sem)) { |
|
android::prdebug("logmuch adjust thread wakeup"); |
|
|
|
property_get("ro.aee.build.info", property, ""); |
|
value = !strcmp(property, "mtk"); |
|
if (value != true) { |
|
log_detect_value = 0; |
|
continue; |
|
} |
|
|
|
value = property_get_bool("persist.logmuch.detect", true); |
|
if (value == true) { |
|
property_get("ro.build.type", property, ""); |
|
if (!strcmp(property, "eng")) { |
|
build_type = 0; |
|
} else if (!strcmp(property, "userdebug")) { |
|
build_type = 1; |
|
} else { |
|
build_type = 2; |
|
} |
|
|
|
if (log_detect_value == 0) { |
|
log_detect_value = ANDROID_LOG_MUCH_COUNT; |
|
} |
|
|
|
property_get("logmuch.detect.value", property, "-1"); |
|
count = atoi(property); |
|
if (count == 0) { |
|
count = ANDROID_LOG_MUCH_COUNT; |
|
} |
|
android::prdebug("logmuch detect, build type %d, detect value %d:%d.\n", |
|
build_type, count, log_detect_value); |
|
|
|
if (count > 0 && count != log_detect_value) { // set new log level |
|
log_detect_value = count; |
|
log_much_delay_detect = 1; |
|
} |
|
detect_time = (log_detect_value > 1000) ? 1 : 6; |
|
|
|
property_get("logmuch.detect.delay", property, ""); |
|
delay = atoi(property); |
|
|
|
if (delay > 0) { |
|
log_much_delay_detect = 3*60; |
|
property_set("logmuch.detect.delay", "0"); |
|
} |
|
} else { |
|
log_detect_value = 0; |
|
android::prdebug("logmuch detect disable."); |
|
} |
|
|
|
} |
|
|
|
return nullptr; |
|
} |
|
|
|
void trigger_logmuch_adjust() { |
|
sem_post(&logmuch_sem); |
|
} |
|
|
|
// logmuch need to be adjusted. |
|
int logmuch_adjust() { |
|
cap_t caps = cap_init(); |
|
(void)cap_clear(caps); |
|
(void)cap_set_proc(caps); |
|
(void)cap_free(caps); |
|
|
|
int sock = TEMP_FAILURE_RETRY(socket_local_client( |
|
"logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)); |
|
if (sock < 0) return -errno; |
|
|
|
static const char logmuchStr[] = "logmuch"; |
|
ssize_t ret = TEMP_FAILURE_RETRY(write(sock, logmuchStr, sizeof(logmuchStr))); |
|
if (ret < 0) return -errno; |
|
|
|
struct pollfd p; |
|
memset(&p, 0, sizeof(p)); |
|
p.fd = sock; |
|
p.events = POLLIN; |
|
ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000)); |
|
if (ret < 0) return -errno; |
|
if ((ret == 0) || !(p.revents & POLLIN)) return -ETIME; |
|
|
|
static const char success[] = "success"; |
|
char buffer[sizeof(success) - 1]; |
|
memset(buffer, 0, sizeof(buffer)); |
|
ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); |
|
if (ret < 0) return -errno; |
|
|
|
return strncmp(buffer, success, sizeof(success) - 1) != 0; |
|
} |
|
#endif |
|
|
|
#if defined(LOGD_FORCE_DIRECTCOREDUMP) |
|
#define SIGNUM 7 |
|
|
|
// need sync with vendor\mediatek\proprietary\external\aee\direct-coredump\direct-coredump.c |
|
void directcoredump_init() { |
|
int sigtype[SIGNUM] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP, SIGSYS}; |
|
char value[PROPERTY_VALUE_MAX] = {'\0'}; |
|
|
|
// eng&userdebug load direct-coredump default enable |
|
// user load direct-coredump default disable due to libdirect-coredump.so will not be preloaded |
|
property_get("persist.aee.core.direct", value, "default"); |
|
if (strncmp(value, "disable", sizeof("disable"))) { |
|
int loop; |
|
for (loop = 0; loop < SIGNUM; loop++) { |
|
signal(sigtype[loop], SIG_DFL); |
|
} |
|
} |
|
android::prdebug("init directcoredump done!\n"); |
|
} |
|
#endif |
|
#endif |
|
|
|
|