blob: ddbb64fb16adadd387db61c57e10af9870c88d92 [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
Mark Salyzyn9af33ee2016-10-05 12:34:37 -070024#include <list>
25
Mark Salyzynaeaaf812016-09-30 13:30:33 -070026#include <android/log.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080027
28#include "LogStatistics.h"
29
Mark Salyzyn77187782015-05-12 15:21:31 -070030LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070031 log_id_for_each(id) {
32 mSizes[id] = 0;
33 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070034 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070035 mSizesTotal[id] = 0;
36 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080037 }
38}
39
Mark Salyzyn720f6d12015-03-16 08:26:05 -070040namespace android {
41
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070042// caller must own and free character string
Mark Salyzyn81b3eab2015-04-13 14:24:45 -070043char *pidToName(pid_t pid) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070044 char *retval = NULL;
Mark Salyzynae4d9282014-10-15 08:49:39 -070045 if (pid == 0) { // special case from auditd/klogd for kernel
46 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070047 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070048 char buffer[512];
49 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
50 int fd = open(buffer, O_RDONLY);
51 if (fd >= 0) {
52 ssize_t ret = read(fd, buffer, sizeof(buffer));
53 if (ret > 0) {
54 buffer[sizeof(buffer)-1] = '\0';
55 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080056 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070057 retval = strdup(buffer);
58 }
59 }
60 close(fd);
61 }
62 }
63 return retval;
64}
65
Mark Salyzyn720f6d12015-03-16 08:26:05 -070066}
67
Mark Salyzyn758058f2015-08-21 16:44:30 -070068void LogStatistics::add(LogBufferElement *element) {
69 log_id_t log_id = element->getLogId();
70 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080071 mSizes[log_id] += size;
72 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070073
Mark Salyzyna2c02222016-12-13 10:31:29 -080074 if (element->getDropped()) {
75 ++mDroppedElements[log_id];
76 } else {
77 // When caller adding a chatty entry, they will have already
78 // called add() and subtract() for each entry as they are
79 // evaluated and trimmed, thus recording size and number of
80 // elements, but we must recognize the manufactured dropped
81 // entry as not contributing to the lifetime totals.
82 mSizesTotal[log_id] += size;
83 ++mElementsTotal[log_id];
84 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -070085
Mark Salyzynae4d9282014-10-15 08:49:39 -070086 if (log_id == LOG_ID_KERNEL) {
87 return;
88 }
89
Mark Salyzyn758058f2015-08-21 16:44:30 -070090 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070091 if (element->getUid() == AID_SYSTEM) {
92 pidSystemTable[log_id].add(element->getPid(), element);
93 }
Mark Salyzynae4d9282014-10-15 08:49:39 -070094
Mark Salyzyn720f6d12015-03-16 08:26:05 -070095 if (!enable) {
96 return;
97 }
98
Mark Salyzyn758058f2015-08-21 16:44:30 -070099 pidTable.add(element->getPid(), element);
100 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700101
Mark Salyzyn758058f2015-08-21 16:44:30 -0700102 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700103 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800104 if (log_id == LOG_ID_SECURITY) {
105 securityTagTable.add(tag, element);
106 } else {
107 tagTable.add(tag, element);
108 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700109 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800110}
111
Mark Salyzyn758058f2015-08-21 16:44:30 -0700112void LogStatistics::subtract(LogBufferElement *element) {
113 log_id_t log_id = element->getLogId();
114 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800115 mSizes[log_id] -= size;
116 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700117 if (element->getDropped()) {
118 --mDroppedElements[log_id];
119 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700120
Mark Salyzynae4d9282014-10-15 08:49:39 -0700121 if (log_id == LOG_ID_KERNEL) {
122 return;
123 }
124
Mark Salyzyn758058f2015-08-21 16:44:30 -0700125 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700126 if (element->getUid() == AID_SYSTEM) {
127 pidSystemTable[log_id].subtract(element->getPid(), element);
128 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800129
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700130 if (!enable) {
131 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800132 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700133
Mark Salyzyn758058f2015-08-21 16:44:30 -0700134 pidTable.subtract(element->getPid(), element);
135 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700136
Mark Salyzyn758058f2015-08-21 16:44:30 -0700137 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700138 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800139 if (log_id == LOG_ID_SECURITY) {
140 securityTagTable.subtract(tag, element);
141 } else {
142 tagTable.subtract(tag, element);
143 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700144 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800145}
146
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700147// Atomically set an entry to drop
148// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700149void LogStatistics::drop(LogBufferElement *element) {
150 log_id_t log_id = element->getLogId();
151 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700152 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700153 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700154
Mark Salyzyn758058f2015-08-21 16:44:30 -0700155 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700156 if (element->getUid() == AID_SYSTEM) {
157 pidSystemTable[log_id].drop(element->getPid(), element);
158 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700159
160 if (!enable) {
161 return;
162 }
163
Mark Salyzyn758058f2015-08-21 16:44:30 -0700164 pidTable.drop(element->getPid(), element);
165 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700166
167 uint32_t tag = element->getTag();
168 if (tag) {
169 if (log_id == LOG_ID_SECURITY) {
170 securityTagTable.drop(tag, element);
171 } else {
172 tagTable.drop(tag, element);
173 }
174 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700175}
176
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700177// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700178const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700179 // Local hard coded favourites
180 if (uid == AID_LOGD) {
181 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800182 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700183
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700184 // Android system
185 if (uid < AID_APP) {
186 // in bionic, thread safe as long as we copy the results
187 struct passwd *pwd = getpwuid(uid);
188 if (pwd) {
189 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700190 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800191 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700192
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700193 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700194 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700195 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700196 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
197 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
198 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700199 if (name) {
200 return name;
201 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700202
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700203 // Android application
204 if (uid >= AID_APP) {
205 struct passwd *pwd = getpwuid(uid);
206 if (pwd) {
207 return strdup(pwd->pw_name);
208 }
209 }
210
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700211 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700212 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700213 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700214
215 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700216 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700217
Mark Salyzyn758058f2015-08-21 16:44:30 -0700218 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700219 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700220 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800221 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700222 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700223 name = NULL;
224 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700225 }
226 }
227 }
228 }
229
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700230 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700231 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800232}
233
Mark Salyzyn758058f2015-08-21 16:44:30 -0700234std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
235 bool isprune = worstUidEnabledForLogid(id);
236 return formatLine(android::base::StringPrintf(
237 name.c_str(), android_log_id_to_name(id)),
238 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700239 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700240 + formatLine(std::string("UID PACKAGE"),
241 std::string("BYTES"),
242 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800243}
244
Mark Salyzync723df82015-08-24 11:08:00 -0700245std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800246 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700247 std::string name = android::base::StringPrintf("%u", uid);
248 const char *nameTmp = stat.uidToName(uid);
249 if (nameTmp) {
250 name += android::base::StringPrintf(
251 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
252 "", nameTmp);
253 free(const_cast<char *>(nameTmp));
254 }
255
256 std::string size = android::base::StringPrintf("%zu", getSizes());
257
258 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700259 if (worstUidEnabledForLogid(id)) {
260 size_t totalDropped = 0;
261 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
262 it != stat.uidTable[id].end(); ++it) {
263 totalDropped += it->second.getDropped();
264 }
265 size_t sizes = stat.sizes(id);
266 size_t totalSize = stat.sizesTotal(id);
267 size_t totalElements = stat.elementsTotal(id);
268 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
269 / totalElements;
270 size_t entrySize = getSizes();
271 float virtualEntrySize = entrySize;
272 int realPermille = virtualEntrySize * 1000.0 / sizes;
273 size_t dropped = getDropped();
274 if (dropped) {
275 pruned = android::base::StringPrintf("%zu", dropped);
276 virtualEntrySize += (float)dropped * totalSize / totalElements;
277 }
278 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
279 int permille = (realPermille - virtualPermille) * 1000L
280 / (virtualPermille ?: 1);
281 if ((permille < -1) || (1 < permille)) {
282 std::string change;
283 const char *units = "%";
284 const char *prefix = (permille > 0) ? "+" : "";
285
286 if (permille > 999) {
287 permille = (permille + 1000) / 100; // Now tenths fold
288 units = "X";
289 prefix = "";
290 }
291 if ((-99 < permille) && (permille < 99)) {
292 change = android::base::StringPrintf("%s%d.%u%s",
293 prefix,
294 permille / 10,
295 ((permille < 0) ? (-permille % 10) : (permille % 10)),
296 units);
297 } else {
298 change = android::base::StringPrintf("%s%d%s",
299 prefix,
300 (permille + 5) / 10, units);
301 }
302 ssize_t spaces = EntryBaseConstants::pruned_len
303 - 2 - pruned.length() - change.length();
304 if ((spaces <= 0) && pruned.length()) {
305 spaces = 1;
306 }
Mark Salyzyn0adcc3e2016-07-15 07:40:33 -0700307 if ((spaces > 0) && (pruned.length() != 0)) {
Mark Salyzync723df82015-08-24 11:08:00 -0700308 change += android::base::StringPrintf("%*s", (int)spaces, "");
309 }
310 pruned = change + pruned;
311 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700312 }
313
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700314 std::string output = formatLine(name, size, pruned);
315
316 if (uid != AID_SYSTEM) {
317 return output;
318 }
319
320 static const size_t maximum_sorted_entries = 32;
321 std::unique_ptr<const PidEntry *[]> sorted
322 = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
323
324 if (!sorted.get()) {
325 return output;
326 }
327 std::string byPid;
328 size_t index;
329 bool hasDropped = false;
330 for (index = 0; index < maximum_sorted_entries; ++index) {
331 const PidEntry *entry = sorted[index];
332 if (!entry) {
333 break;
334 }
335 if (entry->getSizes() <= (getSizes() / 100)) {
336 break;
337 }
338 if (entry->getDropped()) {
339 hasDropped = true;
340 }
341 byPid += entry->format(stat, id);
342 }
343 if (index > 1) { // print this only if interesting
344 std::string ditto("\" ");
345 output += formatLine(std::string(" PID/UID COMMAND LINE"),
346 ditto, hasDropped ? ditto : std::string(""));
347 output += byPid;
348 }
349
350 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700351}
352
353std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
354 return formatLine(name,
355 std::string("Size"),
356 std::string("Pruned"))
357 + formatLine(std::string(" PID/UID COMMAND LINE"),
358 std::string("BYTES"),
359 std::string("NUM"));
360}
361
362std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
363 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800364 pid_t pid = getPid();
365 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700366 const char *nameTmp = getName();
367 if (nameTmp) {
368 name += android::base::StringPrintf(
369 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
370 "", nameTmp);
371 } else if ((nameTmp = stat.uidToName(uid))) {
372 name += android::base::StringPrintf(
373 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
374 "", nameTmp);
375 free(const_cast<char *>(nameTmp));
376 }
377
378 std::string size = android::base::StringPrintf("%zu",
379 getSizes());
380
381 std::string pruned = "";
382 size_t dropped = getDropped();
383 if (dropped) {
384 pruned = android::base::StringPrintf("%zu", dropped);
385 }
386
387 return formatLine(name, size, pruned);
388}
389
390std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
391 return formatLine(name,
392 std::string("Size"),
393 std::string("Pruned"))
394 + formatLine(std::string(" TID/UID COMM"),
395 std::string("BYTES"),
396 std::string("NUM"));
397}
398
399std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
400 uid_t uid = getUid();
401 std::string name = android::base::StringPrintf("%5u/%u",
Mark Salyzynee3b8382015-12-17 09:58:43 -0800402 getTid(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700403 const char *nameTmp = getName();
404 if (nameTmp) {
405 name += android::base::StringPrintf(
406 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
407 "", nameTmp);
408 } else if ((nameTmp = stat.uidToName(uid))) {
409 // if we do not have a PID name, lets punt to try UID name?
410 name += android::base::StringPrintf(
411 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
412 "", nameTmp);
413 free(const_cast<char *>(nameTmp));
414 // We tried, better to not have a name at all, we still
415 // have TID/UID by number to report in any case.
416 }
417
418 std::string size = android::base::StringPrintf("%zu",
419 getSizes());
420
421 std::string pruned = "";
422 size_t dropped = getDropped();
423 if (dropped) {
424 pruned = android::base::StringPrintf("%zu", dropped);
425 }
426
427 return formatLine(name, size, pruned);
428}
429
430std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
431 bool isprune = worstUidEnabledForLogid(id);
432 return formatLine(name,
433 std::string("Size"),
434 std::string(isprune ? "Prune" : ""))
435 + formatLine(std::string(" TAG/UID TAGNAME"),
436 std::string("BYTES"),
437 std::string(isprune ? "NUM" : ""));
438}
439
440std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
441 std::string name;
442 uid_t uid = getUid();
443 if (uid == (uid_t)-1) {
444 name = android::base::StringPrintf("%7u",
445 getKey());
446 } else {
447 name = android::base::StringPrintf("%7u/%u",
448 getKey(), uid);
449 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700450 size_t len = 0;
451 const char *nameTmp = getName(len);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700452 if (nameTmp) {
453 name += android::base::StringPrintf(
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700454 "%*s%.*s", (int)std::max(14 - name.length(), (size_t)1),
455 "", (int)len, nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700456 }
457
458 std::string size = android::base::StringPrintf("%zu",
459 getSizes());
460
461 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700462 size_t dropped = getDropped();
463 if (dropped) {
464 pruned = android::base::StringPrintf("%zu", dropped);
465 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700466
467 return formatLine(name, size, pruned);
468}
469
Mark Salyzynee3b8382015-12-17 09:58:43 -0800470std::string LogStatistics::format(uid_t uid, pid_t pid,
471 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700472 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800473
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700474 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800475
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700476 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700477 size_t oldLength;
478 short spaces = 1;
479
480 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700481 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700482 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700483 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700484 output += android::base::StringPrintf("%*s%s", spaces, "",
485 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700486 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800487 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700488 if (spaces < 0) spaces = 0;
489 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800490
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700491 static const char TotalStr[] = "\nTotal";
492 spaces = 10 - strlen(TotalStr);
493 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800494
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700495 size_t totalSize = 0;
496 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700497 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700498 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700499 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700500 if (spaces < 0) spaces = 0;
501 size_t szs = sizesTotal(id);
502 totalSize += szs;
503 size_t els = elementsTotal(id);
504 totalEls += els;
505 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700506 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800507 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700508 if (spaces < 0) spaces = 0;
509 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800510
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700511 static const char NowStr[] = "\nNow";
512 spaces = 10 - strlen(NowStr);
513 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800514
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700515 totalSize = 0;
516 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700517 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700518 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800519
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700520 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800521 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700522 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700523 if (spaces < 0) spaces = 0;
524 size_t szs = sizes(id);
525 totalSize += szs;
526 totalEls += els;
527 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700528 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800529 }
530 spaces += spaces_total;
531 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700532 if (spaces < 0) spaces = 0;
533 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
534
535 static const char OverheadStr[] = "\nOverhead";
536 spaces = 10 - strlen(OverheadStr);
537 output += OverheadStr;
538
539 totalSize = 0;
540 log_id_for_each(id) {
541 if (!(logMask & (1 << id))) continue;
542
543 size_t els = elements(id);
544 if (els) {
545 oldLength = output.length();
546 if (spaces < 0) spaces = 0;
547 // estimate the std::list overhead.
548 static const size_t overhead =
549 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
550 -sizeof(uint64_t)) +
551 sizeof(std::list<LogBufferElement*>);
552 size_t szs = sizes(id) + els * overhead;
553 totalSize += szs;
554 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
555 spaces -= output.length() - oldLength;
556 }
557 spaces += spaces_total;
558 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700559 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700560 if (spaces < 0) spaces = 0;
561 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800562
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700563 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700564
Mark Salyzyn758058f2015-08-21 16:44:30 -0700565 std::string name;
566
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700567 // Chattiest by application (UID)
568 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700569 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700570
Mark Salyzyn758058f2015-08-21 16:44:30 -0700571 name = (uid == AID_ROOT)
572 ? "Chattiest UIDs in %s log buffer:"
573 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800574 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700575 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700576
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700577 if (enable) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800578 name = ((uid == AID_ROOT) && !pid)
579 ? "Chattiest PIDs:"
580 : "Logging for this PID:";
581 output += pidTable.format(*this, uid, pid, name);
582 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700583 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800584 name += ":";
585 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700586 }
587
Mark Salyzyn344bff42015-04-13 14:24:45 -0700588 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800589 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700590 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800591 name += ":";
592 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700593 }
594
Mark Salyzyn083b0372015-12-04 10:59:45 -0800595 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800596 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700597 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800598 name += ":";
599 output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800600 }
601
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700602 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800603}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700604
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700605namespace android {
606
607uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700608 char buffer[512];
609 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
610 FILE *fp = fopen(buffer, "r");
611 if (fp) {
612 while (fgets(buffer, sizeof(buffer), fp)) {
613 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700614 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700615 fclose(fp);
616 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700617 }
618 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700619 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700620 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700621 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700622}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700623
624}
625
626uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700627 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700628}
629
630// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700631const char *LogStatistics::pidToName(pid_t pid) const {
632 // An inconvenient truth ... getName() can alter the object
633 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
634 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700635 if (!name) {
636 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700637 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700638 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700639}