LogStatistics.cpp revision 08739ba71fc1f2659149be760405d622e5b68f06
134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn/* 234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Copyright (C) 2014 The Android Open Source Project 334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * 434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * you may not use this file except in compliance with the License. 634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * You may obtain a copy of the License at 734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * 834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * 1034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Unless required by applicable law or agreed to in writing, software 1134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 1234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * See the License for the specific language governing permissions and 1434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * limitations under the License. 1534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn */ 1634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 1797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <algorithm> // std::max 189a03863e88da99ba010342c874252089dd771f7fMark Salyzyn#include <fcntl.h> 1997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <stdio.h> 2097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <string.h> 2197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <unistd.h> 2234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <log/logger.h> 2434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <private/android_filesystem_config.h> 2534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <utils/String8.h> 2634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 2734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include "LogStatistics.h" 2834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 29720f6d1d55d936d98cc9752e96f479e03e6d5009Mark SalyzynLogStatistics::LogStatistics() 30720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn : enable(false) { 3197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_for_each(id) { 3297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mSizes[id] = 0; 3397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mElements[id] = 0; 3497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mSizesTotal[id] = 0; 3597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mElementsTotal[id] = 0; 3634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 3734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 3834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 39720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android { 40720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 4197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string 42720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynstatic char *pidToName(pid_t pid) { 439a03863e88da99ba010342c874252089dd771f7fMark Salyzyn char *retval = NULL; 44df5aa61f05ccbef441cf8b024d4bbc1b717451f9Mark Salyzyn if (pid == 0) { // special case from auditd for kernel 45df5aa61f05ccbef441cf8b024d4bbc1b717451f9Mark Salyzyn retval = strdup("logd.auditd"); 4697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn } else { 479a03863e88da99ba010342c874252089dd771f7fMark Salyzyn char buffer[512]; 489a03863e88da99ba010342c874252089dd771f7fMark Salyzyn snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid); 499a03863e88da99ba010342c874252089dd771f7fMark Salyzyn int fd = open(buffer, O_RDONLY); 509a03863e88da99ba010342c874252089dd771f7fMark Salyzyn if (fd >= 0) { 519a03863e88da99ba010342c874252089dd771f7fMark Salyzyn ssize_t ret = read(fd, buffer, sizeof(buffer)); 529a03863e88da99ba010342c874252089dd771f7fMark Salyzyn if (ret > 0) { 539a03863e88da99ba010342c874252089dd771f7fMark Salyzyn buffer[sizeof(buffer)-1] = '\0'; 549a03863e88da99ba010342c874252089dd771f7fMark Salyzyn // frameworks intermediate state 559a03863e88da99ba010342c874252089dd771f7fMark Salyzyn if (strcmp(buffer, "<pre-initialized>")) { 569a03863e88da99ba010342c874252089dd771f7fMark Salyzyn retval = strdup(buffer); 579a03863e88da99ba010342c874252089dd771f7fMark Salyzyn } 589a03863e88da99ba010342c874252089dd771f7fMark Salyzyn } 599a03863e88da99ba010342c874252089dd771f7fMark Salyzyn close(fd); 609a03863e88da99ba010342c874252089dd771f7fMark Salyzyn } 619a03863e88da99ba010342c874252089dd771f7fMark Salyzyn } 629a03863e88da99ba010342c874252089dd771f7fMark Salyzyn return retval; 639a03863e88da99ba010342c874252089dd771f7fMark Salyzyn} 649a03863e88da99ba010342c874252089dd771f7fMark Salyzyn 65720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn} 66720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 6797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::add(LogBufferElement *e) { 6897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_t log_id = e->getLogId(); 6997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn unsigned short size = e->getMsgLen(); 7097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mSizes[log_id] += size; 7197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn ++mElements[log_id]; 7234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 7397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn uid_t uid = e->getUid(); 7497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::hash_t hash = android::hash_type(uid); 7597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn uidTable_t &table = uidTable[log_id]; 7697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn ssize_t index = table.find(-1, hash, uid); 7797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (index == -1) { 7897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn UidEntry initEntry(uid); 7997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn initEntry.add(size); 8097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn table.add(hash, initEntry); 8134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } else { 8297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn UidEntry &entry = table.editEntryAt(index); 8397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn entry.add(size); 8434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 85c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn 8697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mSizesTotal[log_id] += size; 8797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn ++mElementsTotal[log_id]; 88720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 89720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!enable) { 90720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return; 91720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 92720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 93720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pid_t pid = e->getPid(); 94720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn hash = android::hash_type(pid); 95720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn index = pidTable.find(-1, hash, pid); 96720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (index == -1) { 97720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry initEntry(pid, uid, android::pidToName(pid)); 98720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn initEntry.add(size); 99720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pidTable.add(hash, initEntry); 100720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 101720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry &entry = pidTable.editEntryAt(index); 102720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (entry.getUid() != uid) { 103720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.setUid(uid); 104720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.setName(android::pidToName(pid)); 105720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else if (!entry.getName()) { 106720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn char *name = android::pidToName(pid); 107720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (name) { 108720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.setName(name); 109720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 110720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 111720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.add(size); 112720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 11334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 11434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 11597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::subtract(LogBufferElement *e) { 11697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_t log_id = e->getLogId(); 11797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn unsigned short size = e->getMsgLen(); 11897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn mSizes[log_id] -= size; 11997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn --mElements[log_id]; 12034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 12197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn uid_t uid = e->getUid(); 12297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::hash_t hash = android::hash_type(uid); 12397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn uidTable_t &table = uidTable[log_id]; 12497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn ssize_t index = table.find(-1, hash, uid); 12597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (index != -1) { 12697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn UidEntry &entry = table.editEntryAt(index); 12797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (entry.subtract(size)) { 12897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn table.removeAt(index); 12934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 13034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 13134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 132720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!enable) { 133720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return; 13434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 13534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 136720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pid_t pid = e->getPid(); 137720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn hash = android::hash_type(pid); 138720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn index = pidTable.find(-1, hash, pid); 139720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (index != -1) { 140720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry &entry = pidTable.editEntryAt(index); 141720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (entry.subtract(size)) { 142720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pidTable.removeAt(index); 143c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn } 144c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn } 145c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn} 146c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn 14797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string 14897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynchar *LogStatistics::uidToName(uid_t uid) { 14997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // Local hard coded favourites 15097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (uid == AID_LOGD) { 15197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn return strdup("auditd"); 15234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 15334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 15497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // Android hard coded 15597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn const struct android_id_info *info = android_ids; 15634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 15797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn for (size_t i = 0; i < android_id_count; ++i) { 15897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (info->aid == uid) { 15997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn return strdup(info->name); 16034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 16197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn ++info; 16234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 16334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 16408739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn // Parse /data/system/packages.list 16508739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn char *name = android::uidToName(uid); 16608739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn if (name) { 16708739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn return name; 16808739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn } 169720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 170720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn // report uid -> pid(s) -> pidToName if unique 171720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn ssize_t index = -1; 172720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn while ((index = pidTable.next(index)) != -1) { 173720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn const PidEntry &entry = pidTable.entryAt(index); 174720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 175720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (entry.getUid() == uid) { 176720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn const char *n = entry.getName(); 177720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 178720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (n) { 179720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!name) { 180720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name = strdup(n); 181720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else if (strcmp(name, n)) { 182720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn free(name); 183720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return NULL; 184720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 185720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 186720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 187720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 188720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 18997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // No one 190720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return name; 19134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 19234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 19397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynstatic void format_line(android::String8 &output, 19497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 &name, android::String8 &size) { 19597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn static const size_t total_len = 70; 19634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 19797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("%s%*s\n", name.string(), 198317843decf92ddf63d8110df8169c33546d587c3Mark Salyzyn (int)std::max(total_len - name.length() - 1, size.length() + 1), 19997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn size.string()); 20034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 20134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 20297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) { 2039a03863e88da99ba010342c874252089dd771f7fMark Salyzyn static const unsigned short spaces_total = 19; 20434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 20534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn if (*buf) { 206239605ef64d34ced82c97870e3f3f5c4145be58cGreg Hackmann free(*buf); 20734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *buf = NULL; 20834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 20934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 21097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // Report on total logging, current and for all time 21197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn 21297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 output("size/num"); 21334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn size_t oldLength; 21497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn short spaces = 1; 21534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 21697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_for_each(id) { 21797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (!(logMask & (1 << id))) { 218c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn continue; 219c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn } 22097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn oldLength = output.length(); 221c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn if (spaces < 0) { 222c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn spaces = 0; 223c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn } 22497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("%*s%s", spaces, "", android_log_id_to_name(id)); 22597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces += spaces_total + oldLength - output.length(); 22697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn } 227c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn 22897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces = 4; 22997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("\nTotal"); 230c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn 23197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_for_each(id) { 23297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (!(logMask & (1 << id))) { 23397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn continue; 23434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 23597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn oldLength = output.length(); 23697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (spaces < 0) { 23797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces = 0; 238e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn } 23997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("%*s%zu/%zu", spaces, "", 24097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn sizesTotal(id), elementsTotal(id)); 24197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces += spaces_total + oldLength - output.length(); 24234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 24334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 24497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces = 6; 24597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("\nNow"); 24634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 24797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_for_each(id) { 24897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (!(logMask & (1 << id))) { 24934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn continue; 25034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 25134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 25297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn size_t els = elements(id); 25334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn if (els) { 25497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn oldLength = output.length(); 255e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn if (spaces < 0) { 256e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn spaces = 0; 257e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn } 25897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat("%*s%zu/%zu", spaces, "", sizes(id), els); 25997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn spaces -= output.length() - oldLength; 26034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 26134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn spaces += spaces_total; 26234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 26334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 26497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // Report on Chattiest 2658e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn 26697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn // Chattiest by application (UID) 267720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn static const size_t maximum_sorted_entries = 32; 26897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn log_id_for_each(id) { 26997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (!(logMask & (1 << id))) { 2708e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn continue; 2718e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn } 2728e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn 273720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn bool headerPrinted = false; 274720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn std::unique_ptr<const UidEntry *[]> sorted = sort(maximum_sorted_entries, id); 275720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn ssize_t index = -1; 276720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn while ((index = uidTable_t::next(index, sorted, maximum_sorted_entries)) >= 0) { 27797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn const UidEntry *entry = sorted[index]; 27897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn uid_t u = entry->getKey(); 27997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if ((uid != AID_ROOT) && (u != uid)) { 28034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn continue; 28134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 28234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 283720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!headerPrinted) { 28497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (uid == AID_ROOT) { 28597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat( 28697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn "\n\nChattiest UIDs in %s:\n", 28797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android_log_id_to_name(id)); 28897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 name("UID"); 28997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 size("Size"); 29097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn format_line(output, name, size); 29197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn } else { 29297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn output.appendFormat( 29397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn "\n\nLogging for your UID in %s:\n", 29497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android_log_id_to_name(id)); 295e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn } 296720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn headerPrinted = true; 29734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 29834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 29997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 name(""); 30097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn name.appendFormat("%u", u); 30197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn char *n = uidToName(u); 30297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (n) { 30397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn name.appendFormat("%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n); 30497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn free(n); 30534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 30634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 30797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn android::String8 size(""); 308720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn size.appendFormat("%zu", entry->getSizes()); 30934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 31097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn format_line(output, name, size); 31134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 312720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 31397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn 314720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (enable) { 315720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn bool headerPrinted = false; 316720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries); 317720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn ssize_t index = -1; 318720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn while ((index = pidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { 319720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn const PidEntry *entry = sorted[index]; 320720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn uid_t u = entry->getUid(); 321720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if ((uid != AID_ROOT) && (u != uid)) { 322720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn continue; 323720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 324720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 325720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!headerPrinted) { 326720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (uid == AID_ROOT) { 327720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn output.appendFormat("\n\nChattiest PIDs:\n"); 328720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 329720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn output.appendFormat("\n\nLogging for this PID:\n"); 330720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 331720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::String8 name(" PID/UID"); 332720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::String8 size("Size"); 333720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::String8 pruned("Pruned"); 334720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn format_line(output, name, size, pruned); 335720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn headerPrinted = true; 336720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 337720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 338720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::String8 name(""); 339720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name.appendFormat("%5u/%u", entry->getKey(), u); 340720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn const char *n = entry->getName(); 341720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (n) { 342720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); 343720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 344720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn char *un = uidToName(u); 345720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (un) { 346720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); 347720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn free(un); 348720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 349720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 350720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 351720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::String8 size(""); 352720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn size.appendFormat("%zu", entry->getSizes()); 353720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 354720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn format_line(output, name, size); 355720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 35634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn } 35734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 35897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn *buf = strdup(output.string()); 35934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 3604ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn 361720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android { 362720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 363720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t pidToUid(pid_t pid) { 36497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn char buffer[512]; 36597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid); 36697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn FILE *fp = fopen(buffer, "r"); 36797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (fp) { 36897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn while (fgets(buffer, sizeof(buffer), fp)) { 36997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn int uid; 37097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn if (sscanf(buffer, "Groups: %d", &uid) == 1) { 37197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn fclose(fp); 37297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn return uid; 3734ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn } 3744ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn } 37597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn fclose(fp); 3764ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn } 3774ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn return getuid(); // associate this with the logger 3784ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn} 379720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 380720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn} 381720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 382720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t LogStatistics::pidToUid(pid_t pid) { 383720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn uid_t uid; 384720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::hash_t hash = android::hash_type(pid); 385720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn ssize_t index = pidTable.find(-1, hash, pid); 386720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (index == -1) { 387720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn uid = android::pidToUid(pid); 388720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry initEntry(pid, uid, android::pidToName(pid)); 389720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pidTable.add(hash, initEntry); 390720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 391720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry &entry = pidTable.editEntryAt(index); 392720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (!entry.getName()) { 393720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn char *name = android::pidToName(pid); 394720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (name) { 395720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.setName(name); 396720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 397720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 398720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn uid = entry.getUid(); 399720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 400720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return uid; 401720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn} 402720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 403720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn// caller must free character string 404720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynchar *LogStatistics::pidToName(pid_t pid) { 405720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn char *name; 406720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 407720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn android::hash_t hash = android::hash_type(pid); 408720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn ssize_t index = pidTable.find(-1, hash, pid); 409720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (index == -1) { 410720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name = android::pidToName(pid); 411720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry initEntry(pid, android::pidToUid(pid), name ? strdup(name) : NULL); 412720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn pidTable.add(hash, initEntry); 413720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 414720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn PidEntry &entry = pidTable.editEntryAt(index); 415720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn const char *n = entry.getName(); 416720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (n) { 417720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name = strdup(n); 418720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } else { 419720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn name = android::pidToName(pid); 420720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn if (name) { 421720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn entry.setName(strdup(name)); 422720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 423720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 424720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn } 425720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn 426720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn return name; 427720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn} 428