1、system\core\logcat\logcatd.rc
add:
on property:persist.vendor.logcpu.enable=true
start logcpu
on property:persist.vendor.logcpu.enable=false
stop logcpu
setprop persist.vendor.logcpu.enable ""
on property:persist.vendor.logcpu.once.enable=true
start logcpu_once
setprop persist.vendor.logcpu.once.enable false
# logcpu service
service logcpu /system/bin/logcatd -CPU
class late_start
disabled
user logd
group log media_rw sdcard_rw system readproc
writepid /dev/cpuset/system-background/tasks
oom_score_adjust -600
# logcpu service
service logcpu_once /system/bin/logcatd -CPUONCE
class late_start
disabled
oneshot
user logd
group log media_rw sdcard_rw system readproc
writepid /dev/cpuset/system-background/tasks
oom_score_adjust -600
2、system\core\logcat\logcatd_main.cpp
add:
const char* startstr = "\'**********************\'";
const char* endstr = "\'**********************\'";
const char* CPU_MEM_FILE = "cpumem";
const char* CPU_TOP_FILE = "cputop";
const char* GPU_TOP_FILE = "gputop";
const char* CPU_MEM_ONCE_FILE = "cpumem_once";
const char* CPU_TOP_ONCE_FILE = "cputop_once";
const char* GPU_TOP_ONCE_FILE = "gputop_once";
add:
void CollectCPUAndGPUInfo(char* datepath,const char* cpu_mem_file,const char* cpu_top_file,const char* gpu_top_file){
char commond[1024]={""};
//CPU MEM
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",startstr,datepath,cpu_mem_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
if(DEBUG)LOG(INFO) << "commond "<<commond;
snprintf(commond, sizeof(commond), "date >> %s/%s",datepath,cpu_mem_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",endstr,datepath,cpu_mem_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "memcheck -mzscp >> %s/%s",datepath,cpu_mem_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
//CPU TOP
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",startstr,datepath,cpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "date >> %s/%s",datepath,cpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",endstr,datepath,cpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "top -n 1 >> %s/%s",datepath,cpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "echo >> %s/%s",datepath,cpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
//GPU TOP
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",startstr,datepath,gpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "date >> %s/%s",datepath,gpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "echo %s >> %s/%s",endstr,datepath,gpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
snprintf(commond, sizeof(commond), "gpu-top -f -b >> %s/%s",datepath,gpu_top_file);
if(DEBUG)LOG(INFO) << commond;
system(commond);
}
void startCollectCPUAndGPUInfo(){
LOG(INFO) << "startCollectCPUAndGPUInfo";
char datepath[50]={""};
const char* cdate = NULL;
const char* pboot = NULL;
const char* logpath = NULL;
while(1){
sleep(5);
cdate = getDate();
pboot = get_property_boot();
if(strcmp(pboot, "1") == 0){
logpath = APLOG_SDCARD_PATH;
}else{
logpath = APLOG_PATH;
}
snprintf(datepath, sizeof(datepath), "%s/%s",logpath,cdate);
if(is_dir_exist(datepath)==-1){
makeLogcatdir(datepath,cdate);
}
if(DEBUG)LOG(INFO) << "datepath "<<datepath;
CollectCPUAndGPUInfo(datepath,CPU_MEM_FILE,CPU_TOP_FILE,GPU_TOP_FILE);
}
}
void startCollectCPUAndGPUInfoOnce(){
LOG(INFO) << "startCollectCPUAndGPUInfoOnce";
char datepath[50]={""};
const char* cdate = NULL;
const char* logpath = NULL;
const char* pboot = get_property_boot();
if(strcmp(pboot, "1") == 0){
logpath = APLOG_SDCARD_PATH;
}else{
logpath = APLOG_PATH;
}
cdate = getDate();
snprintf(datepath, sizeof(datepath), "%s/%s",APLOG_SDCARD_PATH,cdate);
if(is_dir_exist(datepath)==-1){
makeLogcatdir(datepath,cdate);
}
LOG(INFO) << "datepath "<<datepath;
CollectCPUAndGPUInfo(datepath,CPU_MEM_ONCE_FILE,CPU_TOP_ONCE_FILE,GPU_TOP_ONCE_FILE);
}
modify:
int main(int argc, char** argv, char** envp) {
if(OPEN_DEBUG)InitKernelLogging(argv);
if(OPEN_DEBUG)LOG(INFO) << "logcatd started: " << argc << argv;
signal(SIGPIPE, exit);
// Save and detect presence of -L or --last flag
std::vector<std::string> args;
bool last = false;
bool hsaelog = false;
bool hsaelogcpu = false;
bool hsaelogcpuonce = false;
int tryCount = 0;
for (int i = 0; i < argc; ++i) {
if (!argv[i]) continue;
args.push_back(std::string(argv[i]));
if (!strcmp(argv[i], "-L") || !strcmp(argv[i], "--last")) last = true;
if (!strcmp(argv[i], "-Z")) hsaelog = true;
if (!strcmp(argv[i], "-CPU")) hsaelogcpu = true;
if (!strcmp(argv[i], "-CPUONCE")) hsaelogcpuonce = true;
}
if(OPEN_DEBUG)LOG(INFO) << "logcatd started: ps = " << hsaelog << " hsaelogcpu =" << hsaelogcpu << " hsaelogcpuonce" << hsaelogcpuonce;
if(hsaelog){
if(OPEN_DEBUG)LOG(INFO) << "hsaelog start";
const char* pboot = get_property_boot();
if(strcmp(pboot, "1") == 0){
int isDirExit = -1;
for(;tryCount<MAX_TRY_COUNT;tryCount++){
isDirExit = is_dir_exist(APLOG_SDCARD_PATH);
if(isDirExit==-1){
makeLogcatdir(APLOG_SDCARD_PATH,NULL);
}else if(isDirExit == 0){
if(OPEN_DEBUG)LOG(INFO) << "get_property_boot1 tryCount= "<< tryCount << "isDirExit= "<<isDirExit;
break;
}
if(OPEN_DEBUG)LOG(INFO) << "get_property_boot2 tryCount= "<< tryCount << "isDirExit= "<<isDirExit;
sleep(1);
}
if(OPEN_DEBUG)LOG(INFO) << "get_property_boot3 tryCount= "<< tryCount << "isDirExit= "<<isDirExit;
if(isDirExit==-1) return 0;
}
forkLogcat();
forkLogcatEvent();
//forkLogcatRadio();
forkLogcatCrash();
forkLogcatKernel();
forkSdcardInotify();
startnotify();
return 0;
}else if(hsaelogcpu){
if(__android_log_is_debuggable()){
if(OPEN_DEBUG)LOG(INFO) << "hsaelogcpu start";
startCollectCPUAndGPUInfo();
}
}else if(hsaelogcpuonce){
if(__android_log_is_debuggable()){
if(OPEN_DEBUG)LOG(INFO) << "hsaelogcpuonce start";
startCollectCPUAndGPUInfoOnce();
}
}else{
android_logcat_context ctx = create_android_logcat();
if (!ctx) return -1;
// Generate argv from saved content
std::vector<const char*> argv_hold;
for (auto& str : args) argv_hold.push_back(str.c_str());
argv_hold.push_back(nullptr);
int ret = 0;
if (last) {
// Run logcat command with -L flag
ret = android_logcat_run_command(ctx, -1, -1, argv_hold.size() - 1,
(char* const*)&argv_hold[0], envp);
// Remove -L and --last flags from argument list
for (std::vector<const char*>::iterator it = argv_hold.begin();
it != argv_hold.end();) {
if (!*it || (strcmp(*it, "-L") && strcmp(*it, "--last"))) {
++it;
} else {
it = argv_hold.erase(it);
}
}
// fall through to re-run the command regardless of the arguments
// passed in. For instance, we expect -h to report help stutter.
}
if(DEBUG)LOG(INFO) << "logcatd run_command: last = %d" << last;
// Run logcat command without -L flag
int retval = android_logcat_run_command(ctx, -1, -1, argv_hold.size() - 1,
(char* const*)&argv_hold[0], envp);
if (!ret) ret = retval;
retval = android_logcat_destroy(&ctx);
if (!ret) ret = retval;
if(DEBUG)LOG(INFO) << "logcatd run command end";
return retval;
}
}
3、system\core\debuggerd\tombstoned\tombstoned.cpp
add:
#include <log/log_properties.h>
add persist.vendor.logcpu.once.enable:
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
ssize_t rc;
Crash* crash = static_cast<Crash*>(arg);
TombstonedCrashPacket request = {};
if ((ev & EV_TIMEOUT) != 0) {
LOG(WARNING) << "crash request timed out";
goto fail;
} else if ((ev & EV_READ) == 0) {
LOG(WARNING) << "tombstoned received unexpected event from crash socket";
goto fail;
}
rc = TEMP_FAILURE_RETRY(read(sockfd, &request, sizeof(request)));
if (rc == -1) {
PLOG(WARNING) << "failed to read from crash socket";
goto fail;
} else if (rc != sizeof(request)) {
LOG(WARNING) << "crash socket received short read of length " << rc << " (expected "
<< sizeof(request) << ")";
goto fail;
}
if (request.packet_type != CrashPacketType::kDumpRequest) {
LOG(WARNING) << "unexpected crash packet type, expected kDumpRequest, received "
<< StringPrintf("%#2hhX", request.packet_type);
goto fail;
}
crash->crash_type = request.packet.dump_request.dump_type;
if (crash->crash_type < 0 || crash->crash_type > kDebuggerdAnyIntercept) {
LOG(WARNING) << "unexpected crash dump type: " << crash->crash_type;
goto fail;
}
if (crash->crash_type != kDebuggerdJavaBacktrace) {
crash->crash_pid = request.packet.dump_request.pid;
} else {
// Requests for java traces are sent from untrusted processes, so we
// must not trust the PID sent down with the request. Instead, we ask the
// kernel.
ucred cr = {};
socklen_t len = sizeof(cr);
int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
if (ret != 0) {
PLOG(ERROR) << "Failed to getsockopt(..SO_PEERCRED)";
goto fail;
}
crash->crash_pid = cr.pid;
}
LOG(INFO) << "received crash request for pid " << crash->crash_pid;
// new add for logcpu enable 2020.12.01
if(__android_log_is_debuggable()){
android::base::SetProperty("persist.vendor.logcpu.once.enable", "true");
}
if (CrashQueue::for_crash(crash)->maybe_enqueue_crash(crash)) {
LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
} else {
perform_request(crash);
}
return;
fail:
delete crash;
}
4、添加sepolicy权限
system\sepolicy\public/domain.te
add userdebug_or_eng(`-logpersist’):
neverallow {
domain
-adbd
-init
-runas
-zygote
userdebug_or_eng(`-logpersist')
} shell:process { transition dyntransition };
add userdebug_or_eng(`-logpersist’):
neverallow { domain -init -vendor_init -system_server -dumpstate userdebug_or_eng(`-logpersist')} debugfs:file no_rw_file_perms;
system\sepolicy\public/logpersist.te
add ioctl:
allow logpersist sdcardfs:file { create read write open setattr getattr unlink append rename ioctl};
system\sepolicy\private/system_server.te
add:
allow system_server logpersistd_logging_prop:property_service set;
system\sepolicy\private\property_contexts
persist.vendor.logcpu.enable u:object_r:logpersistd_logging_prop:s0
persist.vendor.logcpu.once.enable u:object_r:logpersistd_logging_prop:s0
system\sepolicy\private/logpersist.te
add:
userdebug_or_eng(`
permissive logpersist;
r_dir_file(logpersist, proc_net)
allow logpersist {
proc_asound
proc_filesystems
proc_interrupts
proc_meminfo
proc_modules
proc_pid_max
proc_stat
proc_timer
proc_uptime
proc_version
proc_zoneinfo
}:file r_file_perms;
allow logpersist {
ueventd
incidentd
vendor_init
debugfs
kernel
installd
vndservicemanager
sysfs
debugfs
}:file { read open getattr };
allow logpersist {
ueventd
vold
perfprofd
mediacodec
vendor_init
logd
servicemanager
kernel
watchdogd
netd
zygote
init
}:dir { search getattr};
allow logpersist { system_file }:file { execute_no_trans };
')
system\sepolicy\private/domain.te
add userdebug_or_eng(`-logpersist’):
# Limit ability to ptrace or read sensitive /proc/pid files of processes
# with other UIDs to these whitelisted domains.
neverallow {
domain
-vold
-dumpstate
userdebug_or_eng(`-incidentd')
-storaged
-system_server
userdebug_or_eng(`-perfprofd')
userdebug_or_eng(`-logpersist')
} self:global_capability_class_set sys_ptrace;
# Core domains are not permitted to use kernel interfaces which are not
# explicitly labeled.
# TODO(b/65643247): Apply these neverallow rules to all coredomain.
full_treble_only(`
# /proc
neverallow {
coredomain
-vold
userdebug_or_eng(`-logpersist')
} proc:file no_rw_file_perms;
# /sys
neverallow {
coredomain
-init
-ueventd
-vold
-recovery
userdebug_or_eng(`-logpersist')
} sysfs:file no_rw_file_perms;
# /dev
neverallow {
coredomain
-fsck
-init
-ueventd
} device:{ blk_file file } no_rw_file_perms;
# debugfs
neverallow {
coredomain
-dumpstate
-init
-system_server
userdebug_or_eng(`-logpersist')
} debugfs:file no_rw_file_perms;
system\sepolicy\prebuilts/api/28.0/public/tombstoned.te
add:
allow tombstoned logpersistd_logging_prop:property_service set;
allow tombstoned property_socket:sock_file write;
allow tombstoned init:unix_stream_socket connectto;
system\sepolicy\prebuilts/api/28.0/public/logpersist.te
add:
allow logpersist sdcardfs:file { create read write open setattr getattr unlink append rename ioctl};
system\sepolicy\prebuilts/api/28.0/public/domain.te
add userdebug_or_eng(`-logpersist’):
neverallow {
domain
-adbd
-init
-runas
-zygote
userdebug_or_eng(`-logpersist')
} shell:process { transition dyntransition };
neverallow { domain -init -vendor_init -system_server -dumpstate userdebug_or_eng(`-logpersist')} debugfs:file no_rw_file_perms;
system\sepolicy\prebuilts/api/28.0/private/system_server.te
allow system_server logpersistd_logging_prop:property_service set;
system\sepolicy\prebuilts/api/28.0/private/logpersist.te
同public中的修正。
system\sepolicy\prebuilts/api/28.0/private/property_contexts
同public中的修正。
add:
persist.vendor.logcpu.enable u:object_r:logpersistd_logging_prop:s0
persist.vendor.logcpu.once.enable u:object_r:logpersistd_logging_prop:s0
system\sepolicy\prebuilts/api/28.0/private/domain.te
同public中的修正。
add userdebug_or_eng(`-logpersist’):
neverallow {
domain
-vold
-dumpstate
userdebug_or_eng(`-incidentd')
-storaged
-system_server
userdebug_or_eng(`-perfprofd')
userdebug_or_eng(`-logpersist')
} self:global_capability_class_set sys_ptrace;
full_treble_only(`
# /proc
neverallow {
coredomain
-vold
userdebug_or_eng(`-logpersist')
} proc:file no_rw_file_perms;
# /sys
neverallow {
coredomain
-init
-ueventd
-vold
-recovery
userdebug_or_eng(`-logpersist')
} sysfs:file no_rw_file_perms;
# /dev
neverallow {
coredomain
-fsck
-init
-ueventd
} device:{ blk_file file } no_rw_file_perms;
# debugfs
neverallow {
coredomain
-dumpstate
-init
-system_server
userdebug_or_eng(`-logpersist')
} debugfs:file no_rw_file_perms;