blob: 416edd8a127754945b3c483627fcb6e9a99a0e8c [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 Salyzynae4d9282014-10-15 08:49:39 -070078
Mark Salyzyn720f6d12015-03-16 08:26:05 -070079 if (!enable) {
80 return;
81 }
82
Mark Salyzyn758058f2015-08-21 16:44:30 -070083 pidTable.add(element->getPid(), element);
84 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -070085
Mark Salyzyn758058f2015-08-21 16:44:30 -070086 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -070087 if (tag) {
Mark Salyzyn758058f2015-08-21 16:44:30 -070088 tagTable.add(tag, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -070089 }
Mark Salyzyn34facab2014-02-06 14:48:50 -080090}
91
Mark Salyzyn758058f2015-08-21 16:44:30 -070092void LogStatistics::subtract(LogBufferElement *element) {
93 log_id_t log_id = element->getLogId();
94 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080095 mSizes[log_id] -= size;
96 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -070097 if (element->getDropped()) {
98 --mDroppedElements[log_id];
99 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700100
Mark Salyzynae4d9282014-10-15 08:49:39 -0700101 if (log_id == LOG_ID_KERNEL) {
102 return;
103 }
104
Mark Salyzyn758058f2015-08-21 16:44:30 -0700105 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800106
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700107 if (!enable) {
108 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800109 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700110
Mark Salyzyn758058f2015-08-21 16:44:30 -0700111 pidTable.subtract(element->getPid(), element);
112 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700113
Mark Salyzyn758058f2015-08-21 16:44:30 -0700114 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700115 if (tag) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700116 tagTable.subtract(tag, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700117 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800118}
119
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700120// Atomically set an entry to drop
121// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn758058f2015-08-21 16:44:30 -0700122void LogStatistics::drop(LogBufferElement *element) {
123 log_id_t log_id = element->getLogId();
124 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700125 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700126 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700127
Mark Salyzyn758058f2015-08-21 16:44:30 -0700128 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700129
130 if (!enable) {
131 return;
132 }
133
Mark Salyzyn758058f2015-08-21 16:44:30 -0700134 pidTable.drop(element->getPid(), element);
135 tidTable.drop(element->getTid(), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700136}
137
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700138// caller must own and free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700139const char *LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700140 // Local hard coded favourites
141 if (uid == AID_LOGD) {
142 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800143 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700144
145 // Android hard coded
146 const struct android_id_info *info = android_ids;
147
148 for (size_t i = 0; i < android_id_count; ++i) {
149 if (info->aid == uid) {
150 return strdup(info->name);
151 }
152 ++info;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800153 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700154
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700155 // Parse /data/system/packages.list
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700156 uid_t userId = uid % AID_USER;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700157 const char *name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700158 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
159 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
160 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700161 if (name) {
162 return name;
163 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700164
165 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn758058f2015-08-21 16:44:30 -0700166 for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700167 const PidEntry &entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700168
169 if (entry.getUid() == uid) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700170 const char *nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700171
Mark Salyzyn758058f2015-08-21 16:44:30 -0700172 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700173 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700174 name = strdup(nameTmp);
175 } else if (fast<strcmp>(name, nameTmp)) {
176 free(const_cast<char *>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700177 name = NULL;
178 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700179 }
180 }
181 }
182 }
183
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700184 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700185 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800186}
187
Mark Salyzyn758058f2015-08-21 16:44:30 -0700188std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
189 bool isprune = worstUidEnabledForLogid(id);
190 return formatLine(android::base::StringPrintf(
191 name.c_str(), android_log_id_to_name(id)),
192 std::string("Size"),
Mark Salyzync723df82015-08-24 11:08:00 -0700193 std::string(isprune ? "+/- Pruned" : ""))
Mark Salyzyn758058f2015-08-21 16:44:30 -0700194 + formatLine(std::string("UID PACKAGE"),
195 std::string("BYTES"),
196 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800197}
198
Mark Salyzync723df82015-08-24 11:08:00 -0700199std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700200 uid_t uid = getKey();
201 std::string name = android::base::StringPrintf("%u", uid);
202 const char *nameTmp = stat.uidToName(uid);
203 if (nameTmp) {
204 name += android::base::StringPrintf(
205 "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
206 "", nameTmp);
207 free(const_cast<char *>(nameTmp));
208 }
209
210 std::string size = android::base::StringPrintf("%zu", getSizes());
211
212 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700213 if (worstUidEnabledForLogid(id)) {
214 size_t totalDropped = 0;
215 for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
216 it != stat.uidTable[id].end(); ++it) {
217 totalDropped += it->second.getDropped();
218 }
219 size_t sizes = stat.sizes(id);
220 size_t totalSize = stat.sizesTotal(id);
221 size_t totalElements = stat.elementsTotal(id);
222 float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
223 / totalElements;
224 size_t entrySize = getSizes();
225 float virtualEntrySize = entrySize;
226 int realPermille = virtualEntrySize * 1000.0 / sizes;
227 size_t dropped = getDropped();
228 if (dropped) {
229 pruned = android::base::StringPrintf("%zu", dropped);
230 virtualEntrySize += (float)dropped * totalSize / totalElements;
231 }
232 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
233 int permille = (realPermille - virtualPermille) * 1000L
234 / (virtualPermille ?: 1);
235 if ((permille < -1) || (1 < permille)) {
236 std::string change;
237 const char *units = "%";
238 const char *prefix = (permille > 0) ? "+" : "";
239
240 if (permille > 999) {
241 permille = (permille + 1000) / 100; // Now tenths fold
242 units = "X";
243 prefix = "";
244 }
245 if ((-99 < permille) && (permille < 99)) {
246 change = android::base::StringPrintf("%s%d.%u%s",
247 prefix,
248 permille / 10,
249 ((permille < 0) ? (-permille % 10) : (permille % 10)),
250 units);
251 } else {
252 change = android::base::StringPrintf("%s%d%s",
253 prefix,
254 (permille + 5) / 10, units);
255 }
256 ssize_t spaces = EntryBaseConstants::pruned_len
257 - 2 - pruned.length() - change.length();
258 if ((spaces <= 0) && pruned.length()) {
259 spaces = 1;
260 }
261 if (spaces > 0) {
262 change += android::base::StringPrintf("%*s", (int)spaces, "");
263 }
264 pruned = change + pruned;
265 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700266 }
267
268 return formatLine(name, size, pruned);
269}
270
271std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
272 return formatLine(name,
273 std::string("Size"),
274 std::string("Pruned"))
275 + formatLine(std::string(" PID/UID COMMAND LINE"),
276 std::string("BYTES"),
277 std::string("NUM"));
278}
279
280std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
281 uid_t uid = getUid();
282 std::string name = android::base::StringPrintf("%5u/%u",
283 getKey(), uid);
284 const char *nameTmp = getName();
285 if (nameTmp) {
286 name += android::base::StringPrintf(
287 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
288 "", nameTmp);
289 } else if ((nameTmp = stat.uidToName(uid))) {
290 name += android::base::StringPrintf(
291 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
292 "", nameTmp);
293 free(const_cast<char *>(nameTmp));
294 }
295
296 std::string size = android::base::StringPrintf("%zu",
297 getSizes());
298
299 std::string pruned = "";
300 size_t dropped = getDropped();
301 if (dropped) {
302 pruned = android::base::StringPrintf("%zu", dropped);
303 }
304
305 return formatLine(name, size, pruned);
306}
307
308std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
309 return formatLine(name,
310 std::string("Size"),
311 std::string("Pruned"))
312 + formatLine(std::string(" TID/UID COMM"),
313 std::string("BYTES"),
314 std::string("NUM"));
315}
316
317std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
318 uid_t uid = getUid();
319 std::string name = android::base::StringPrintf("%5u/%u",
320 getKey(), uid);
321 const char *nameTmp = getName();
322 if (nameTmp) {
323 name += android::base::StringPrintf(
324 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
325 "", nameTmp);
326 } else if ((nameTmp = stat.uidToName(uid))) {
327 // if we do not have a PID name, lets punt to try UID name?
328 name += android::base::StringPrintf(
329 "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
330 "", nameTmp);
331 free(const_cast<char *>(nameTmp));
332 // We tried, better to not have a name at all, we still
333 // have TID/UID by number to report in any case.
334 }
335
336 std::string size = android::base::StringPrintf("%zu",
337 getSizes());
338
339 std::string pruned = "";
340 size_t dropped = getDropped();
341 if (dropped) {
342 pruned = android::base::StringPrintf("%zu", dropped);
343 }
344
345 return formatLine(name, size, pruned);
346}
347
348std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
349 bool isprune = worstUidEnabledForLogid(id);
350 return formatLine(name,
351 std::string("Size"),
352 std::string(isprune ? "Prune" : ""))
353 + formatLine(std::string(" TAG/UID TAGNAME"),
354 std::string("BYTES"),
355 std::string(isprune ? "NUM" : ""));
356}
357
358std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
359 std::string name;
360 uid_t uid = getUid();
361 if (uid == (uid_t)-1) {
362 name = android::base::StringPrintf("%7u",
363 getKey());
364 } else {
365 name = android::base::StringPrintf("%7u/%u",
366 getKey(), uid);
367 }
368 const char *nameTmp = getName();
369 if (nameTmp) {
370 name += android::base::StringPrintf(
371 "%*s%s", (int)std::max(14 - name.length(), (size_t)1),
372 "", nameTmp);
373 }
374
375 std::string size = android::base::StringPrintf("%zu",
376 getSizes());
377
378 std::string pruned = "";
379
380 return formatLine(name, size, pruned);
381}
382
383std::string LogStatistics::format(uid_t uid, unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700384 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800385
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700386 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800387
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700388 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700389 size_t oldLength;
390 short spaces = 1;
391
392 log_id_for_each(id) {
393 if (!(logMask & (1 << id))) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700394 continue;
395 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700396 oldLength = output.length();
Mark Salyzync8a576c2014-04-04 16:35:59 -0700397 if (spaces < 0) {
398 spaces = 0;
399 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700400 output += android::base::StringPrintf("%*s%s", spaces, "",
401 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700402 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800403 }
404
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700405 spaces = 4;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700406 output += "\nTotal";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800407
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700408 log_id_for_each(id) {
409 if (!(logMask & (1 << id))) {
410 continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800411 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700412 oldLength = output.length();
413 if (spaces < 0) {
414 spaces = 0;
415 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700416 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
417 sizesTotal(id),
418 elementsTotal(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700419 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800420 }
421
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700422 spaces = 6;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700423 output += "\nNow";
Mark Salyzyn34facab2014-02-06 14:48:50 -0800424
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700425 log_id_for_each(id) {
426 if (!(logMask & (1 << id))) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800427 continue;
428 }
429
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700430 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800431 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700432 oldLength = output.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800433 if (spaces < 0) {
434 spaces = 0;
435 }
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700436 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
437 sizes(id), els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700438 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800439 }
440 spaces += spaces_total;
441 }
442
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700443 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700444
Mark Salyzyn758058f2015-08-21 16:44:30 -0700445 std::string name;
446
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700447 // Chattiest by application (UID)
448 log_id_for_each(id) {
449 if (!(logMask & (1 << id))) {
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700450 continue;
451 }
452
Mark Salyzyn758058f2015-08-21 16:44:30 -0700453 name = (uid == AID_ROOT)
454 ? "Chattiest UIDs in %s log buffer:"
455 : "Logging for your UID in %s log buffer:";
456 output += uidTable[id].format(*this, uid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700457 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700458
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700459 if (enable) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700460 name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:";
461 output += pidTable.format(*this, uid, name);
462 name = "Chattiest TIDs:";
463 output += tidTable.format(*this, uid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700464 }
465
Mark Salyzyn344bff42015-04-13 14:24:45 -0700466 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700467 name = "Chattiest events log buffer TAGs:";
468 output += tagTable.format(*this, uid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700469 }
470
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700471 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800472}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700473
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700474namespace android {
475
476uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700477 char buffer[512];
478 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
479 FILE *fp = fopen(buffer, "r");
480 if (fp) {
481 while (fgets(buffer, sizeof(buffer), fp)) {
482 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700483 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700484 fclose(fp);
485 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700486 }
487 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700488 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700489 }
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700490 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700491}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700492
493}
494
495uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700496 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700497}
498
499// caller must free character string
Mark Salyzyn758058f2015-08-21 16:44:30 -0700500const char *LogStatistics::pidToName(pid_t pid) const {
501 // An inconvenient truth ... getName() can alter the object
502 pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
503 const char *name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700504 if (!name) {
505 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700506 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700507 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700508}