blob: c6ebd52dcabe8f578d63a2c3693cac97a6134361 [file] [log] [blame]
Mark Salyzyn34facab2014-02-06 14:48:50 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mark Salyzyn9a038632014-04-07 07:05:40 -070017#include <fcntl.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070018#include <pwd.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070019#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070020#include <string.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070021#include <sys/types.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070022#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080023
24#include <log/logger.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080025
26#include "LogStatistics.h"
27
Mark Salyzyn77187782015-05-12 15:21:31 -070028LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070029 log_id_for_each(id) {
30 mSizes[id] = 0;
31 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070032 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070033 mSizesTotal[id] = 0;
34 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080035 }
36}
37
Mark Salyzyn720f6d12015-03-16 08:26:05 -070038namespace android {
39
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070040// caller must own and free character string
Mark Salyzyn81b3eab2015-04-13 14:24:45 -070041char *pidToName(pid_t pid) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070042 char *retval = NULL;
Mark Salyzynae4d9282014-10-15 08:49:39 -070043 if (pid == 0) { // special case from auditd/klogd for kernel
44 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070045 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070046 char buffer[512];
47 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
48 int fd = open(buffer, O_RDONLY);
49 if (fd >= 0) {
50 ssize_t ret = read(fd, buffer, sizeof(buffer));
51 if (ret > 0) {
52 buffer[sizeof(buffer)-1] = '\0';
53 // frameworks intermediate state
Mark Salyzynddda2122015-10-02 09:22:52 -070054 if (fast<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070055 retval = strdup(buffer);
56 }
57 }
58 close(fd);
59 }
60 }
61 return retval;
62}
63
Mark Salyzyn720f6d12015-03-16 08:26:05 -070064}
65
Mark Salyzyn758058f2015-08-21 16:44:30 -070066void LogStatistics::add(LogBufferElement *element) {
67 log_id_t log_id = element->getLogId();
68 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080069 mSizes[log_id] += size;
70 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070071
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070072 mSizesTotal[log_id] += size;
73 ++mElementsTotal[log_id];
Mark Salyzyn720f6d12015-03-16 08:26:05 -070074
Mark Salyzynae4d9282014-10-15 08:49:39 -070075 if (log_id == LOG_ID_KERNEL) {
76 return;
77 }
78
Mark Salyzyn758058f2015-08-21 16:44:30 -070079 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070080 if (element->getUid() == AID_SYSTEM) {
81 pidSystemTable[log_id].add(element->getPid(), element);
82 }
Mark Salyzynae4d9282014-10-15 08:49:39 -070083
Mark Salyzyn720f6d12015-03-16 08:26:05 -070084 if (!enable) {
85 return;
86 }
87
Mark Salyzyn758058f2015-08-21 16:44:30 -070088 pidTable.add(element->getPid(), element);
89 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -070090
Mark Salyzyn758058f2015-08-21 16:44:30 -070091 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -070092 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -080093 if (log_id == LOG_ID_SECURITY) {
94 securityTagTable.add(tag, element);
95 } else {
96 tagTable.add(tag, element);
97 }
Mark Salyzyn344bff42015-04-13 14:24:45 -070098 }
Mark Salyzyn34facab2014-02-06 14:48:50 -080099}
100
Mark Salyzyn758058f2015-08-21 16:44:30 -0700101void LogStatistics::subtract(LogBufferElement *element) {
102 log_id_t log_id = element->getLogId();
103 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800104 mSizes[log_id] -= size;
105 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700106 if (element->getDropped()) {
107 --mDroppedElements[log_id];
108 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700109
Mark Salyzynae4d9282014-10-15 08:49:39 -0700110 if (log_id == LOG_ID_KERNEL) {
111 return;
112 }
113
Mark Salyzyn758058f2015-08-21 16:44:30 -0700114 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700115 if (element->getUid() == AID_SYSTEM) {
116 pidSystemTable[log_id].subtract(element->getPid(), element);
117 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800118
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700119 if (!enable) {
120 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800121 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700122
Mark Salyzyn758058f2015-08-21 16:44:30 -0700123 pidTable.subtract(element->getPid(), element);
124 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700125
Mark Salyzyn758058f2015-08-21 16:44:30 -0700126 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700127 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800128 if (log_id == LOG_ID_SECURITY) {
129 securityTagTable.subtract(tag, element);
130 } else {
131 tagTable.subtract(tag, element);
132 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700133 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800134}
135
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700136// Atomically set an entry to drop
137// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700138void LogStatistics::drop(LogBufferElement *element) {
139 log_id_t log_id = element->getLogId();
140 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700141 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700142 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700143
Mark Salyzyn758058f2015-08-21 16:44:30 -0700144 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700145 if (element->getUid() == AID_SYSTEM) {
146 pidSystemTable[log_id].drop(element->getPid(), element);
147 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700148
149 if (!enable) {
150 return;
151 }
152
Mark Salyzyn758058f2015-08-21 16:44:30 -0700153 pidTable.drop(element->getPid(), element);
154 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700155
156 uint32_t tag = element->getTag();
157 if (tag) {
158 if (log_id == LOG_ID_SECURITY) {
159 securityTagTable.drop(tag, element);
160 } else {
161 tagTable.drop(tag, element);
162 }
163 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700164}
165
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700166// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700167const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700168 // Local hard coded favourites
169 if (uid == AID_LOGD) {
170 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800171 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700172
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700173 // Android system
174 if (uid < AID_APP) {
175 // in bionic, thread safe as long as we copy the results
176 struct passwd *pwd = getpwuid(uid);
177 if (pwd) {
178 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700179 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800180 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700181
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700182 // Parse /data/system/packages.list
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700183 uid_t userId = uid % AID_USER;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700184 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700185 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
186 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
187 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700188 if (name) {
189 return name;
190 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700191
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700192 // Android application
193 if (uid >= AID_APP) {
194 struct passwd *pwd = getpwuid(uid);
195 if (pwd) {
196 return strdup(pwd->pw_name);
197 }
198 }
199
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700200 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700201 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700202 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700203
204 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700205 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700206
Mark Salyzyn758058f2015-08-21 16:44:30 -0700207 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700208 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700209 name = strdup(nameTmp);
210 } else if (fast<strcmp>(name, nameTmp)) {
211 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700212 name = NULL;
213 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700214 }
215 }
216 }
217 }
218
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700219 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700220 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800221}
222
Mark Salyzyn758058f2015-08-21 16:44:30 -0700223std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
224 bool isprune = worstUidEnabledForLogid(id);
225 return formatLine(android::base::StringPrintf(
226 name.c_str(), android_log_id_to_name(id)),
227 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700228 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700229 + formatLine(std::string("UID PACKAGE"),
230 std::string("BYTES"),
231 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800232}
233
Mark Salyzync723df82015-08-24 11:08:00 -0700234std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800235 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700236 std::string name = android::base::StringPrintf("%u", uid);
237 const char *nameTmp = stat.uidToName(uid);
238 if (nameTmp) {
239 name += android::base::StringPrintf(
240 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
241 "", nameTmp);
242 free(const_cast<char *>(nameTmp));
243 }
244
245 std::string size = android::base::StringPrintf("%zu", getSizes());
246
247 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700248 if (worstUidEnabledForLogid(id)) {
249 size_t totalDropped = 0;
250 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
251 it != stat.uidTable[id].end(); ++it) {
252 totalDropped += it->second.getDropped();
253 }
254 size_t sizes = stat.sizes(id);
255 size_t totalSize = stat.sizesTotal(id);
256 size_t totalElements = stat.elementsTotal(id);
257 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
258 / totalElements;
259 size_t entrySize = getSizes();
260 float virtualEntrySize = entrySize;
261 int realPermille = virtualEntrySize * 1000.0 / sizes;
262 size_t dropped = getDropped();
263 if (dropped) {
264 pruned = android::base::StringPrintf("%zu", dropped);
265 virtualEntrySize += (float)dropped * totalSize / totalElements;
266 }
267 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
268 int permille = (realPermille - virtualPermille) * 1000L
269 / (virtualPermille ?: 1);
270 if ((permille < -1) || (1 < permille)) {
271 std::string change;
272 const char *units = "%";
273 const char *prefix = (permille > 0) ? "+" : "";
274
275 if (permille > 999) {
276 permille = (permille + 1000) / 100; // Now tenths fold
277 units = "X";
278 prefix = "";
279 }
280 if ((-99 < permille) && (permille < 99)) {
281 change = android::base::StringPrintf("%s%d.%u%s",
282 prefix,
283 permille / 10,
284 ((permille < 0) ? (-permille % 10) : (permille % 10)),
285 units);
286 } else {
287 change = android::base::StringPrintf("%s%d%s",
288 prefix,
289 (permille + 5) / 10, units);
290 }
291 ssize_t spaces = EntryBaseConstants::pruned_len
292 - 2 - pruned.length() - change.length();
293 if ((spaces <= 0) && pruned.length()) {
294 spaces = 1;
295 }
Mark Salyzyn0adcc3e2016-07-15 07:40:33 -0700296 if ((spaces > 0) && (pruned.length() != 0)) {
Mark Salyzync723df82015-08-24 11:08:00 -0700297 change += android::base::StringPrintf("%*s", (int)spaces, "");
298 }
299 pruned = change + pruned;
300 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700301 }
302
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700303 std::string output = formatLine(name, size, pruned);
304
305 if (uid != AID_SYSTEM) {
306 return output;
307 }
308
309 static const size_t maximum_sorted_entries = 32;
310 std::unique_ptr<const PidEntry *[]> sorted
311 = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
312
313 if (!sorted.get()) {
314 return output;
315 }
316 std::string byPid;
317 size_t index;
318 bool hasDropped = false;
319 for (index = 0; index < maximum_sorted_entries; ++index) {
320 const PidEntry *entry = sorted[index];
321 if (!entry) {
322 break;
323 }
324 if (entry->getSizes() <= (getSizes() / 100)) {
325 break;
326 }
327 if (entry->getDropped()) {
328 hasDropped = true;
329 }
330 byPid += entry->format(stat, id);
331 }
332 if (index > 1) { // print this only if interesting
333 std::string ditto("\" ");
334 output += formatLine(std::string(" PID/UID COMMAND LINE"),
335 ditto, hasDropped ? ditto : std::string(""));
336 output += byPid;
337 }
338
339 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700340}
341
342std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
343 return formatLine(name,
344 std::string("Size"),
345 std::string("Pruned"))
346 + formatLine(std::string(" PID/UID COMMAND LINE"),
347 std::string("BYTES"),
348 std::string("NUM"));
349}
350
351std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
352 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800353 pid_t pid = getPid();
354 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700355 const char *nameTmp = getName();
356 if (nameTmp) {
357 name += android::base::StringPrintf(
358 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
359 "", nameTmp);
360 } else if ((nameTmp = stat.uidToName(uid))) {
361 name += android::base::StringPrintf(
362 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
363 "", nameTmp);
364 free(const_cast<char *>(nameTmp));
365 }
366
367 std::string size = android::base::StringPrintf("%zu",
368 getSizes());
369
370 std::string pruned = "";
371 size_t dropped = getDropped();
372 if (dropped) {
373 pruned = android::base::StringPrintf("%zu", dropped);
374 }
375
376 return formatLine(name, size, pruned);
377}
378
379std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
380 return formatLine(name,
381 std::string("Size"),
382 std::string("Pruned"))
383 + formatLine(std::string(" TID/UID COMM"),
384 std::string("BYTES"),
385 std::string("NUM"));
386}
387
388std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
389 uid_t uid = getUid();
390 std::string name = android::base::StringPrintf("%5u/%u",
Mark Salyzynee3b8382015-12-17 09:58:43 -0800391 getTid(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700392 const char *nameTmp = getName();
393 if (nameTmp) {
394 name += android::base::StringPrintf(
395 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
396 "", nameTmp);
397 } else if ((nameTmp = stat.uidToName(uid))) {
398 // if we do not have a PID name, lets punt to try UID name?
399 name += android::base::StringPrintf(
400 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
401 "", nameTmp);
402 free(const_cast<char *>(nameTmp));
403 // We tried, better to not have a name at all, we still
404 // have TID/UID by number to report in any case.
405 }
406
407 std::string size = android::base::StringPrintf("%zu",
408 getSizes());
409
410 std::string pruned = "";
411 size_t dropped = getDropped();
412 if (dropped) {
413 pruned = android::base::StringPrintf("%zu", dropped);
414 }
415
416 return formatLine(name, size, pruned);
417}
418
419std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
420 bool isprune = worstUidEnabledForLogid(id);
421 return formatLine(name,
422 std::string("Size"),
423 std::string(isprune ? "Prune" : ""))
424 + formatLine(std::string(" TAG/UID TAGNAME"),
425 std::string("BYTES"),
426 std::string(isprune ? "NUM" : ""));
427}
428
429std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
430 std::string name;
431 uid_t uid = getUid();
432 if (uid == (uid_t)-1) {
433 name = android::base::StringPrintf("%7u",
434 getKey());
435 } else {
436 name = android::base::StringPrintf("%7u/%u",
437 getKey(), uid);
438 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700439 size_t len = 0;
440 const char *nameTmp = getName(len);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700441 if (nameTmp) {
442 name += android::base::StringPrintf(
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700443 "%*s%.*s", (int)std::max(14 - name.length(), (size_t)1),
444 "", (int)len, nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700445 }
446
447 std::string size = android::base::StringPrintf("%zu",
448 getSizes());
449
450 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700451 size_t dropped = getDropped();
452 if (dropped) {
453 pruned = android::base::StringPrintf("%zu", dropped);
454 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700455
456 return formatLine(name, size, pruned);
457}
458
Mark Salyzynee3b8382015-12-17 09:58:43 -0800459std::string LogStatistics::format(uid_t uid, pid_t pid,
460 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700461 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800462
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700463 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800464
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700465 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700466 size_t oldLength;
467 short spaces = 1;
468
469 log_id_for_each(id) {
470 if (!(logMask & (1 << id))) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700471 continue;
472 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700473 oldLength = output.length();
Mark Salyzync8a576c2014-04-04 16:35:59 -0700474 if (spaces < 0) {
475 spaces = 0;
476 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700477 output += android::base::StringPrintf("%*s%s", spaces, "",
478 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700479 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800480 }
481
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700482 spaces = 4;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700483 output += "\nTotal";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800484
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700485 log_id_for_each(id) {
486 if (!(logMask & (1 << id))) {
487 continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800488 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700489 oldLength = output.length();
490 if (spaces < 0) {
491 spaces = 0;
492 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700493 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
494 sizesTotal(id),
495 elementsTotal(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700496 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800497 }
498
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700499 spaces = 6;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700500 output += "\nNow";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800501
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700502 log_id_for_each(id) {
503 if (!(logMask & (1 << id))) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800504 continue;
505 }
506
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700507 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800508 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700509 oldLength = output.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800510 if (spaces < 0) {
511 spaces = 0;
512 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700513 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
514 sizes(id), els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700515 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800516 }
517 spaces += spaces_total;
518 }
519
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700520 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700521
Mark Salyzyn758058f2015-08-21 16:44:30 -0700522 std::string name;
523
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700524 // Chattiest by application (UID)
525 log_id_for_each(id) {
526 if (!(logMask & (1 << id))) {
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700527 continue;
528 }
529
Mark Salyzyn758058f2015-08-21 16:44:30 -0700530 name = (uid == AID_ROOT)
531 ? "Chattiest UIDs in %s log buffer:"
532 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800533 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700534 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700535
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700536 if (enable) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800537 name = ((uid == AID_ROOT) && !pid)
538 ? "Chattiest PIDs:"
539 : "Logging for this PID:";
540 output += pidTable.format(*this, uid, pid, name);
541 name = "Chattiest TIDs";
542 if (pid) {
543 name += android::base::StringPrintf(" for PID %d", pid);
544 }
545 name += ":";
546 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700547 }
548
Mark Salyzyn344bff42015-04-13 14:24:45 -0700549 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800550 name = "Chattiest events log buffer TAGs";
551 if (pid) {
552 name += android::base::StringPrintf(" for PID %d", pid);
553 }
554 name += ":";
555 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700556 }
557
Mark Salyzyn083b0372015-12-04 10:59:45 -0800558 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800559 name = "Chattiest security log buffer TAGs";
560 if (pid) {
561 name += android::base::StringPrintf(" for PID %d", pid);
562 }
563 name += ":";
564 output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800565 }
566
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700567 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800568}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700569
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700570namespace android {
571
572uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700573 char buffer[512];
574 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
575 FILE *fp = fopen(buffer, "r");
576 if (fp) {
577 while (fgets(buffer, sizeof(buffer), fp)) {
578 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700579 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700580 fclose(fp);
581 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700582 }
583 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700584 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700585 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700586 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700587}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700588
589}
590
591uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700592 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700593}
594
595// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700596const char *LogStatistics::pidToName(pid_t pid) const {
597 // An inconvenient truth ... getName() can alter the object
598 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
599 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700600 if (!name) {
601 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700602 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700603 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700604}