blob: af59ddc25a46a833743b33b1097d4be56232b0a2 [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 Salyzync4e48232017-05-04 13:54:46 -070017#include <ctype.h>
Mark Salyzyn9a038632014-04-07 07:05:40 -070018#include <fcntl.h>
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070019#include <inttypes.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070020#include <pwd.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070021#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070022#include <string.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070023#include <sys/types.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070024#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080025
Mark Salyzyn9af33ee2016-10-05 12:34:37 -070026#include <list>
27
Mark Salyzyn03bb7592017-04-14 09:46:57 -070028#include <private/android_logger.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080029
30#include "LogStatistics.h"
31
Mark Salyzyn03bb7592017-04-14 09:46:57 -070032static const uint64_t hourSec = 60 * 60;
33static const uint64_t monthSec = 31 * 24 * hourSec;
34
Mark Salyzyn32962912016-09-12 10:29:17 -070035size_t LogStatistics::SizesTotal;
36
Mark Salyzyn77187782015-05-12 15:21:31 -070037LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn03bb7592017-04-14 09:46:57 -070038 log_time now(CLOCK_REALTIME);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070039 log_id_for_each(id) {
40 mSizes[id] = 0;
41 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070042 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070043 mSizesTotal[id] = 0;
44 mElementsTotal[id] = 0;
Mark Salyzyn03bb7592017-04-14 09:46:57 -070045 mOldest[id] = now;
46 mNewest[id] = now;
47 mNewestDropped[id] = now;
Mark Salyzyn34facab2014-02-06 14:48:50 -080048 }
49}
50
Mark Salyzyn720f6d12015-03-16 08:26:05 -070051namespace android {
52
Mark Salyzyn501c3732017-03-10 14:31:54 -080053size_t sizesTotal() {
54 return LogStatistics::sizesTotal();
55}
Mark Salyzyn32962912016-09-12 10:29:17 -070056
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070057// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080058char* pidToName(pid_t pid) {
59 char* retval = NULL;
60 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070061 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070062 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070063 char buffer[512];
64 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
65 int fd = open(buffer, O_RDONLY);
66 if (fd >= 0) {
67 ssize_t ret = read(fd, buffer, sizeof(buffer));
68 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080069 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070070 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080071 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070072 retval = strdup(buffer);
73 }
74 }
75 close(fd);
76 }
77 }
78 return retval;
79}
Mark Salyzyn720f6d12015-03-16 08:26:05 -070080}
81
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070082void LogStatistics::addTotal(LogBufferElement* element) {
83 if (element->getDropped()) return;
84
85 log_id_t log_id = element->getLogId();
86 unsigned short size = element->getMsgLen();
87 mSizesTotal[log_id] += size;
88 SizesTotal += size;
89 ++mElementsTotal[log_id];
90}
91
Mark Salyzyn501c3732017-03-10 14:31:54 -080092void LogStatistics::add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -070093 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 Salyzyn97c1c2b2015-03-10 13:51:35 -070097
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070098 // When caller adding a chatty entry, they will have already
99 // called add() and subtract() for each entry as they are
100 // evaluated and trimmed, thus recording size and number of
101 // elements, but we must recognize the manufactured dropped
102 // entry as not contributing to the lifetime totals.
Mark Salyzyna2c02222016-12-13 10:31:29 -0800103 if (element->getDropped()) {
104 ++mDroppedElements[log_id];
105 } else {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800106 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -0700107 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -0800108 ++mElementsTotal[log_id];
109 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700110
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700111 log_time stamp(element->getRealTime());
112 if (mNewest[log_id] < stamp) {
113 // A major time update invalidates the statistics :-(
114 log_time diff = stamp - mNewest[log_id];
115 mNewest[log_id] = stamp;
116
117 if (diff.tv_sec > hourSec) {
118 // approximate Do-Your-Best fixup
119 diff += mOldest[log_id];
120 if ((diff > stamp) && ((diff - stamp).tv_sec < hourSec)) {
121 diff = stamp;
122 }
123 if (diff <= stamp) {
124 mOldest[log_id] = diff;
125 if (mNewestDropped[log_id] < diff) {
126 mNewestDropped[log_id] = diff;
127 }
128 }
129 }
130 }
131
Mark Salyzynae4d9282014-10-15 08:49:39 -0700132 if (log_id == LOG_ID_KERNEL) {
133 return;
134 }
135
Mark Salyzyn758058f2015-08-21 16:44:30 -0700136 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700137 if (element->getUid() == AID_SYSTEM) {
138 pidSystemTable[log_id].add(element->getPid(), element);
139 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700140
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700141 if (!enable) {
142 return;
143 }
144
Mark Salyzyn758058f2015-08-21 16:44:30 -0700145 pidTable.add(element->getPid(), element);
146 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700147
Mark Salyzyn758058f2015-08-21 16:44:30 -0700148 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700149 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800150 if (log_id == LOG_ID_SECURITY) {
151 securityTagTable.add(tag, element);
152 } else {
153 tagTable.add(tag, element);
154 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700155 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700156
157 if (!element->getDropped()) {
158 tagNameTable.add(TagNameKey(element), element);
159 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800160}
161
Mark Salyzyn501c3732017-03-10 14:31:54 -0800162void LogStatistics::subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700163 log_id_t log_id = element->getLogId();
164 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800165 mSizes[log_id] -= size;
166 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700167 if (element->getDropped()) {
168 --mDroppedElements[log_id];
169 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700170
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700171 if (mOldest[log_id] < element->getRealTime()) {
172 mOldest[log_id] = element->getRealTime();
173 }
174
Mark Salyzynae4d9282014-10-15 08:49:39 -0700175 if (log_id == LOG_ID_KERNEL) {
176 return;
177 }
178
Mark Salyzyn758058f2015-08-21 16:44:30 -0700179 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700180 if (element->getUid() == AID_SYSTEM) {
181 pidSystemTable[log_id].subtract(element->getPid(), element);
182 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800183
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700184 if (!enable) {
185 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800186 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700187
Mark Salyzyn758058f2015-08-21 16:44:30 -0700188 pidTable.subtract(element->getPid(), element);
189 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700190
Mark Salyzyn758058f2015-08-21 16:44:30 -0700191 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700192 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800193 if (log_id == LOG_ID_SECURITY) {
194 securityTagTable.subtract(tag, element);
195 } else {
196 tagTable.subtract(tag, element);
197 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700198 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700199
200 if (!element->getDropped()) {
201 tagNameTable.subtract(TagNameKey(element), element);
202 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800203}
204
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700205// Atomically set an entry to drop
206// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800207void LogStatistics::drop(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700208 log_id_t log_id = element->getLogId();
209 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700210 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700211 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700212
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700213 if (mNewestDropped[log_id] < element->getRealTime()) {
214 mNewestDropped[log_id] = element->getRealTime();
215 }
216
Mark Salyzyn758058f2015-08-21 16:44:30 -0700217 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700218 if (element->getUid() == AID_SYSTEM) {
219 pidSystemTable[log_id].drop(element->getPid(), element);
220 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700221
222 if (!enable) {
223 return;
224 }
225
Mark Salyzyn758058f2015-08-21 16:44:30 -0700226 pidTable.drop(element->getPid(), element);
227 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700228
229 uint32_t tag = element->getTag();
230 if (tag) {
231 if (log_id == LOG_ID_SECURITY) {
232 securityTagTable.drop(tag, element);
233 } else {
234 tagTable.drop(tag, element);
235 }
236 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700237
238 tagNameTable.subtract(TagNameKey(element), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700239}
240
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700241// caller must own and free character string
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700242// Requires parent LogBuffer::wrlock() to be held
Mark Salyzyn501c3732017-03-10 14:31:54 -0800243const char* LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700244 // Local hard coded favourites
245 if (uid == AID_LOGD) {
246 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800247 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700248
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700249 // Android system
250 if (uid < AID_APP) {
251 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800252 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700253 if (pwd) {
254 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700255 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800256 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700257
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700258 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700259 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800260 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700261 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
262 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
263 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700264 if (name) {
265 return name;
266 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700267
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700268 // Android application
269 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800270 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700271 if (pwd) {
272 return strdup(pwd->pw_name);
273 }
274 }
275
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700276 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800277 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
278 ++it) {
279 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700280
281 if (entry.getUid() == uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800282 const char* nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700283
Mark Salyzyn758058f2015-08-21 16:44:30 -0700284 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700285 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700286 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800287 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800288 free(const_cast<char*>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700289 name = NULL;
290 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700291 }
292 }
293 }
294 }
295
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700296 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700297 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800298}
299
Mark Salyzyn501c3732017-03-10 14:31:54 -0800300std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700301 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800302 return formatLine(android::base::StringPrintf(name.c_str(),
303 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700304 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800305 std::string(isprune ? "+/- Pruned" : "")) +
306 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700307 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800308}
309
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700310// Helper to truncate name, if too long, and add name dressings
311static void formatTmp(const LogStatistics& stat, const char* nameTmp, uid_t uid,
312 std::string& name, std::string& size, size_t nameLen) {
313 const char* allocNameTmp = nullptr;
314 if (!nameTmp) nameTmp = allocNameTmp = stat.uidToName(uid);
315 if (nameTmp) {
316 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
317 size_t len = EntryBaseConstants::total_len -
318 EntryBaseConstants::pruned_len - size.length() -
319 name.length() - lenSpace - 2;
320 size_t lenNameTmp = strlen(nameTmp);
321 while ((len < lenNameTmp) && (lenSpace > 1)) {
322 ++len;
323 --lenSpace;
324 }
325 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
326 if (len < lenNameTmp) {
327 name += "...";
328 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
329 }
330 name += nameTmp;
331 free(const_cast<char*>(allocNameTmp));
332 }
333}
334
Mark Salyzyn501c3732017-03-10 14:31:54 -0800335std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800336 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700337 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700338 std::string size = android::base::StringPrintf("%zu", getSizes());
339
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700340 formatTmp(stat, nullptr, uid, name, size, 6);
341
Mark Salyzyn758058f2015-08-21 16:44:30 -0700342 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700343 if (worstUidEnabledForLogid(id)) {
344 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800345 for (LogStatistics::uidTable_t::const_iterator it =
346 stat.uidTable[id].begin();
347 it != stat.uidTable[id].end(); ++it) {
Mark Salyzync723df82015-08-24 11:08:00 -0700348 totalDropped += it->second.getDropped();
349 }
350 size_t sizes = stat.sizes(id);
351 size_t totalSize = stat.sizesTotal(id);
352 size_t totalElements = stat.elementsTotal(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800353 float totalVirtualSize =
354 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700355 size_t entrySize = getSizes();
356 float virtualEntrySize = entrySize;
357 int realPermille = virtualEntrySize * 1000.0 / sizes;
358 size_t dropped = getDropped();
359 if (dropped) {
360 pruned = android::base::StringPrintf("%zu", dropped);
361 virtualEntrySize += (float)dropped * totalSize / totalElements;
362 }
363 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800364 int permille =
365 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700366 if ((permille < -1) || (1 < permille)) {
367 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800368 const char* units = "%";
369 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700370
371 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800372 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700373 units = "X";
374 prefix = "";
375 }
376 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800377 change = android::base::StringPrintf(
378 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700379 ((permille < 0) ? (-permille % 10) : (permille % 10)),
380 units);
381 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800382 change = android::base::StringPrintf(
383 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700384 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800385 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
386 pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700387 if ((spaces <= 0) && pruned.length()) {
388 spaces = 1;
389 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000390 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700391 change += android::base::StringPrintf("%*s", (int)spaces, "");
392 }
393 pruned = change + pruned;
394 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700395 }
396
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700397 std::string output = formatLine(name, size, pruned);
398
399 if (uid != AID_SYSTEM) {
400 return output;
401 }
402
403 static const size_t maximum_sorted_entries = 32;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800404 std::unique_ptr<const PidEntry* []> sorted =
405 stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700406
407 if (!sorted.get()) {
408 return output;
409 }
410 std::string byPid;
411 size_t index;
412 bool hasDropped = false;
413 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800414 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700415 if (!entry) {
416 break;
417 }
418 if (entry->getSizes() <= (getSizes() / 100)) {
419 break;
420 }
421 if (entry->getDropped()) {
422 hasDropped = true;
423 }
424 byPid += entry->format(stat, id);
425 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800426 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700427 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800428 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
429 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700430 output += byPid;
431 }
432
433 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700434}
435
Mark Salyzyn501c3732017-03-10 14:31:54 -0800436std::string PidEntry::formatHeader(const std::string& name,
437 log_id_t /* id */) const {
438 return formatLine(name, std::string("Size"), std::string("Pruned")) +
439 formatLine(std::string(" PID/UID COMMAND LINE"),
440 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700441}
442
Mark Salyzyn501c3732017-03-10 14:31:54 -0800443std::string PidEntry::format(const LogStatistics& stat,
444 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700445 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800446 pid_t pid = getPid();
447 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800448 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700449
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700450 formatTmp(stat, getName(), uid, name, size, 12);
451
Mark Salyzyn758058f2015-08-21 16:44:30 -0700452 std::string pruned = "";
453 size_t dropped = getDropped();
454 if (dropped) {
455 pruned = android::base::StringPrintf("%zu", dropped);
456 }
457
458 return formatLine(name, size, pruned);
459}
460
Mark Salyzyn501c3732017-03-10 14:31:54 -0800461std::string TidEntry::formatHeader(const std::string& name,
462 log_id_t /* id */) const {
463 return formatLine(name, std::string("Size"), std::string("Pruned")) +
464 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700465 std::string("NUM"));
466}
467
Mark Salyzyn501c3732017-03-10 14:31:54 -0800468std::string TidEntry::format(const LogStatistics& stat,
469 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700470 uid_t uid = getUid();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800471 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800472 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700473
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700474 formatTmp(stat, getName(), uid, name, size, 12);
475
Mark Salyzyn758058f2015-08-21 16:44:30 -0700476 std::string pruned = "";
477 size_t dropped = getDropped();
478 if (dropped) {
479 pruned = android::base::StringPrintf("%zu", dropped);
480 }
481
482 return formatLine(name, size, pruned);
483}
484
Mark Salyzyn501c3732017-03-10 14:31:54 -0800485std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700486 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800487 return formatLine(name, std::string("Size"),
488 std::string(isprune ? "Prune" : "")) +
489 formatLine(std::string(" TAG/UID TAGNAME"),
490 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700491}
492
Mark Salyzyn501c3732017-03-10 14:31:54 -0800493std::string TagEntry::format(const LogStatistics& /* stat */,
494 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700495 std::string name;
496 uid_t uid = getUid();
497 if (uid == (uid_t)-1) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800498 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700499 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800500 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700501 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800502 const char* nameTmp = getName();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700503 if (nameTmp) {
504 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800505 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700506 }
507
Mark Salyzyn501c3732017-03-10 14:31:54 -0800508 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700509
510 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700511 size_t dropped = getDropped();
512 if (dropped) {
513 pruned = android::base::StringPrintf("%zu", dropped);
514 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700515
516 return formatLine(name, size, pruned);
517}
518
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700519std::string TagNameEntry::formatHeader(const std::string& name,
520 log_id_t /* id */) const {
521 return formatLine(name, std::string("Size"), std::string("")) +
522 formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
523 std::string("BYTES"), std::string(""));
524}
525
526std::string TagNameEntry::format(const LogStatistics& /* stat */,
527 log_id_t /* id */) const {
528 std::string name;
529 pid_t tid = getTid();
530 pid_t pid = getPid();
531 std::string pidstr;
532 if (pid != (pid_t)-1) {
533 pidstr = android::base::StringPrintf("%u", pid);
534 if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr;
535 }
536 int len = 9 - pidstr.length();
537 if (len < 0) len = 0;
538 if ((tid == (pid_t)-1) || (tid == pid)) {
539 name = android::base::StringPrintf("%*s", len, "");
540 } else {
541 name = android::base::StringPrintf("%*u", len, tid);
542 }
543 name += pidstr;
544 uid_t uid = getUid();
545 if (uid != (uid_t)-1) {
546 name += android::base::StringPrintf("/%u", uid);
547 }
548
549 std::string size = android::base::StringPrintf("%zu", getSizes());
550
551 const char* nameTmp = getName();
552 if (nameTmp) {
553 size_t lenSpace = std::max(16 - name.length(), (size_t)1);
554 size_t len = EntryBaseConstants::total_len -
555 EntryBaseConstants::pruned_len - size.length() -
556 name.length() - lenSpace - 2;
557 size_t lenNameTmp = strlen(nameTmp);
558 while ((len < lenNameTmp) && (lenSpace > 1)) {
559 ++len;
560 --lenSpace;
561 }
562 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
563 if (len < lenNameTmp) {
564 name += "...";
565 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
566 }
567 name += nameTmp;
568 }
569
570 std::string pruned = "";
571
572 return formatLine(name, size, pruned);
573}
574
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700575static std::string formatMsec(uint64_t val) {
576 static const unsigned subsecDigits = 3;
577 static const uint64_t sec = MS_PER_SEC;
578
579 static const uint64_t minute = 60 * sec;
580 static const uint64_t hour = 60 * minute;
581 static const uint64_t day = 24 * hour;
582
583 std::string output;
584 if (val < sec) return output;
585
586 if (val >= day) {
587 output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
588 val = (val % day) + day;
589 }
590 if (val >= minute) {
591 if (val >= hour) {
592 output += android::base::StringPrintf("%" PRIu64 ":",
593 (val / hour) % (day / hour));
594 }
595 output += android::base::StringPrintf(
596 (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
597 (val / minute) % (hour / minute));
598 }
599 output +=
600 android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
601 (val / sec) % (minute / sec));
602 val %= sec;
603 unsigned digits = subsecDigits;
604 while (digits && ((val % 10) == 0)) {
605 val /= 10;
606 --digits;
607 }
608 if (digits) {
609 output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
610 }
611 return output;
612}
613
Mark Salyzynee3b8382015-12-17 09:58:43 -0800614std::string LogStatistics::format(uid_t uid, pid_t pid,
615 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700616 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800617
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700618 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800619
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700620 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700621 size_t oldLength;
622 short spaces = 1;
623
624 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700625 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700626 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700627 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700628 output += android::base::StringPrintf("%*s%s", spaces, "",
629 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700630 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800631 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700632 if (spaces < 0) spaces = 0;
633 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800634
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700635 static const char TotalStr[] = "\nTotal";
636 spaces = 10 - strlen(TotalStr);
637 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800638
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700639 size_t totalSize = 0;
640 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700641 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700642 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700643 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700644 if (spaces < 0) spaces = 0;
645 size_t szs = sizesTotal(id);
646 totalSize += szs;
647 size_t els = elementsTotal(id);
648 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800649 output +=
650 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700651 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800652 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700653 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800654 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
655 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800656
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700657 static const char NowStr[] = "\nNow";
658 spaces = 10 - strlen(NowStr);
659 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800660
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700661 totalSize = 0;
662 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700663 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700664 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800665
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700666 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800667 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700668 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700669 if (spaces < 0) spaces = 0;
670 size_t szs = sizes(id);
671 totalSize += szs;
672 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800673 output +=
674 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700675 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800676 }
677 spaces += spaces_total;
678 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700679 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800680 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
681 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700682
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700683 static const char SpanStr[] = "\nLogspan";
684 spaces = 10 - strlen(SpanStr);
685 output += SpanStr;
686
687 // Total reports the greater of the individual maximum time span, or the
688 // validated minimum start and maximum end time span if it makes sense.
689 uint64_t minTime = UINT64_MAX;
690 uint64_t maxTime = 0;
691 uint64_t maxSpan = 0;
692 totalSize = 0;
693
694 log_id_for_each(id) {
695 if (!(logMask & (1 << id))) continue;
696
697 // validity checking
698 uint64_t oldest = mOldest[id].msec();
699 uint64_t newest = mNewest[id].msec();
700 if (newest <= oldest) {
701 spaces += spaces_total;
702 continue;
703 }
704
705 uint64_t span = newest - oldest;
706 if (span > (monthSec * MS_PER_SEC)) {
707 spaces += spaces_total;
708 continue;
709 }
710
711 // total span
712 if (minTime > oldest) minTime = oldest;
713 if (maxTime < newest) maxTime = newest;
714 if (span > maxSpan) maxSpan = span;
715 totalSize += span;
716
717 uint64_t dropped = mNewestDropped[id].msec();
718 if (dropped < oldest) dropped = oldest;
719 if (dropped > newest) dropped = newest;
720
721 oldLength = output.length();
722 output += android::base::StringPrintf("%*s%s", spaces, "",
723 formatMsec(span).c_str());
724 unsigned permille = ((newest - dropped) * 1000 + (span / 2)) / span;
725 if ((permille > 1) && (permille < 999)) {
726 output += android::base::StringPrintf("(%u", permille / 10);
727 permille %= 10;
728 if (permille) {
729 output += android::base::StringPrintf(".%u", permille);
730 }
731 output += android::base::StringPrintf("%%)");
732 }
733 spaces -= output.length() - oldLength;
734 spaces += spaces_total;
735 }
736 if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
737 (maxTime > maxSpan)) {
738 maxSpan = maxTime;
739 }
740 if (spaces < 0) spaces = 0;
741 output += android::base::StringPrintf("%*s%s", spaces, "",
742 formatMsec(maxSpan).c_str());
743
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700744 static const char OverheadStr[] = "\nOverhead";
745 spaces = 10 - strlen(OverheadStr);
746 output += OverheadStr;
747
748 totalSize = 0;
749 log_id_for_each(id) {
750 if (!(logMask & (1 << id))) continue;
751
752 size_t els = elements(id);
753 if (els) {
754 oldLength = output.length();
755 if (spaces < 0) spaces = 0;
756 // estimate the std::list overhead.
757 static const size_t overhead =
758 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800759 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700760 sizeof(std::list<LogBufferElement*>);
761 size_t szs = sizes(id) + els * overhead;
762 totalSize += szs;
763 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
764 spaces -= output.length() - oldLength;
765 }
766 spaces += spaces_total;
767 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700768 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700769 if (spaces < 0) spaces = 0;
770 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800771
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700772 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700773
Mark Salyzyn758058f2015-08-21 16:44:30 -0700774 std::string name;
775
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700776 // Chattiest by application (UID)
777 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700778 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700779
Mark Salyzyn501c3732017-03-10 14:31:54 -0800780 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
781 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800782 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700783 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700784
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700785 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800786 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
787 : "Logging for this PID:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800788 output += pidTable.format(*this, uid, pid, name);
789 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700790 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800791 name += ":";
792 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700793 }
794
Mark Salyzyn344bff42015-04-13 14:24:45 -0700795 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800796 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700797 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800798 name += ":";
799 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700800 }
801
Mark Salyzyn083b0372015-12-04 10:59:45 -0800802 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800803 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700804 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800805 name += ":";
Mark Salyzyn501c3732017-03-10 14:31:54 -0800806 output +=
807 securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800808 }
809
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700810 if (enable) {
811 name = "Chattiest TAGs";
812 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
813 name += ":";
814 output += tagNameTable.format(*this, uid, pid, name);
815 }
816
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700817 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800818}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700819
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700820namespace android {
821
822uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700823 char buffer[512];
824 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800825 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700826 if (fp) {
827 while (fgets(buffer, sizeof(buffer), fp)) {
Mark Salyzync4e48232017-05-04 13:54:46 -0700828 int uid = AID_LOGD;
829 char space = 0;
830 if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
831 isspace(space)) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700832 fclose(fp);
833 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700834 }
835 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700836 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700837 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800838 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700839}
Mark Salyzync4e48232017-05-04 13:54:46 -0700840
841pid_t tidToPid(pid_t tid) {
842 char buffer[512];
843 snprintf(buffer, sizeof(buffer), "/proc/%u/status", tid);
844 FILE* fp = fopen(buffer, "r");
845 if (fp) {
846 while (fgets(buffer, sizeof(buffer), fp)) {
847 int pid = tid;
848 char space = 0;
849 if ((sscanf(buffer, "Tgid: %d%c", &pid, &space) == 2) &&
850 isspace(space)) {
851 fclose(fp);
852 return pid;
853 }
854 }
855 fclose(fp);
856 }
857 return tid;
858}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700859}
860
861uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700862 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700863}
864
Mark Salyzync4e48232017-05-04 13:54:46 -0700865pid_t LogStatistics::tidToPid(pid_t tid) {
866 return tidTable.add(tid)->second.getPid();
867}
868
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700869// caller must free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800870const char* LogStatistics::pidToName(pid_t pid) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700871 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800872 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
873 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700874 if (!name) {
875 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700876 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700877 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700878}