blob: 5a706899ec538b65a537122f41cf569e89022095 [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>
Elliott Hughesa744b052015-01-28 11:37:57 -080018#include <malloc.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080019#include <stdarg.h>
20#include <time.h>
21
22#include <log/logger.h>
23#include <private/android_filesystem_config.h>
24#include <utils/String8.h>
25
26#include "LogStatistics.h"
27
Mark Salyzyn9a038632014-04-07 07:05:40 -070028PidStatistics::PidStatistics(pid_t pid, char *name)
Mark Salyzyn34facab2014-02-06 14:48:50 -080029 : pid(pid)
30 , mSizesTotal(0)
31 , mElementsTotal(0)
32 , mSizes(0)
Mark Salyzyn9a038632014-04-07 07:05:40 -070033 , mElements(0)
34 , name(name)
Mark Salyzynfdabe722014-04-21 10:09:42 -070035 , mGone(false)
Mark Salyzyn9a038632014-04-07 07:05:40 -070036{ }
37
38#ifdef DO_NOT_ERROR_IF_PIDSTATISTICS_USES_A_COPY_CONSTRUCTOR
39PidStatistics::PidStatistics(const PidStatistics &copy)
40 : pid(copy->pid)
41 , name(copy->name ? strdup(copy->name) : NULL)
42 , mSizesTotal(copy->mSizesTotal)
43 , mElementsTotal(copy->mElementsTotal)
44 , mSizes(copy->mSizes)
45 , mElements(copy->mElements)
Mark Salyzynfdabe722014-04-21 10:09:42 -070046 , mGone(copy->mGone)
Mark Salyzyn9a038632014-04-07 07:05:40 -070047{ }
48#endif
49
50PidStatistics::~PidStatistics() {
51 free(name);
52}
53
Mark Salyzynfdabe722014-04-21 10:09:42 -070054bool PidStatistics::pidGone() {
Mark Salyzyne72c6e42014-09-21 14:22:18 -070055 if (mGone || (pid == gone)) {
Mark Salyzynfdabe722014-04-21 10:09:42 -070056 return true;
57 }
Mark Salyzyndf5aa612014-09-21 14:22:18 -070058 if (pid == 0) {
59 return false;
60 }
Mark Salyzynfdabe722014-04-21 10:09:42 -070061 if (kill(pid, 0) && (errno != EPERM)) {
62 mGone = true;
63 return true;
64 }
65 return false;
66}
67
Mark Salyzyn9a038632014-04-07 07:05:40 -070068void PidStatistics::setName(char *new_name) {
69 free(name);
70 name = new_name;
71}
Mark Salyzyn34facab2014-02-06 14:48:50 -080072
73void PidStatistics::add(unsigned short size) {
74 mSizesTotal += size;
75 ++mElementsTotal;
76 mSizes += size;
77 ++mElements;
78}
79
80bool PidStatistics::subtract(unsigned short size) {
81 mSizes -= size;
82 --mElements;
Mark Salyzynfdabe722014-04-21 10:09:42 -070083 return (mElements == 0) && pidGone();
Mark Salyzyn34facab2014-02-06 14:48:50 -080084}
85
86void PidStatistics::addTotal(size_t size, size_t element) {
87 if (pid == gone) {
88 mSizesTotal += size;
89 mElementsTotal += element;
90 }
91}
92
Mark Salyzyn9a038632014-04-07 07:05:40 -070093// must call free to release return value
Mark Salyzyne72c6e42014-09-21 14:22:18 -070094// If only we could sniff our own logs for:
95// <time> <pid> <pid> E AndroidRuntime: Process: <name>, PID: <pid>
96// which debuggerd prints as a process is crashing.
Mark Salyzyn9a038632014-04-07 07:05:40 -070097char *PidStatistics::pidToName(pid_t pid) {
98 char *retval = NULL;
Mark Salyzyndf5aa612014-09-21 14:22:18 -070099 if (pid == 0) { // special case from auditd for kernel
100 retval = strdup("logd.auditd");
101 } else if (pid != gone) {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700102 char buffer[512];
103 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
104 int fd = open(buffer, O_RDONLY);
105 if (fd >= 0) {
106 ssize_t ret = read(fd, buffer, sizeof(buffer));
107 if (ret > 0) {
108 buffer[sizeof(buffer)-1] = '\0';
109 // frameworks intermediate state
110 if (strcmp(buffer, "<pre-initialized>")) {
111 retval = strdup(buffer);
112 }
113 }
114 close(fd);
115 }
116 }
117 return retval;
118}
119
Mark Salyzyn34facab2014-02-06 14:48:50 -0800120UidStatistics::UidStatistics(uid_t uid)
Mark Salyzync8a576c2014-04-04 16:35:59 -0700121 : uid(uid)
122 , mSizes(0)
123 , mElements(0) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800124 Pids.clear();
125}
126
127UidStatistics::~UidStatistics() {
128 PidStatisticsCollection::iterator it;
129 for (it = begin(); it != end();) {
130 delete (*it);
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700131 it = erase(it);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800132 }
133}
134
135void UidStatistics::add(unsigned short size, pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700136 mSizes += size;
137 ++mElements;
138
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700139 PidStatistics *p = NULL;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800140 PidStatisticsCollection::iterator last;
141 PidStatisticsCollection::iterator it;
142 for (last = it = begin(); it != end(); last = it, ++it) {
143 p = *it;
144 if (pid == p->getPid()) {
145 p->add(size);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800146 return;
147 }
148 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700149 // insert if the gone entry.
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700150 bool insert_before_last = (last != it) && p && (p->getPid() == p->gone);
Mark Salyzyn9a038632014-04-07 07:05:40 -0700151 p = new PidStatistics(pid, pidToName(pid));
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700152 if (insert_before_last) {
153 insert(last, p);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800154 } else {
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700155 push_back(p);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800156 }
157 p->add(size);
158}
159
160void UidStatistics::subtract(unsigned short size, pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700161 mSizes -= size;
162 --mElements;
163
Mark Salyzyn34facab2014-02-06 14:48:50 -0800164 PidStatisticsCollection::iterator it;
165 for (it = begin(); it != end(); ++it) {
166 PidStatistics *p = *it;
167 if (pid == p->getPid()) {
168 if (p->subtract(size)) {
169 size_t szsTotal = p->sizesTotal();
170 size_t elsTotal = p->elementsTotal();
171 delete p;
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700172 erase(it);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800173 it = end();
174 --it;
175 if (it == end()) {
176 p = new PidStatistics(p->gone);
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700177 push_back(p);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800178 } else {
179 p = *it;
180 if (p->getPid() != p->gone) {
181 p = new PidStatistics(p->gone);
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700182 push_back(p);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800183 }
184 }
185 p->addTotal(szsTotal, elsTotal);
186 }
187 return;
188 }
189 }
190}
191
Mark Salyzync8a576c2014-04-04 16:35:59 -0700192void UidStatistics::sort() {
193 for (bool pass = true; pass;) {
194 pass = false;
195 PidStatisticsCollection::iterator it = begin();
196 if (it != end()) {
197 PidStatisticsCollection::iterator lt = it;
198 PidStatistics *l = (*lt);
199 while (++it != end()) {
200 PidStatistics *n = (*it);
201 if ((n->getPid() != n->gone) && (n->sizes() > l->sizes())) {
202 pass = true;
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700203 erase(it);
204 insert(lt, n);
Mark Salyzync8a576c2014-04-04 16:35:59 -0700205 it = lt;
206 n = l;
207 }
208 lt = it;
209 l = n;
210 }
211 }
212 }
213}
214
Mark Salyzyn34facab2014-02-06 14:48:50 -0800215size_t UidStatistics::sizes(pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700216 if (pid == pid_all) {
217 return sizes();
218 }
219
Mark Salyzyn34facab2014-02-06 14:48:50 -0800220 PidStatisticsCollection::iterator it;
221 for (it = begin(); it != end(); ++it) {
222 PidStatistics *p = *it;
Mark Salyzync8a576c2014-04-04 16:35:59 -0700223 if (pid == p->getPid()) {
224 return p->sizes();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800225 }
226 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700227 return 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800228}
229
230size_t UidStatistics::elements(pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700231 if (pid == pid_all) {
232 return elements();
233 }
234
Mark Salyzyn34facab2014-02-06 14:48:50 -0800235 PidStatisticsCollection::iterator it;
236 for (it = begin(); it != end(); ++it) {
237 PidStatistics *p = *it;
Mark Salyzync8a576c2014-04-04 16:35:59 -0700238 if (pid == p->getPid()) {
239 return p->elements();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800240 }
241 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700242 return 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800243}
244
245size_t UidStatistics::sizesTotal(pid_t pid) {
246 size_t sizes = 0;
247 PidStatisticsCollection::iterator it;
248 for (it = begin(); it != end(); ++it) {
249 PidStatistics *p = *it;
250 if ((pid == pid_all) || (pid == p->getPid())) {
251 sizes += p->sizesTotal();
252 }
253 }
254 return sizes;
255}
256
257size_t UidStatistics::elementsTotal(pid_t pid) {
258 size_t elements = 0;
259 PidStatisticsCollection::iterator it;
260 for (it = begin(); it != end(); ++it) {
261 PidStatistics *p = *it;
262 if ((pid == pid_all) || (pid == p->getPid())) {
263 elements += p->elementsTotal();
264 }
265 }
266 return elements;
267}
268
269LidStatistics::LidStatistics() {
270 Uids.clear();
271}
272
273LidStatistics::~LidStatistics() {
274 UidStatisticsCollection::iterator it;
275 for (it = begin(); it != end();) {
276 delete (*it);
277 it = Uids.erase(it);
278 }
279}
280
281void LidStatistics::add(unsigned short size, uid_t uid, pid_t pid) {
282 UidStatistics *u;
283 UidStatisticsCollection::iterator it;
284 UidStatisticsCollection::iterator last;
285
286 if (uid == (uid_t) -1) { // init
287 uid = (uid_t) AID_ROOT;
288 }
289
290 for (last = it = begin(); it != end(); last = it, ++it) {
291 u = *it;
292 if (uid == u->getUid()) {
293 u->add(size, pid);
294 if ((last != it) && ((*last)->sizesTotal() < u->sizesTotal())) {
295 Uids.erase(it);
296 Uids.insert(last, u);
297 }
298 return;
299 }
300 }
301 u = new UidStatistics(uid);
302 if ((last != it) && ((*last)->sizesTotal() < (size_t) size)) {
303 Uids.insert(last, u);
304 } else {
305 Uids.push_back(u);
306 }
307 u->add(size, pid);
308}
309
310void LidStatistics::subtract(unsigned short size, uid_t uid, pid_t pid) {
Mark Salyzynf48ea7c2014-09-22 10:58:36 -0700311 if (uid == (uid_t) -1) { // init
312 uid = (uid_t) AID_ROOT;
313 }
314
Mark Salyzyn34facab2014-02-06 14:48:50 -0800315 UidStatisticsCollection::iterator it;
316 for (it = begin(); it != end(); ++it) {
317 UidStatistics *u = *it;
318 if (uid == u->getUid()) {
319 u->subtract(size, pid);
320 return;
321 }
322 }
323}
324
Mark Salyzync8a576c2014-04-04 16:35:59 -0700325void LidStatistics::sort() {
326 for (bool pass = true; pass;) {
327 pass = false;
328 UidStatisticsCollection::iterator it = begin();
329 if (it != end()) {
330 UidStatisticsCollection::iterator lt = it;
331 UidStatistics *l = (*lt);
332 while (++it != end()) {
333 UidStatistics *n = (*it);
334 if (n->sizes() > l->sizes()) {
335 pass = true;
336 Uids.erase(it);
337 Uids.insert(lt, n);
338 it = lt;
339 n = l;
340 }
341 lt = it;
342 l = n;
343 }
344 }
345 }
346}
347
Mark Salyzyn34facab2014-02-06 14:48:50 -0800348size_t LidStatistics::sizes(uid_t uid, pid_t pid) {
349 size_t sizes = 0;
350 UidStatisticsCollection::iterator it;
351 for (it = begin(); it != end(); ++it) {
352 UidStatistics *u = *it;
353 if ((uid == uid_all) || (uid == u->getUid())) {
354 sizes += u->sizes(pid);
355 }
356 }
357 return sizes;
358}
359
360size_t LidStatistics::elements(uid_t uid, pid_t pid) {
361 size_t elements = 0;
362 UidStatisticsCollection::iterator it;
363 for (it = begin(); it != end(); ++it) {
364 UidStatistics *u = *it;
365 if ((uid == uid_all) || (uid == u->getUid())) {
366 elements += u->elements(pid);
367 }
368 }
369 return elements;
370}
371
372size_t LidStatistics::sizesTotal(uid_t uid, pid_t pid) {
373 size_t sizes = 0;
374 UidStatisticsCollection::iterator it;
375 for (it = begin(); it != end(); ++it) {
376 UidStatistics *u = *it;
377 if ((uid == uid_all) || (uid == u->getUid())) {
378 sizes += u->sizesTotal(pid);
379 }
380 }
381 return sizes;
382}
383
384size_t LidStatistics::elementsTotal(uid_t uid, pid_t pid) {
385 size_t elements = 0;
386 UidStatisticsCollection::iterator it;
387 for (it = begin(); it != end(); ++it) {
388 UidStatistics *u = *it;
389 if ((uid == uid_all) || (uid == u->getUid())) {
390 elements += u->elementsTotal(pid);
391 }
392 }
393 return elements;
394}
395
396LogStatistics::LogStatistics()
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700397 : mStatistics(false)
Mark Salyzyne72c6e42014-09-21 14:22:18 -0700398 , start(CLOCK_MONOTONIC) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800399 log_id_for_each(i) {
400 mSizes[i] = 0;
401 mElements[i] = 0;
402 }
403}
404
405void LogStatistics::add(unsigned short size,
406 log_id_t log_id, uid_t uid, pid_t pid) {
407 mSizes[log_id] += size;
408 ++mElements[log_id];
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700409 if (!mStatistics) {
410 return;
411 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800412 id(log_id).add(size, uid, pid);
413}
414
415void LogStatistics::subtract(unsigned short size,
416 log_id_t log_id, uid_t uid, pid_t pid) {
417 mSizes[log_id] -= size;
418 --mElements[log_id];
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700419 if (!mStatistics) {
420 return;
421 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800422 id(log_id).subtract(size, uid, pid);
423}
424
425size_t LogStatistics::sizes(log_id_t log_id, uid_t uid, pid_t pid) {
426 if (log_id != log_id_all) {
427 return id(log_id).sizes(uid, pid);
428 }
429 size_t sizes = 0;
430 log_id_for_each(i) {
431 sizes += id(i).sizes(uid, pid);
432 }
433 return sizes;
434}
435
436size_t LogStatistics::elements(log_id_t log_id, uid_t uid, pid_t pid) {
437 if (log_id != log_id_all) {
438 return id(log_id).elements(uid, pid);
439 }
440 size_t elements = 0;
441 log_id_for_each(i) {
442 elements += id(i).elements(uid, pid);
443 }
444 return elements;
445}
446
447size_t LogStatistics::sizesTotal(log_id_t log_id, uid_t uid, pid_t pid) {
448 if (log_id != log_id_all) {
449 return id(log_id).sizesTotal(uid, pid);
450 }
451 size_t sizes = 0;
452 log_id_for_each(i) {
453 sizes += id(i).sizesTotal(uid, pid);
454 }
455 return sizes;
456}
457
458size_t LogStatistics::elementsTotal(log_id_t log_id, uid_t uid, pid_t pid) {
459 if (log_id != log_id_all) {
460 return id(log_id).elementsTotal(uid, pid);
461 }
462 size_t elements = 0;
463 log_id_for_each(i) {
464 elements += id(i).elementsTotal(uid, pid);
465 }
466 return elements;
467}
468
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800469void LogStatistics::format(char **buf,
470 uid_t uid, unsigned int logMask, log_time oldest) {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700471 static const unsigned short spaces_current = 13;
472 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800473
474 if (*buf) {
Greg Hackmann239605e2014-04-06 21:25:58 -0700475 free(*buf);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800476 *buf = NULL;
477 }
478
479 android::String8 string(" span -> size/num");
480 size_t oldLength;
481 short spaces = 2;
482
483 log_id_for_each(i) {
Arseniy Antonovc3ce2242014-09-03 17:29:20 +0400484 if (!(logMask & (1 << i))) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700485 continue;
486 }
487 oldLength = string.length();
488 if (spaces < 0) {
489 spaces = 0;
490 }
491 string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
492 spaces += spaces_total + oldLength - string.length();
493
494 LidStatistics &l = id(i);
495 l.sort();
496
497 UidStatisticsCollection::iterator iu;
498 for (iu = l.begin(); iu != l.end(); ++iu) {
499 (*iu)->sort();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800500 }
501 }
502
503 spaces = 1;
504 log_time t(CLOCK_MONOTONIC);
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700505 unsigned long long d;
506 if (mStatistics) {
507 d = t.nsec() - start.nsec();
508 string.appendFormat("\nTotal%4llu:%02llu:%02llu.%09llu",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800509 d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
510 (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
511
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700512 log_id_for_each(i) {
513 if (!(logMask & (1 << i))) {
514 continue;
515 }
516 oldLength = string.length();
517 if (spaces < 0) {
518 spaces = 0;
519 }
520 string.appendFormat("%*s%zu/%zu", spaces, "",
521 sizesTotal(i), elementsTotal(i));
522 spaces += spaces_total + oldLength - string.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800523 }
Mark Salyzynf5fc5092014-09-21 14:22:18 -0700524 spaces = 1;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800525 }
526
Mark Salyzyn34facab2014-02-06 14:48:50 -0800527 d = t.nsec() - oldest.nsec();
528 string.appendFormat("\nNow%6llu:%02llu:%02llu.%09llu",
529 d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
530 (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
531
532 log_id_for_each(i) {
533 if (!(logMask & (1 << i))) {
534 continue;
535 }
536
537 size_t els = elements(i);
538 if (els) {
539 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800540 if (spaces < 0) {
541 spaces = 0;
542 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800543 string.appendFormat("%*s%zu/%zu", spaces, "", sizes(i), els);
544 spaces -= string.length() - oldLength;
545 }
546 spaces += spaces_total;
547 }
548
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700549 // Construct list of worst spammers by Pid
550 static const unsigned char num_spammers = 10;
551 bool header = false;
552
553 log_id_for_each(i) {
554 if (!(logMask & (1 << i))) {
555 continue;
556 }
557
558 PidStatisticsCollection pids;
559 pids.clear();
560
561 LidStatistics &l = id(i);
562 UidStatisticsCollection::iterator iu;
563 for (iu = l.begin(); iu != l.end(); ++iu) {
564 UidStatistics &u = *(*iu);
565 PidStatisticsCollection::iterator ip;
566 for (ip = u.begin(); ip != u.end(); ++ip) {
567 PidStatistics *p = (*ip);
568 if (p->getPid() == p->gone) {
569 break;
570 }
571
572 size_t mySizes = p->sizes();
573
574 PidStatisticsCollection::iterator q;
575 unsigned char num = 0;
576 for (q = pids.begin(); q != pids.end(); ++q) {
577 if (mySizes > (*q)->sizes()) {
578 pids.insert(q, p);
579 break;
580 }
581 // do we need to traverse deeper in the list?
582 if (++num > num_spammers) {
583 break;
584 }
585 }
586 if (q == pids.end()) {
587 pids.push_back(p);
588 }
589 }
590 }
591
592 size_t threshold = sizes(i);
593 if (threshold < 65536) {
594 threshold = 65536;
595 }
596 threshold /= 100;
597
598 PidStatisticsCollection::iterator pt = pids.begin();
599
600 for(int line = 0;
601 (pt != pids.end()) && (line < num_spammers);
602 ++line, pt = pids.erase(pt)) {
603 PidStatistics *p = *pt;
604
605 size_t sizes = p->sizes();
606 if (sizes < threshold) {
607 break;
608 }
609
610 char *name = p->getName();
611 pid_t pid = p->getPid();
612 if (!name || !*name) {
613 name = pidToName(pid);
614 if (name) {
615 if (*name) {
616 p->setName(name);
617 } else {
618 free(name);
619 name = NULL;
620 }
621 }
622 }
623
624 if (!header) {
625 string.appendFormat("\n\nChattiest clients:\n"
626 "log id %-*s PID[?] name",
627 spaces_total, "size/total");
628 header = true;
629 }
630
631 size_t sizesTotal = p->sizesTotal();
632
633 android::String8 sz("");
Chih-Hung Hsieh634118e2014-09-12 16:02:28 -0700634 if (sizes == sizesTotal) {
635 sz.appendFormat("%zu", sizes);
636 } else {
637 sz.appendFormat("%zu/%zu", sizes, sizesTotal);
638 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700639
640 android::String8 pd("");
Mark Salyzynfdabe722014-04-21 10:09:42 -0700641 pd.appendFormat("%u%c", pid, p->pidGone() ? '?' : ' ');
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700642
643 string.appendFormat("\n%-7s%-*s %-7s%s",
644 line ? "" : android_log_id_to_name(i),
645 spaces_total, sz.string(), pd.string(),
646 name ? name : "");
647 }
648
649 pids.clear();
650 }
651
Mark Salyzyn34facab2014-02-06 14:48:50 -0800652 log_id_for_each(i) {
653 if (!(logMask & (1 << i))) {
654 continue;
655 }
656
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700657 header = false;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800658 bool first = true;
659
660 UidStatisticsCollection::iterator ut;
661 for(ut = id(i).begin(); ut != id(i).end(); ++ut) {
662 UidStatistics *up = *ut;
663 if ((uid != AID_ROOT) && (uid != up->getUid())) {
664 continue;
665 }
666
667 PidStatisticsCollection::iterator pt = up->begin();
668 if (pt == up->end()) {
669 continue;
670 }
671
672 android::String8 intermediate;
673
674 if (!header) {
675 // header below tuned to match spaces_total and spaces_current
676 spaces = 0;
677 intermediate = string.format("%s: UID/PID Total size/num",
678 android_log_id_to_name(i));
679 string.appendFormat("\n\n%-31sNow "
680 "UID/PID[?] Total Now",
681 intermediate.string());
682 intermediate.clear();
683 header = true;
684 }
685
686 bool oneline = ++pt == up->end();
687 --pt;
688
689 if (!oneline) {
690 first = true;
Mark Salyzyne457b742014-02-19 17:18:31 -0800691 } else if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800692 string.appendFormat("%*s", spaces, "");
693 }
694 spaces = 0;
695
696 uid_t u = up->getUid();
Mark Salyzynfdabe722014-04-21 10:09:42 -0700697 PidStatistics *pp = *pt;
698 pid_t p = pp->getPid();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800699
Chih-Hung Hsieh634118e2014-09-12 16:02:28 -0700700 if (!oneline) {
701 intermediate = string.format("%d", u);
702 } else if (p == PidStatistics::gone) {
703 intermediate = string.format("%d/?", u);
704 } else if (pp->pidGone()) {
705 intermediate = string.format("%d/%d?", u, p);
706 } else {
707 intermediate = string.format("%d/%d", u, p);
708 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700709 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800710 intermediate.string());
711 intermediate.clear();
712
713 size_t elsTotal = up->elementsTotal();
714 oldLength = string.length();
715 string.appendFormat("%zu/%zu", up->sizesTotal(), elsTotal);
716 spaces += spaces_total + oldLength - string.length();
717
718 size_t els = up->elements();
719 if (els == elsTotal) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800720 if (spaces < 0) {
721 spaces = 0;
722 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800723 string.appendFormat("%*s=", spaces, "");
724 spaces = -1;
725 } else if (els) {
726 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800727 if (spaces < 0) {
728 spaces = 0;
729 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800730 string.appendFormat("%*s%zu/%zu", spaces, "", up->sizes(), els);
731 spaces -= string.length() - oldLength;
732 }
733 spaces += spaces_current;
734
735 first = !first;
736
737 if (oneline) {
738 continue;
739 }
740
741 size_t gone_szs = 0;
742 size_t gone_els = 0;
743
744 for(; pt != up->end(); ++pt) {
Mark Salyzynfdabe722014-04-21 10:09:42 -0700745 pp = *pt;
746 p = pp->getPid();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800747
748 // If a PID no longer has any current logs, and is not
749 // active anymore, skip & report totals for gone.
750 elsTotal = pp->elementsTotal();
751 size_t szsTotal = pp->sizesTotal();
752 if (p == pp->gone) {
753 gone_szs += szsTotal;
754 gone_els += elsTotal;
755 continue;
756 }
757 els = pp->elements();
Mark Salyzynfdabe722014-04-21 10:09:42 -0700758 bool gone = pp->pidGone();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800759 if (gone && (els == 0)) {
760 // ToDo: garbage collection: move this statistical bucket
761 // from its current UID/PID to UID/? (races and
762 // wrap around are our achilles heel). Below is
763 // merely lipservice to catch PIDs that were still
764 // around when the stats were pruned to zero.
765 gone_szs += szsTotal;
766 gone_els += elsTotal;
767 continue;
768 }
769
Mark Salyzyne457b742014-02-19 17:18:31 -0800770 if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800771 string.appendFormat("%*s", spaces, "");
772 }
773 spaces = 0;
774
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700775 intermediate = string.format(gone ? "%d/%d?" : "%d/%d", u, p);
776 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800777 intermediate.string());
778 intermediate.clear();
779
780 oldLength = string.length();
781 string.appendFormat("%zu/%zu", szsTotal, elsTotal);
782 spaces += spaces_total + oldLength - string.length();
783
784 if (els == elsTotal) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800785 if (spaces < 0) {
786 spaces = 0;
787 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800788 string.appendFormat("%*s=", spaces, "");
789 spaces = -1;
790 } else if (els) {
791 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800792 if (spaces < 0) {
793 spaces = 0;
794 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800795 string.appendFormat("%*s%zu/%zu", spaces, "",
796 pp->sizes(), els);
797 spaces -= string.length() - oldLength;
798 }
799 spaces += spaces_current;
800
801 first = !first;
802 }
803
804 if (gone_els) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800805 if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800806 string.appendFormat("%*s", spaces, "");
807 }
808
809 intermediate = string.format("%d/?", u);
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700810 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800811 intermediate.string());
812 intermediate.clear();
813
814 spaces = spaces_total + spaces_current;
815
816 oldLength = string.length();
817 string.appendFormat("%zu/%zu", gone_szs, gone_els);
818 spaces -= string.length() - oldLength;
819
820 first = !first;
821 }
822 }
823 }
824
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800825 *buf = strdup(string.string());
Mark Salyzyn34facab2014-02-06 14:48:50 -0800826}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700827
828uid_t LogStatistics::pidToUid(pid_t pid) {
829 log_id_for_each(i) {
830 LidStatistics &l = id(i);
831 UidStatisticsCollection::iterator iu;
832 for (iu = l.begin(); iu != l.end(); ++iu) {
833 UidStatistics &u = *(*iu);
834 PidStatisticsCollection::iterator ip;
835 for (ip = u.begin(); ip != u.end(); ++ip) {
836 if ((*ip)->getPid() == pid) {
837 return u.getUid();
838 }
839 }
840 }
841 }
842 return getuid(); // associate this with the logger
843}