blob: d4b48ef9b0b12a179b14a1aa0e8878afb2419aca [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 Salyzynddda2122015-10-02 09:22:52 -070056 if (fast<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 Salyzyn97c1c2b2015-03-10 13:51:35 -070074 mSizesTotal[log_id] += size;
75 ++mElementsTotal[log_id];
Mark Salyzyn720f6d12015-03-16 08:26:05 -070076
Mark Salyzynae4d9282014-10-15 08:49:39 -070077 if (log_id == LOG_ID_KERNEL) {
78 return;
79 }
80
Mark Salyzyn758058f2015-08-21 16:44:30 -070081 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070082 if (element->getUid() == AID_SYSTEM) {
83 pidSystemTable[log_id].add(element->getPid(), element);
84 }
Mark Salyzynae4d9282014-10-15 08:49:39 -070085
Mark Salyzyn720f6d12015-03-16 08:26:05 -070086 if (!enable) {
87 return;
88 }
89
Mark Salyzyn758058f2015-08-21 16:44:30 -070090 pidTable.add(element->getPid(), element);
91 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -070092
Mark Salyzyn758058f2015-08-21 16:44:30 -070093 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -070094 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -080095 if (log_id == LOG_ID_SECURITY) {
96 securityTagTable.add(tag, element);
97 } else {
98 tagTable.add(tag, element);
99 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700100 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800101}
102
Mark Salyzyn758058f2015-08-21 16:44:30 -0700103void LogStatistics::subtract(LogBufferElement *element) {
104 log_id_t log_id = element->getLogId();
105 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800106 mSizes[log_id] -= size;
107 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700108 if (element->getDropped()) {
109 --mDroppedElements[log_id];
110 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700111
Mark Salyzynae4d9282014-10-15 08:49:39 -0700112 if (log_id == LOG_ID_KERNEL) {
113 return;
114 }
115
Mark Salyzyn758058f2015-08-21 16:44:30 -0700116 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700117 if (element->getUid() == AID_SYSTEM) {
118 pidSystemTable[log_id].subtract(element->getPid(), element);
119 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800120
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700121 if (!enable) {
122 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800123 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700124
Mark Salyzyn758058f2015-08-21 16:44:30 -0700125 pidTable.subtract(element->getPid(), element);
126 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700127
Mark Salyzyn758058f2015-08-21 16:44:30 -0700128 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700129 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800130 if (log_id == LOG_ID_SECURITY) {
131 securityTagTable.subtract(tag, element);
132 } else {
133 tagTable.subtract(tag, element);
134 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700135 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800136}
137
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700138// Atomically set an entry to drop
139// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700140void LogStatistics::drop(LogBufferElement *element) {
141 log_id_t log_id = element->getLogId();
142 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700143 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700144 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700145
Mark Salyzyn758058f2015-08-21 16:44:30 -0700146 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700147 if (element->getUid() == AID_SYSTEM) {
148 pidSystemTable[log_id].drop(element->getPid(), element);
149 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700150
151 if (!enable) {
152 return;
153 }
154
Mark Salyzyn758058f2015-08-21 16:44:30 -0700155 pidTable.drop(element->getPid(), element);
156 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700157
158 uint32_t tag = element->getTag();
159 if (tag) {
160 if (log_id == LOG_ID_SECURITY) {
161 securityTagTable.drop(tag, element);
162 } else {
163 tagTable.drop(tag, element);
164 }
165 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700166}
167
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700168// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700169const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700170 // Local hard coded favourites
171 if (uid == AID_LOGD) {
172 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800173 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700174
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700175 // Android system
176 if (uid < AID_APP) {
177 // in bionic, thread safe as long as we copy the results
178 struct passwd *pwd = getpwuid(uid);
179 if (pwd) {
180 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700181 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800182 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700183
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700184 // Parse /data/system/packages.list
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700185 uid_t userId = uid % AID_USER;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700186 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700187 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
188 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
189 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700190 if (name) {
191 return name;
192 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700193
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700194 // Android application
195 if (uid >= AID_APP) {
196 struct passwd *pwd = getpwuid(uid);
197 if (pwd) {
198 return strdup(pwd->pw_name);
199 }
200 }
201
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700202 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700203 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700204 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700205
206 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700207 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700208
Mark Salyzyn758058f2015-08-21 16:44:30 -0700209 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700210 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700211 name = strdup(nameTmp);
212 } else if (fast<strcmp>(name, nameTmp)) {
213 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700214 name = NULL;
215 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700216 }
217 }
218 }
219 }
220
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700221 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700222 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800223}
224
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
226 bool isprune = worstUidEnabledForLogid(id);
227 return formatLine(android::base::StringPrintf(
228 name.c_str(), android_log_id_to_name(id)),
229 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700230 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700231 + formatLine(std::string("UID PACKAGE"),
232 std::string("BYTES"),
233 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800234}
235
Mark Salyzync723df82015-08-24 11:08:00 -0700236std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800237 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700238 std::string name = android::base::StringPrintf("%u", uid);
239 const char *nameTmp = stat.uidToName(uid);
240 if (nameTmp) {
241 name += android::base::StringPrintf(
242 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
243 "", nameTmp);
244 free(const_cast<char *>(nameTmp));
245 }
246
247 std::string size = android::base::StringPrintf("%zu", getSizes());
248
249 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700250 if (worstUidEnabledForLogid(id)) {
251 size_t totalDropped = 0;
252 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
253 it != stat.uidTable[id].end(); ++it) {
254 totalDropped += it->second.getDropped();
255 }
256 size_t sizes = stat.sizes(id);
257 size_t totalSize = stat.sizesTotal(id);
258 size_t totalElements = stat.elementsTotal(id);
259 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
260 / totalElements;
261 size_t entrySize = getSizes();
262 float virtualEntrySize = entrySize;
263 int realPermille = virtualEntrySize * 1000.0 / sizes;
264 size_t dropped = getDropped();
265 if (dropped) {
266 pruned = android::base::StringPrintf("%zu", dropped);
267 virtualEntrySize += (float)dropped * totalSize / totalElements;
268 }
269 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
270 int permille = (realPermille - virtualPermille) * 1000L
271 / (virtualPermille ?: 1);
272 if ((permille < -1) || (1 < permille)) {
273 std::string change;
274 const char *units = "%";
275 const char *prefix = (permille > 0) ? "+" : "";
276
277 if (permille > 999) {
278 permille = (permille + 1000) / 100; // Now tenths fold
279 units = "X";
280 prefix = "";
281 }
282 if ((-99 < permille) && (permille < 99)) {
283 change = android::base::StringPrintf("%s%d.%u%s",
284 prefix,
285 permille / 10,
286 ((permille < 0) ? (-permille % 10) : (permille % 10)),
287 units);
288 } else {
289 change = android::base::StringPrintf("%s%d%s",
290 prefix,
291 (permille + 5) / 10, units);
292 }
293 ssize_t spaces = EntryBaseConstants::pruned_len
294 - 2 - pruned.length() - change.length();
295 if ((spaces <= 0) && pruned.length()) {
296 spaces = 1;
297 }
Mark Salyzyn0adcc3e2016-07-15 07:40:33 -0700298 if ((spaces > 0) && (pruned.length() != 0)) {
Mark Salyzync723df82015-08-24 11:08:00 -0700299 change += android::base::StringPrintf("%*s", (int)spaces, "");
300 }
301 pruned = change + pruned;
302 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700303 }
304
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700305 std::string output = formatLine(name, size, pruned);
306
307 if (uid != AID_SYSTEM) {
308 return output;
309 }
310
311 static const size_t maximum_sorted_entries = 32;
312 std::unique_ptr<const PidEntry *[]> sorted
313 = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
314
315 if (!sorted.get()) {
316 return output;
317 }
318 std::string byPid;
319 size_t index;
320 bool hasDropped = false;
321 for (index = 0; index < maximum_sorted_entries; ++index) {
322 const PidEntry *entry = sorted[index];
323 if (!entry) {
324 break;
325 }
326 if (entry->getSizes() <= (getSizes() / 100)) {
327 break;
328 }
329 if (entry->getDropped()) {
330 hasDropped = true;
331 }
332 byPid += entry->format(stat, id);
333 }
334 if (index > 1) { // print this only if interesting
335 std::string ditto("\" ");
336 output += formatLine(std::string(" PID/UID COMMAND LINE"),
337 ditto, hasDropped ? ditto : std::string(""));
338 output += byPid;
339 }
340
341 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700342}
343
344std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
345 return formatLine(name,
346 std::string("Size"),
347 std::string("Pruned"))
348 + formatLine(std::string(" PID/UID COMMAND LINE"),
349 std::string("BYTES"),
350 std::string("NUM"));
351}
352
353std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
354 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800355 pid_t pid = getPid();
356 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700357 const char *nameTmp = getName();
358 if (nameTmp) {
359 name += android::base::StringPrintf(
360 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
361 "", nameTmp);
362 } else if ((nameTmp = stat.uidToName(uid))) {
363 name += android::base::StringPrintf(
364 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
365 "", nameTmp);
366 free(const_cast<char *>(nameTmp));
367 }
368
369 std::string size = android::base::StringPrintf("%zu",
370 getSizes());
371
372 std::string pruned = "";
373 size_t dropped = getDropped();
374 if (dropped) {
375 pruned = android::base::StringPrintf("%zu", dropped);
376 }
377
378 return formatLine(name, size, pruned);
379}
380
381std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
382 return formatLine(name,
383 std::string("Size"),
384 std::string("Pruned"))
385 + formatLine(std::string(" TID/UID COMM"),
386 std::string("BYTES"),
387 std::string("NUM"));
388}
389
390std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
391 uid_t uid = getUid();
392 std::string name = android::base::StringPrintf("%5u/%u",
Mark Salyzynee3b8382015-12-17 09:58:43 -0800393 getTid(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700394 const char *nameTmp = getName();
395 if (nameTmp) {
396 name += android::base::StringPrintf(
397 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
398 "", nameTmp);
399 } else if ((nameTmp = stat.uidToName(uid))) {
400 // if we do not have a PID name, lets punt to try UID name?
401 name += android::base::StringPrintf(
402 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
403 "", nameTmp);
404 free(const_cast<char *>(nameTmp));
405 // We tried, better to not have a name at all, we still
406 // have TID/UID by number to report in any case.
407 }
408
409 std::string size = android::base::StringPrintf("%zu",
410 getSizes());
411
412 std::string pruned = "";
413 size_t dropped = getDropped();
414 if (dropped) {
415 pruned = android::base::StringPrintf("%zu", dropped);
416 }
417
418 return formatLine(name, size, pruned);
419}
420
421std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
422 bool isprune = worstUidEnabledForLogid(id);
423 return formatLine(name,
424 std::string("Size"),
425 std::string(isprune ? "Prune" : ""))
426 + formatLine(std::string(" TAG/UID TAGNAME"),
427 std::string("BYTES"),
428 std::string(isprune ? "NUM" : ""));
429}
430
431std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
432 std::string name;
433 uid_t uid = getUid();
434 if (uid == (uid_t)-1) {
435 name = android::base::StringPrintf("%7u",
436 getKey());
437 } else {
438 name = android::base::StringPrintf("%7u/%u",
439 getKey(), uid);
440 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700441 size_t len = 0;
442 const char *nameTmp = getName(len);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700443 if (nameTmp) {
444 name += android::base::StringPrintf(
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700445 "%*s%.*s", (int)std::max(14 - name.length(), (size_t)1),
446 "", (int)len, nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700447 }
448
449 std::string size = android::base::StringPrintf("%zu",
450 getSizes());
451
452 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700453 size_t dropped = getDropped();
454 if (dropped) {
455 pruned = android::base::StringPrintf("%zu", dropped);
456 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700457
458 return formatLine(name, size, pruned);
459}
460
Mark Salyzynee3b8382015-12-17 09:58:43 -0800461std::string LogStatistics::format(uid_t uid, pid_t pid,
462 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700463 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800464
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700465 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800466
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700467 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700468 size_t oldLength;
469 short spaces = 1;
470
471 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700472 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700473 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700474 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700475 output += android::base::StringPrintf("%*s%s", spaces, "",
476 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700477 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800478 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700479 if (spaces < 0) spaces = 0;
480 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800481
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700482 static const char TotalStr[] = "\nTotal";
483 spaces = 10 - strlen(TotalStr);
484 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800485
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700486 size_t totalSize = 0;
487 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700488 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700489 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700490 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700491 if (spaces < 0) spaces = 0;
492 size_t szs = sizesTotal(id);
493 totalSize += szs;
494 size_t els = elementsTotal(id);
495 totalEls += els;
496 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700497 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800498 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700499 if (spaces < 0) spaces = 0;
500 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800501
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700502 static const char NowStr[] = "\nNow";
503 spaces = 10 - strlen(NowStr);
504 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800505
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700506 totalSize = 0;
507 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700508 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700509 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800510
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700511 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800512 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700513 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700514 if (spaces < 0) spaces = 0;
515 size_t szs = sizes(id);
516 totalSize += szs;
517 totalEls += els;
518 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700519 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800520 }
521 spaces += spaces_total;
522 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700523 if (spaces < 0) spaces = 0;
524 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
525
526 static const char OverheadStr[] = "\nOverhead";
527 spaces = 10 - strlen(OverheadStr);
528 output += OverheadStr;
529
530 totalSize = 0;
531 log_id_for_each(id) {
532 if (!(logMask & (1 << id))) continue;
533
534 size_t els = elements(id);
535 if (els) {
536 oldLength = output.length();
537 if (spaces < 0) spaces = 0;
538 // estimate the std::list overhead.
539 static const size_t overhead =
540 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
541 -sizeof(uint64_t)) +
542 sizeof(std::list<LogBufferElement*>);
543 size_t szs = sizes(id) + els * overhead;
544 totalSize += szs;
545 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
546 spaces -= output.length() - oldLength;
547 }
548 spaces += spaces_total;
549 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700550 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700551 if (spaces < 0) spaces = 0;
552 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800553
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700554 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700555
Mark Salyzyn758058f2015-08-21 16:44:30 -0700556 std::string name;
557
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700558 // Chattiest by application (UID)
559 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700560 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700561
Mark Salyzyn758058f2015-08-21 16:44:30 -0700562 name = (uid == AID_ROOT)
563 ? "Chattiest UIDs in %s log buffer:"
564 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800565 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700566 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700567
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700568 if (enable) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800569 name = ((uid == AID_ROOT) && !pid)
570 ? "Chattiest PIDs:"
571 : "Logging for this PID:";
572 output += pidTable.format(*this, uid, pid, name);
573 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700574 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800575 name += ":";
576 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700577 }
578
Mark Salyzyn344bff42015-04-13 14:24:45 -0700579 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800580 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700581 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800582 name += ":";
583 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700584 }
585
Mark Salyzyn083b0372015-12-04 10:59:45 -0800586 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800587 name = "Chattiest security log buffer TAGs";
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 += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800591 }
592
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700593 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800594}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700595
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700596namespace android {
597
598uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700599 char buffer[512];
600 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
601 FILE *fp = fopen(buffer, "r");
602 if (fp) {
603 while (fgets(buffer, sizeof(buffer), fp)) {
604 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700605 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700606 fclose(fp);
607 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700608 }
609 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700610 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700611 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700612 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700613}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700614
615}
616
617uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700618 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700619}
620
621// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700622const char *LogStatistics::pidToName(pid_t pid) const {
623 // An inconvenient truth ... getName() can alter the object
624 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
625 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700626 if (!name) {
627 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700628 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700629 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700630}