blob: 2b02bc1d708c8aef666e40419706a7175f6e8b62 [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 Salyzyn97c1c2b2015-03-10 13:51:35 -070018#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070019#include <string.h>
20#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080021
22#include <log/logger.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080023
24#include "LogStatistics.h"
25
Mark Salyzyn77187782015-05-12 15:21:31 -070026LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070027 log_id_for_each(id) {
28 mSizes[id] = 0;
29 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070030 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070031 mSizesTotal[id] = 0;
32 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080033 }
34}
35
Mark Salyzyn720f6d12015-03-16 08:26:05 -070036namespace android {
37
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070038// caller must own and free character string
Mark Salyzyn81b3eab2015-04-13 14:24:45 -070039char *pidToName(pid_t pid) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070040 char *retval = NULL;
Mark Salyzynae4d9282014-10-15 08:49:39 -070041 if (pid == 0) { // special case from auditd/klogd for kernel
42 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070043 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070044 char buffer[512];
45 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
46 int fd = open(buffer, O_RDONLY);
47 if (fd >= 0) {
48 ssize_t ret = read(fd, buffer, sizeof(buffer));
49 if (ret > 0) {
50 buffer[sizeof(buffer)-1] = '\0';
51 // frameworks intermediate state
Mark Salyzynddda2122015-10-02 09:22:52 -070052 if (fast<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070053 retval = strdup(buffer);
54 }
55 }
56 close(fd);
57 }
58 }
59 return retval;
60}
61
Mark Salyzyn720f6d12015-03-16 08:26:05 -070062}
63
Mark Salyzyn758058f2015-08-21 16:44:30 -070064void LogStatistics::add(LogBufferElement *element) {
65 log_id_t log_id = element->getLogId();
66 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080067 mSizes[log_id] += size;
68 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070069
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070070 mSizesTotal[log_id] += size;
71 ++mElementsTotal[log_id];
Mark Salyzyn720f6d12015-03-16 08:26:05 -070072
Mark Salyzynae4d9282014-10-15 08:49:39 -070073 if (log_id == LOG_ID_KERNEL) {
74 return;
75 }
76
Mark Salyzyn758058f2015-08-21 16:44:30 -070077 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070078 if (element->getUid() == AID_SYSTEM) {
79 pidSystemTable[log_id].add(element->getPid(), element);
80 }
Mark Salyzynae4d9282014-10-15 08:49:39 -070081
Mark Salyzyn720f6d12015-03-16 08:26:05 -070082 if (!enable) {
83 return;
84 }
85
Mark Salyzyn758058f2015-08-21 16:44:30 -070086 pidTable.add(element->getPid(), element);
87 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -070088
Mark Salyzyn758058f2015-08-21 16:44:30 -070089 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -070090 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -080091 if (log_id == LOG_ID_SECURITY) {
92 securityTagTable.add(tag, element);
93 } else {
94 tagTable.add(tag, element);
95 }
Mark Salyzyn344bff42015-04-13 14:24:45 -070096 }
Mark Salyzyn34facab2014-02-06 14:48:50 -080097}
98
Mark Salyzyn758058f2015-08-21 16:44:30 -070099void LogStatistics::subtract(LogBufferElement *element) {
100 log_id_t log_id = element->getLogId();
101 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800102 mSizes[log_id] -= size;
103 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700104 if (element->getDropped()) {
105 --mDroppedElements[log_id];
106 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700107
Mark Salyzynae4d9282014-10-15 08:49:39 -0700108 if (log_id == LOG_ID_KERNEL) {
109 return;
110 }
111
Mark Salyzyn758058f2015-08-21 16:44:30 -0700112 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700113 if (element->getUid() == AID_SYSTEM) {
114 pidSystemTable[log_id].subtract(element->getPid(), element);
115 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800116
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700117 if (!enable) {
118 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800119 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700120
Mark Salyzyn758058f2015-08-21 16:44:30 -0700121 pidTable.subtract(element->getPid(), element);
122 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700123
Mark Salyzyn758058f2015-08-21 16:44:30 -0700124 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700125 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800126 if (log_id == LOG_ID_SECURITY) {
127 securityTagTable.subtract(tag, element);
128 } else {
129 tagTable.subtract(tag, element);
130 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700131 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800132}
133
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700134// Atomically set an entry to drop
135// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700136void LogStatistics::drop(LogBufferElement *element) {
137 log_id_t log_id = element->getLogId();
138 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700139 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700140 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700141
Mark Salyzyn758058f2015-08-21 16:44:30 -0700142 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700143 if (element->getUid() == AID_SYSTEM) {
144 pidSystemTable[log_id].drop(element->getPid(), element);
145 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700146
147 if (!enable) {
148 return;
149 }
150
Mark Salyzyn758058f2015-08-21 16:44:30 -0700151 pidTable.drop(element->getPid(), element);
152 tidTable.drop(element->getTid(), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700153}
154
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700155// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700156const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700157 // Local hard coded favourites
158 if (uid == AID_LOGD) {
159 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800160 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700161
162 // Android hard coded
163 const struct android_id_info *info = android_ids;
164
165 for (size_t i = 0; i < android_id_count; ++i) {
166 if (info->aid == uid) {
167 return strdup(info->name);
168 }
169 ++info;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800170 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700171
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700172 // Parse /data/system/packages.list
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700173 uid_t userId = uid % AID_USER;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700174 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700175 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
176 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
177 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700178 if (name) {
179 return name;
180 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700181
182 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700183 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700184 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700185
186 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700187 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700188
Mark Salyzyn758058f2015-08-21 16:44:30 -0700189 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700190 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700191 name = strdup(nameTmp);
192 } else if (fast<strcmp>(name, nameTmp)) {
193 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700194 name = NULL;
195 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700196 }
197 }
198 }
199 }
200
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700201 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700202 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800203}
204
Mark Salyzyn758058f2015-08-21 16:44:30 -0700205std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
206 bool isprune = worstUidEnabledForLogid(id);
207 return formatLine(android::base::StringPrintf(
208 name.c_str(), android_log_id_to_name(id)),
209 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700210 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700211 + formatLine(std::string("UID PACKAGE"),
212 std::string("BYTES"),
213 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800214}
215
Mark Salyzync723df82015-08-24 11:08:00 -0700216std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800217 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700218 std::string name = android::base::StringPrintf("%u", uid);
219 const char *nameTmp = stat.uidToName(uid);
220 if (nameTmp) {
221 name += android::base::StringPrintf(
222 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
223 "", nameTmp);
224 free(const_cast<char *>(nameTmp));
225 }
226
227 std::string size = android::base::StringPrintf("%zu", getSizes());
228
229 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700230 if (worstUidEnabledForLogid(id)) {
231 size_t totalDropped = 0;
232 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
233 it != stat.uidTable[id].end(); ++it) {
234 totalDropped += it->second.getDropped();
235 }
236 size_t sizes = stat.sizes(id);
237 size_t totalSize = stat.sizesTotal(id);
238 size_t totalElements = stat.elementsTotal(id);
239 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
240 / totalElements;
241 size_t entrySize = getSizes();
242 float virtualEntrySize = entrySize;
243 int realPermille = virtualEntrySize * 1000.0 / sizes;
244 size_t dropped = getDropped();
245 if (dropped) {
246 pruned = android::base::StringPrintf("%zu", dropped);
247 virtualEntrySize += (float)dropped * totalSize / totalElements;
248 }
249 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
250 int permille = (realPermille - virtualPermille) * 1000L
251 / (virtualPermille ?: 1);
252 if ((permille < -1) || (1 < permille)) {
253 std::string change;
254 const char *units = "%";
255 const char *prefix = (permille > 0) ? "+" : "";
256
257 if (permille > 999) {
258 permille = (permille + 1000) / 100; // Now tenths fold
259 units = "X";
260 prefix = "";
261 }
262 if ((-99 < permille) && (permille < 99)) {
263 change = android::base::StringPrintf("%s%d.%u%s",
264 prefix,
265 permille / 10,
266 ((permille < 0) ? (-permille % 10) : (permille % 10)),
267 units);
268 } else {
269 change = android::base::StringPrintf("%s%d%s",
270 prefix,
271 (permille + 5) / 10, units);
272 }
273 ssize_t spaces = EntryBaseConstants::pruned_len
274 - 2 - pruned.length() - change.length();
275 if ((spaces <= 0) && pruned.length()) {
276 spaces = 1;
277 }
278 if (spaces > 0) {
279 change += android::base::StringPrintf("%*s", (int)spaces, "");
280 }
281 pruned = change + pruned;
282 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700283 }
284
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700285 std::string output = formatLine(name, size, pruned);
286
287 if (uid != AID_SYSTEM) {
288 return output;
289 }
290
291 static const size_t maximum_sorted_entries = 32;
292 std::unique_ptr<const PidEntry *[]> sorted
293 = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
294
295 if (!sorted.get()) {
296 return output;
297 }
298 std::string byPid;
299 size_t index;
300 bool hasDropped = false;
301 for (index = 0; index < maximum_sorted_entries; ++index) {
302 const PidEntry *entry = sorted[index];
303 if (!entry) {
304 break;
305 }
306 if (entry->getSizes() <= (getSizes() / 100)) {
307 break;
308 }
309 if (entry->getDropped()) {
310 hasDropped = true;
311 }
312 byPid += entry->format(stat, id);
313 }
314 if (index > 1) { // print this only if interesting
315 std::string ditto("\" ");
316 output += formatLine(std::string(" PID/UID COMMAND LINE"),
317 ditto, hasDropped ? ditto : std::string(""));
318 output += byPid;
319 }
320
321 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700322}
323
324std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
325 return formatLine(name,
326 std::string("Size"),
327 std::string("Pruned"))
328 + formatLine(std::string(" PID/UID COMMAND LINE"),
329 std::string("BYTES"),
330 std::string("NUM"));
331}
332
333std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
334 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800335 pid_t pid = getPid();
336 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700337 const char *nameTmp = getName();
338 if (nameTmp) {
339 name += android::base::StringPrintf(
340 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
341 "", nameTmp);
342 } else if ((nameTmp = stat.uidToName(uid))) {
343 name += android::base::StringPrintf(
344 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
345 "", nameTmp);
346 free(const_cast<char *>(nameTmp));
347 }
348
349 std::string size = android::base::StringPrintf("%zu",
350 getSizes());
351
352 std::string pruned = "";
353 size_t dropped = getDropped();
354 if (dropped) {
355 pruned = android::base::StringPrintf("%zu", dropped);
356 }
357
358 return formatLine(name, size, pruned);
359}
360
361std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
362 return formatLine(name,
363 std::string("Size"),
364 std::string("Pruned"))
365 + formatLine(std::string(" TID/UID COMM"),
366 std::string("BYTES"),
367 std::string("NUM"));
368}
369
370std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
371 uid_t uid = getUid();
372 std::string name = android::base::StringPrintf("%5u/%u",
Mark Salyzynee3b8382015-12-17 09:58:43 -0800373 getTid(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700374 const char *nameTmp = getName();
375 if (nameTmp) {
376 name += android::base::StringPrintf(
377 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
378 "", nameTmp);
379 } else if ((nameTmp = stat.uidToName(uid))) {
380 // if we do not have a PID name, lets punt to try UID name?
381 name += android::base::StringPrintf(
382 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
383 "", nameTmp);
384 free(const_cast<char *>(nameTmp));
385 // We tried, better to not have a name at all, we still
386 // have TID/UID by number to report in any case.
387 }
388
389 std::string size = android::base::StringPrintf("%zu",
390 getSizes());
391
392 std::string pruned = "";
393 size_t dropped = getDropped();
394 if (dropped) {
395 pruned = android::base::StringPrintf("%zu", dropped);
396 }
397
398 return formatLine(name, size, pruned);
399}
400
401std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
402 bool isprune = worstUidEnabledForLogid(id);
403 return formatLine(name,
404 std::string("Size"),
405 std::string(isprune ? "Prune" : ""))
406 + formatLine(std::string(" TAG/UID TAGNAME"),
407 std::string("BYTES"),
408 std::string(isprune ? "NUM" : ""));
409}
410
411std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
412 std::string name;
413 uid_t uid = getUid();
414 if (uid == (uid_t)-1) {
415 name = android::base::StringPrintf("%7u",
416 getKey());
417 } else {
418 name = android::base::StringPrintf("%7u/%u",
419 getKey(), uid);
420 }
421 const char *nameTmp = getName();
422 if (nameTmp) {
423 name += android::base::StringPrintf(
424 "%*s%s", (int)std::max(14 - name.length(), (size_t)1),
425 "", nameTmp);
426 }
427
428 std::string size = android::base::StringPrintf("%zu",
429 getSizes());
430
431 std::string pruned = "";
432
433 return formatLine(name, size, pruned);
434}
435
Mark Salyzynee3b8382015-12-17 09:58:43 -0800436std::string LogStatistics::format(uid_t uid, pid_t pid,
437 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700438 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800439
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700440 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800441
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700442 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700443 size_t oldLength;
444 short spaces = 1;
445
446 log_id_for_each(id) {
447 if (!(logMask & (1 << id))) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700448 continue;
449 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700450 oldLength = output.length();
Mark Salyzync8a576c2014-04-04 16:35:59 -0700451 if (spaces < 0) {
452 spaces = 0;
453 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700454 output += android::base::StringPrintf("%*s%s", spaces, "",
455 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700456 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800457 }
458
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700459 spaces = 4;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700460 output += "\nTotal";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800461
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700462 log_id_for_each(id) {
463 if (!(logMask & (1 << id))) {
464 continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800465 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700466 oldLength = output.length();
467 if (spaces < 0) {
468 spaces = 0;
469 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700470 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
471 sizesTotal(id),
472 elementsTotal(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700473 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800474 }
475
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700476 spaces = 6;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700477 output += "\nNow";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800478
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700479 log_id_for_each(id) {
480 if (!(logMask & (1 << id))) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800481 continue;
482 }
483
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700484 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800485 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700486 oldLength = output.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800487 if (spaces < 0) {
488 spaces = 0;
489 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700490 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
491 sizes(id), els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700492 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800493 }
494 spaces += spaces_total;
495 }
496
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700497 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700498
Mark Salyzyn758058f2015-08-21 16:44:30 -0700499 std::string name;
500
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700501 // Chattiest by application (UID)
502 log_id_for_each(id) {
503 if (!(logMask & (1 << id))) {
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700504 continue;
505 }
506
Mark Salyzyn758058f2015-08-21 16:44:30 -0700507 name = (uid == AID_ROOT)
508 ? "Chattiest UIDs in %s log buffer:"
509 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800510 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700511 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700512
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700513 if (enable) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800514 name = ((uid == AID_ROOT) && !pid)
515 ? "Chattiest PIDs:"
516 : "Logging for this PID:";
517 output += pidTable.format(*this, uid, pid, name);
518 name = "Chattiest TIDs";
519 if (pid) {
520 name += android::base::StringPrintf(" for PID %d", pid);
521 }
522 name += ":";
523 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700524 }
525
Mark Salyzyn344bff42015-04-13 14:24:45 -0700526 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800527 name = "Chattiest events log buffer TAGs";
528 if (pid) {
529 name += android::base::StringPrintf(" for PID %d", pid);
530 }
531 name += ":";
532 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700533 }
534
Mark Salyzyn083b0372015-12-04 10:59:45 -0800535 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800536 name = "Chattiest security log buffer TAGs";
537 if (pid) {
538 name += android::base::StringPrintf(" for PID %d", pid);
539 }
540 name += ":";
541 output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800542 }
543
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700544 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800545}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700546
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700547namespace android {
548
549uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700550 char buffer[512];
551 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
552 FILE *fp = fopen(buffer, "r");
553 if (fp) {
554 while (fgets(buffer, sizeof(buffer), fp)) {
555 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700556 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700557 fclose(fp);
558 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700559 }
560 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700561 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700562 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700563 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700564}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700565
566}
567
568uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700569 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700570}
571
572// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700573const char *LogStatistics::pidToName(pid_t pid) const {
574 // An inconvenient truth ... getName() can alter the object
575 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
576 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700577 if (!name) {
578 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700579 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700580 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700581}