blob: 6e63015ac1862a1658a6f76a1539a7c4755c003a [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 Salyzyn32962912016-09-12 10:29:17 -070030size_t LogStatistics::SizesTotal;
31
Mark Salyzyn77187782015-05-12 15:21:31 -070032LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070033 log_id_for_each(id) {
34 mSizes[id] = 0;
35 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070036 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070037 mSizesTotal[id] = 0;
38 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080039 }
40}
41
Mark Salyzyn720f6d12015-03-16 08:26:05 -070042namespace android {
43
Mark Salyzyn32962912016-09-12 10:29:17 -070044size_t sizesTotal() { return LogStatistics::sizesTotal(); }
45
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070046// caller must own and free character string
Mark Salyzyn81b3eab2015-04-13 14:24:45 -070047char *pidToName(pid_t pid) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070048 char *retval = NULL;
Mark Salyzynae4d9282014-10-15 08:49:39 -070049 if (pid == 0) { // special case from auditd/klogd for kernel
50 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070051 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070052 char buffer[512];
53 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
54 int fd = open(buffer, O_RDONLY);
55 if (fd >= 0) {
56 ssize_t ret = read(fd, buffer, sizeof(buffer));
57 if (ret > 0) {
58 buffer[sizeof(buffer)-1] = '\0';
59 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080060 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070061 retval = strdup(buffer);
62 }
63 }
64 close(fd);
65 }
66 }
67 return retval;
68}
69
Mark Salyzyn720f6d12015-03-16 08:26:05 -070070}
71
Mark Salyzyn758058f2015-08-21 16:44:30 -070072void LogStatistics::add(LogBufferElement *element) {
73 log_id_t log_id = element->getLogId();
74 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080075 mSizes[log_id] += size;
76 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070077
Mark Salyzyna2c02222016-12-13 10:31:29 -080078 if (element->getDropped()) {
79 ++mDroppedElements[log_id];
80 } else {
81 // When caller adding a chatty entry, they will have already
82 // called add() and subtract() for each entry as they are
83 // evaluated and trimmed, thus recording size and number of
84 // elements, but we must recognize the manufactured dropped
85 // entry as not contributing to the lifetime totals.
86 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -070087 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -080088 ++mElementsTotal[log_id];
89 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -070090
Mark Salyzynae4d9282014-10-15 08:49:39 -070091 if (log_id == LOG_ID_KERNEL) {
92 return;
93 }
94
Mark Salyzyn758058f2015-08-21 16:44:30 -070095 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070096 if (element->getUid() == AID_SYSTEM) {
97 pidSystemTable[log_id].add(element->getPid(), element);
98 }
Mark Salyzynae4d9282014-10-15 08:49:39 -070099
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700100 if (!enable) {
101 return;
102 }
103
Mark Salyzyn758058f2015-08-21 16:44:30 -0700104 pidTable.add(element->getPid(), element);
105 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700106
Mark Salyzyn758058f2015-08-21 16:44:30 -0700107 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700108 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800109 if (log_id == LOG_ID_SECURITY) {
110 securityTagTable.add(tag, element);
111 } else {
112 tagTable.add(tag, element);
113 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700114 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800115}
116
Mark Salyzyn758058f2015-08-21 16:44:30 -0700117void LogStatistics::subtract(LogBufferElement *element) {
118 log_id_t log_id = element->getLogId();
119 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800120 mSizes[log_id] -= size;
121 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700122 if (element->getDropped()) {
123 --mDroppedElements[log_id];
124 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700125
Mark Salyzynae4d9282014-10-15 08:49:39 -0700126 if (log_id == LOG_ID_KERNEL) {
127 return;
128 }
129
Mark Salyzyn758058f2015-08-21 16:44:30 -0700130 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700131 if (element->getUid() == AID_SYSTEM) {
132 pidSystemTable[log_id].subtract(element->getPid(), element);
133 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800134
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700135 if (!enable) {
136 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800137 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700138
Mark Salyzyn758058f2015-08-21 16:44:30 -0700139 pidTable.subtract(element->getPid(), element);
140 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700141
Mark Salyzyn758058f2015-08-21 16:44:30 -0700142 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700143 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800144 if (log_id == LOG_ID_SECURITY) {
145 securityTagTable.subtract(tag, element);
146 } else {
147 tagTable.subtract(tag, element);
148 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700149 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800150}
151
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700152// Atomically set an entry to drop
153// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700154void LogStatistics::drop(LogBufferElement *element) {
155 log_id_t log_id = element->getLogId();
156 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700157 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700158 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700159
Mark Salyzyn758058f2015-08-21 16:44:30 -0700160 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700161 if (element->getUid() == AID_SYSTEM) {
162 pidSystemTable[log_id].drop(element->getPid(), element);
163 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700164
165 if (!enable) {
166 return;
167 }
168
Mark Salyzyn758058f2015-08-21 16:44:30 -0700169 pidTable.drop(element->getPid(), element);
170 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700171
172 uint32_t tag = element->getTag();
173 if (tag) {
174 if (log_id == LOG_ID_SECURITY) {
175 securityTagTable.drop(tag, element);
176 } else {
177 tagTable.drop(tag, element);
178 }
179 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700180}
181
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700182// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700183const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700184 // Local hard coded favourites
185 if (uid == AID_LOGD) {
186 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800187 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700188
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700189 // Android system
190 if (uid < AID_APP) {
191 // in bionic, thread safe as long as we copy the results
192 struct passwd *pwd = getpwuid(uid);
193 if (pwd) {
194 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700195 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800196 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700197
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700198 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700199 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700200 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700201 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
202 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
203 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700204 if (name) {
205 return name;
206 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700207
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700208 // Android application
209 if (uid >= AID_APP) {
210 struct passwd *pwd = getpwuid(uid);
211 if (pwd) {
212 return strdup(pwd->pw_name);
213 }
214 }
215
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700216 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700217 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700218 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700219
220 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700221 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700222
Mark Salyzyn758058f2015-08-21 16:44:30 -0700223 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700224 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800226 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700227 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700228 name = NULL;
229 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700230 }
231 }
232 }
233 }
234
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700235 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700236 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800237}
238
Mark Salyzyn758058f2015-08-21 16:44:30 -0700239std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
240 bool isprune = worstUidEnabledForLogid(id);
241 return formatLine(android::base::StringPrintf(
242 name.c_str(), android_log_id_to_name(id)),
243 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700244 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700245 + formatLine(std::string("UID PACKAGE"),
246 std::string("BYTES"),
247 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800248}
249
Mark Salyzync723df82015-08-24 11:08:00 -0700250std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800251 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700252 std::string name = android::base::StringPrintf("%u", uid);
253 const char *nameTmp = stat.uidToName(uid);
254 if (nameTmp) {
255 name += android::base::StringPrintf(
256 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
257 "", nameTmp);
258 free(const_cast<char *>(nameTmp));
259 }
260
261 std::string size = android::base::StringPrintf("%zu", getSizes());
262
263 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700264 if (worstUidEnabledForLogid(id)) {
265 size_t totalDropped = 0;
266 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
267 it != stat.uidTable[id].end(); ++it) {
268 totalDropped += it->second.getDropped();
269 }
270 size_t sizes = stat.sizes(id);
271 size_t totalSize = stat.sizesTotal(id);
272 size_t totalElements = stat.elementsTotal(id);
273 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
274 / totalElements;
275 size_t entrySize = getSizes();
276 float virtualEntrySize = entrySize;
277 int realPermille = virtualEntrySize * 1000.0 / sizes;
278 size_t dropped = getDropped();
279 if (dropped) {
280 pruned = android::base::StringPrintf("%zu", dropped);
281 virtualEntrySize += (float)dropped * totalSize / totalElements;
282 }
283 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
284 int permille = (realPermille - virtualPermille) * 1000L
285 / (virtualPermille ?: 1);
286 if ((permille < -1) || (1 < permille)) {
287 std::string change;
288 const char *units = "%";
289 const char *prefix = (permille > 0) ? "+" : "";
290
291 if (permille > 999) {
292 permille = (permille + 1000) / 100; // Now tenths fold
293 units = "X";
294 prefix = "";
295 }
296 if ((-99 < permille) && (permille < 99)) {
297 change = android::base::StringPrintf("%s%d.%u%s",
298 prefix,
299 permille / 10,
300 ((permille < 0) ? (-permille % 10) : (permille % 10)),
301 units);
302 } else {
303 change = android::base::StringPrintf("%s%d%s",
304 prefix,
305 (permille + 5) / 10, units);
306 }
307 ssize_t spaces = EntryBaseConstants::pruned_len
308 - 2 - pruned.length() - change.length();
309 if ((spaces <= 0) && pruned.length()) {
310 spaces = 1;
311 }
Mark Salyzyn0adcc3e2016-07-15 07:40:33 -0700312 if ((spaces > 0) && (pruned.length() != 0)) {
Mark Salyzync723df82015-08-24 11:08:00 -0700313 change += android::base::StringPrintf("%*s", (int)spaces, "");
314 }
315 pruned = change + pruned;
316 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700317 }
318
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700319 std::string output = formatLine(name, size, pruned);
320
321 if (uid != AID_SYSTEM) {
322 return output;
323 }
324
325 static const size_t maximum_sorted_entries = 32;
326 std::unique_ptr<const PidEntry *[]> sorted
327 = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
328
329 if (!sorted.get()) {
330 return output;
331 }
332 std::string byPid;
333 size_t index;
334 bool hasDropped = false;
335 for (index = 0; index < maximum_sorted_entries; ++index) {
336 const PidEntry *entry = sorted[index];
337 if (!entry) {
338 break;
339 }
340 if (entry->getSizes() <= (getSizes() / 100)) {
341 break;
342 }
343 if (entry->getDropped()) {
344 hasDropped = true;
345 }
346 byPid += entry->format(stat, id);
347 }
348 if (index > 1) { // print this only if interesting
349 std::string ditto("\" ");
350 output += formatLine(std::string(" PID/UID COMMAND LINE"),
351 ditto, hasDropped ? ditto : std::string(""));
352 output += byPid;
353 }
354
355 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700356}
357
358std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
359 return formatLine(name,
360 std::string("Size"),
361 std::string("Pruned"))
362 + formatLine(std::string(" PID/UID COMMAND LINE"),
363 std::string("BYTES"),
364 std::string("NUM"));
365}
366
367std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
368 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800369 pid_t pid = getPid();
370 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700371 const char *nameTmp = getName();
372 if (nameTmp) {
373 name += android::base::StringPrintf(
374 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
375 "", nameTmp);
376 } else if ((nameTmp = stat.uidToName(uid))) {
377 name += android::base::StringPrintf(
378 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
379 "", nameTmp);
380 free(const_cast<char *>(nameTmp));
381 }
382
383 std::string size = android::base::StringPrintf("%zu",
384 getSizes());
385
386 std::string pruned = "";
387 size_t dropped = getDropped();
388 if (dropped) {
389 pruned = android::base::StringPrintf("%zu", dropped);
390 }
391
392 return formatLine(name, size, pruned);
393}
394
395std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
396 return formatLine(name,
397 std::string("Size"),
398 std::string("Pruned"))
399 + formatLine(std::string(" TID/UID COMM"),
400 std::string("BYTES"),
401 std::string("NUM"));
402}
403
404std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
405 uid_t uid = getUid();
406 std::string name = android::base::StringPrintf("%5u/%u",
Mark Salyzynee3b8382015-12-17 09:58:43 -0800407 getTid(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700408 const char *nameTmp = getName();
409 if (nameTmp) {
410 name += android::base::StringPrintf(
411 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
412 "", nameTmp);
413 } else if ((nameTmp = stat.uidToName(uid))) {
414 // if we do not have a PID name, lets punt to try UID name?
415 name += android::base::StringPrintf(
416 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
417 "", nameTmp);
418 free(const_cast<char *>(nameTmp));
419 // We tried, better to not have a name at all, we still
420 // have TID/UID by number to report in any case.
421 }
422
423 std::string size = android::base::StringPrintf("%zu",
424 getSizes());
425
426 std::string pruned = "";
427 size_t dropped = getDropped();
428 if (dropped) {
429 pruned = android::base::StringPrintf("%zu", dropped);
430 }
431
432 return formatLine(name, size, pruned);
433}
434
435std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
436 bool isprune = worstUidEnabledForLogid(id);
437 return formatLine(name,
438 std::string("Size"),
439 std::string(isprune ? "Prune" : ""))
440 + formatLine(std::string(" TAG/UID TAGNAME"),
441 std::string("BYTES"),
442 std::string(isprune ? "NUM" : ""));
443}
444
445std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
446 std::string name;
447 uid_t uid = getUid();
448 if (uid == (uid_t)-1) {
449 name = android::base::StringPrintf("%7u",
450 getKey());
451 } else {
452 name = android::base::StringPrintf("%7u/%u",
453 getKey(), uid);
454 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700455 size_t len = 0;
456 const char *nameTmp = getName(len);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700457 if (nameTmp) {
458 name += android::base::StringPrintf(
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700459 "%*s%.*s", (int)std::max(14 - name.length(), (size_t)1),
460 "", (int)len, nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700461 }
462
463 std::string size = android::base::StringPrintf("%zu",
464 getSizes());
465
466 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700467 size_t dropped = getDropped();
468 if (dropped) {
469 pruned = android::base::StringPrintf("%zu", dropped);
470 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700471
472 return formatLine(name, size, pruned);
473}
474
Mark Salyzynee3b8382015-12-17 09:58:43 -0800475std::string LogStatistics::format(uid_t uid, pid_t pid,
476 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700477 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800478
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700479 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800480
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700481 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700482 size_t oldLength;
483 short spaces = 1;
484
485 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700486 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700487 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700488 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700489 output += android::base::StringPrintf("%*s%s", spaces, "",
490 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700491 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800492 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700493 if (spaces < 0) spaces = 0;
494 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800495
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700496 static const char TotalStr[] = "\nTotal";
497 spaces = 10 - strlen(TotalStr);
498 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800499
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700500 size_t totalSize = 0;
501 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700502 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700503 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700504 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700505 if (spaces < 0) spaces = 0;
506 size_t szs = sizesTotal(id);
507 totalSize += szs;
508 size_t els = elementsTotal(id);
509 totalEls += els;
510 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700511 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800512 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700513 if (spaces < 0) spaces = 0;
514 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800515
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700516 static const char NowStr[] = "\nNow";
517 spaces = 10 - strlen(NowStr);
518 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800519
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700520 totalSize = 0;
521 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700522 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700523 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800524
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700525 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800526 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700527 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700528 if (spaces < 0) spaces = 0;
529 size_t szs = sizes(id);
530 totalSize += szs;
531 totalEls += els;
532 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700533 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800534 }
535 spaces += spaces_total;
536 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700537 if (spaces < 0) spaces = 0;
538 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
539
540 static const char OverheadStr[] = "\nOverhead";
541 spaces = 10 - strlen(OverheadStr);
542 output += OverheadStr;
543
544 totalSize = 0;
545 log_id_for_each(id) {
546 if (!(logMask & (1 << id))) continue;
547
548 size_t els = elements(id);
549 if (els) {
550 oldLength = output.length();
551 if (spaces < 0) spaces = 0;
552 // estimate the std::list overhead.
553 static const size_t overhead =
554 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
555 -sizeof(uint64_t)) +
556 sizeof(std::list<LogBufferElement*>);
557 size_t szs = sizes(id) + els * overhead;
558 totalSize += szs;
559 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
560 spaces -= output.length() - oldLength;
561 }
562 spaces += spaces_total;
563 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700564 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700565 if (spaces < 0) spaces = 0;
566 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800567
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700568 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700569
Mark Salyzyn758058f2015-08-21 16:44:30 -0700570 std::string name;
571
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700572 // Chattiest by application (UID)
573 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700574 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700575
Mark Salyzyn758058f2015-08-21 16:44:30 -0700576 name = (uid == AID_ROOT)
577 ? "Chattiest UIDs in %s log buffer:"
578 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800579 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700580 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700581
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700582 if (enable) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800583 name = ((uid == AID_ROOT) && !pid)
584 ? "Chattiest PIDs:"
585 : "Logging for this PID:";
586 output += pidTable.format(*this, uid, pid, name);
587 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700588 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800589 name += ":";
590 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700591 }
592
Mark Salyzyn344bff42015-04-13 14:24:45 -0700593 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800594 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700595 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800596 name += ":";
597 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700598 }
599
Mark Salyzyn083b0372015-12-04 10:59:45 -0800600 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800601 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700602 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800603 name += ":";
604 output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800605 }
606
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700607 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800608}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700609
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700610namespace android {
611
612uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700613 char buffer[512];
614 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
615 FILE *fp = fopen(buffer, "r");
616 if (fp) {
617 while (fgets(buffer, sizeof(buffer), fp)) {
618 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700619 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700620 fclose(fp);
621 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700622 }
623 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700624 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700625 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700626 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700627}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700628
629}
630
631uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700632 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700633}
634
635// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700636const char *LogStatistics::pidToName(pid_t pid) const {
637 // An inconvenient truth ... getName() can alter the object
638 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
639 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700640 if (!name) {
641 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700642 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700643 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700644}