blob: 4c4c1dbb3fefd356560fa75d205f576fabbdd75e [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) {
Yi Kongc8d09dd2018-07-13 17:39:22 -070059 char* retval = nullptr;
Mark Salyzyn501c3732017-03-10 14:31:54 -080060 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();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -070086 uint16_t size = element->getMsgLen();
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070087 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();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -070094 uint16_t 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();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700164 uint16_t 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();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700209 uint16_t 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));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700289 name = nullptr;
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700290 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
Tom Cherryb6b78e92020-05-07 09:13:12 -0700300template <typename TKey, typename TEntry>
301void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
302 int* worst, size_t* worst_sizes,
303 size_t* second_worst_sizes) {
304 std::array<const TEntry*, 2> max_entries;
305 table.MaxEntries(AID_ROOT, 0, &max_entries);
306 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
307 return;
308 }
309 *worst_sizes = max_entries[0]->getSizes();
310 // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
311 // 100 characters.
312 if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->getDropped())) {
313 *worst = max_entries[0]->getKey();
314 *second_worst_sizes = max_entries[1]->getSizes();
315 if (*second_worst_sizes < threshold) {
316 *second_worst_sizes = threshold;
317 }
318 }
319}
320
321void LogStatistics::WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
322 size_t* second_worst_sizes) {
323 WorstTwoWithThreshold(uidTable[id], threshold, worst, worst_sizes, second_worst_sizes);
324}
325
326void LogStatistics::WorstTwoTags(size_t threshold, int* worst, size_t* worst_sizes,
327 size_t* second_worst_sizes) {
328 WorstTwoWithThreshold(tagTable, threshold, worst, worst_sizes, second_worst_sizes);
329}
330
331void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst,
332 size_t* second_worst_sizes) {
333 std::array<const PidEntry*, 2> max_entries;
334 pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, &max_entries);
335 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
336 return;
337 }
338
339 *worst = max_entries[0]->getKey();
340 *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
341}
342
Mark Salyzyn501c3732017-03-10 14:31:54 -0800343std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700344 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800345 return formatLine(android::base::StringPrintf(name.c_str(),
346 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700347 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800348 std::string(isprune ? "+/- Pruned" : "")) +
349 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700350 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800351}
352
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700353// Helper to truncate name, if too long, and add name dressings
354static void formatTmp(const LogStatistics& stat, const char* nameTmp, uid_t uid,
355 std::string& name, std::string& size, size_t nameLen) {
356 const char* allocNameTmp = nullptr;
357 if (!nameTmp) nameTmp = allocNameTmp = stat.uidToName(uid);
358 if (nameTmp) {
359 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
360 size_t len = EntryBaseConstants::total_len -
361 EntryBaseConstants::pruned_len - size.length() -
362 name.length() - lenSpace - 2;
363 size_t lenNameTmp = strlen(nameTmp);
364 while ((len < lenNameTmp) && (lenSpace > 1)) {
365 ++len;
366 --lenSpace;
367 }
368 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
369 if (len < lenNameTmp) {
370 name += "...";
371 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
372 }
373 name += nameTmp;
374 free(const_cast<char*>(allocNameTmp));
375 }
376}
377
Mark Salyzyn501c3732017-03-10 14:31:54 -0800378std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800379 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700380 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700381 std::string size = android::base::StringPrintf("%zu", getSizes());
382
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700383 formatTmp(stat, nullptr, uid, name, size, 6);
384
Mark Salyzyn758058f2015-08-21 16:44:30 -0700385 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700386 if (worstUidEnabledForLogid(id)) {
387 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800388 for (LogStatistics::uidTable_t::const_iterator it =
389 stat.uidTable[id].begin();
390 it != stat.uidTable[id].end(); ++it) {
Mark Salyzync723df82015-08-24 11:08:00 -0700391 totalDropped += it->second.getDropped();
392 }
393 size_t sizes = stat.sizes(id);
394 size_t totalSize = stat.sizesTotal(id);
395 size_t totalElements = stat.elementsTotal(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800396 float totalVirtualSize =
397 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700398 size_t entrySize = getSizes();
399 float virtualEntrySize = entrySize;
400 int realPermille = virtualEntrySize * 1000.0 / sizes;
401 size_t dropped = getDropped();
402 if (dropped) {
403 pruned = android::base::StringPrintf("%zu", dropped);
404 virtualEntrySize += (float)dropped * totalSize / totalElements;
405 }
406 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800407 int permille =
408 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700409 if ((permille < -1) || (1 < permille)) {
410 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800411 const char* units = "%";
412 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700413
414 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800415 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700416 units = "X";
417 prefix = "";
418 }
419 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800420 change = android::base::StringPrintf(
421 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700422 ((permille < 0) ? (-permille % 10) : (permille % 10)),
423 units);
424 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800425 change = android::base::StringPrintf(
426 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700427 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800428 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
429 pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700430 if ((spaces <= 0) && pruned.length()) {
431 spaces = 1;
432 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000433 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700434 change += android::base::StringPrintf("%*s", (int)spaces, "");
435 }
436 pruned = change + pruned;
437 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700438 }
439
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700440 std::string output = formatLine(name, size, pruned);
441
442 if (uid != AID_SYSTEM) {
443 return output;
444 }
445
446 static const size_t maximum_sorted_entries = 32;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700447 std::array<const PidEntry*, maximum_sorted_entries> sorted;
448 stat.pidSystemTable[id].MaxEntries(uid, 0, &sorted);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700449
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700450 std::string byPid;
451 size_t index;
452 bool hasDropped = false;
453 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800454 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700455 if (!entry) {
456 break;
457 }
458 if (entry->getSizes() <= (getSizes() / 100)) {
459 break;
460 }
461 if (entry->getDropped()) {
462 hasDropped = true;
463 }
464 byPid += entry->format(stat, id);
465 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800466 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700467 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800468 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
469 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700470 output += byPid;
471 }
472
473 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700474}
475
Mark Salyzyn501c3732017-03-10 14:31:54 -0800476std::string PidEntry::formatHeader(const std::string& name,
477 log_id_t /* id */) const {
478 return formatLine(name, std::string("Size"), std::string("Pruned")) +
479 formatLine(std::string(" PID/UID COMMAND LINE"),
480 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700481}
482
Mark Salyzyn501c3732017-03-10 14:31:54 -0800483std::string PidEntry::format(const LogStatistics& stat,
484 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700485 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800486 pid_t pid = getPid();
487 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800488 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700489
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700490 formatTmp(stat, getName(), uid, name, size, 12);
491
Mark Salyzyn758058f2015-08-21 16:44:30 -0700492 std::string pruned = "";
493 size_t dropped = getDropped();
494 if (dropped) {
495 pruned = android::base::StringPrintf("%zu", dropped);
496 }
497
498 return formatLine(name, size, pruned);
499}
500
Mark Salyzyn501c3732017-03-10 14:31:54 -0800501std::string TidEntry::formatHeader(const std::string& name,
502 log_id_t /* id */) const {
503 return formatLine(name, std::string("Size"), std::string("Pruned")) +
504 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700505 std::string("NUM"));
506}
507
Mark Salyzyn501c3732017-03-10 14:31:54 -0800508std::string TidEntry::format(const LogStatistics& stat,
509 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700510 uid_t uid = getUid();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800511 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800512 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700513
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700514 formatTmp(stat, getName(), uid, name, size, 12);
515
Mark Salyzyn758058f2015-08-21 16:44:30 -0700516 std::string pruned = "";
517 size_t dropped = getDropped();
518 if (dropped) {
519 pruned = android::base::StringPrintf("%zu", dropped);
520 }
521
522 return formatLine(name, size, pruned);
523}
524
Mark Salyzyn501c3732017-03-10 14:31:54 -0800525std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700526 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800527 return formatLine(name, std::string("Size"),
528 std::string(isprune ? "Prune" : "")) +
529 formatLine(std::string(" TAG/UID TAGNAME"),
530 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700531}
532
Mark Salyzyn501c3732017-03-10 14:31:54 -0800533std::string TagEntry::format(const LogStatistics& /* stat */,
534 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700535 std::string name;
536 uid_t uid = getUid();
537 if (uid == (uid_t)-1) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800538 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700539 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800540 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700541 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800542 const char* nameTmp = getName();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700543 if (nameTmp) {
544 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800545 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700546 }
547
Mark Salyzyn501c3732017-03-10 14:31:54 -0800548 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700549
550 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700551 size_t dropped = getDropped();
552 if (dropped) {
553 pruned = android::base::StringPrintf("%zu", dropped);
554 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700555
556 return formatLine(name, size, pruned);
557}
558
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700559std::string TagNameEntry::formatHeader(const std::string& name,
560 log_id_t /* id */) const {
561 return formatLine(name, std::string("Size"), std::string("")) +
562 formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
563 std::string("BYTES"), std::string(""));
564}
565
566std::string TagNameEntry::format(const LogStatistics& /* stat */,
567 log_id_t /* id */) const {
568 std::string name;
569 pid_t tid = getTid();
570 pid_t pid = getPid();
571 std::string pidstr;
572 if (pid != (pid_t)-1) {
573 pidstr = android::base::StringPrintf("%u", pid);
574 if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr;
575 }
576 int len = 9 - pidstr.length();
577 if (len < 0) len = 0;
578 if ((tid == (pid_t)-1) || (tid == pid)) {
579 name = android::base::StringPrintf("%*s", len, "");
580 } else {
581 name = android::base::StringPrintf("%*u", len, tid);
582 }
583 name += pidstr;
584 uid_t uid = getUid();
585 if (uid != (uid_t)-1) {
586 name += android::base::StringPrintf("/%u", uid);
587 }
588
589 std::string size = android::base::StringPrintf("%zu", getSizes());
590
591 const char* nameTmp = getName();
592 if (nameTmp) {
593 size_t lenSpace = std::max(16 - name.length(), (size_t)1);
594 size_t len = EntryBaseConstants::total_len -
595 EntryBaseConstants::pruned_len - size.length() -
596 name.length() - lenSpace - 2;
597 size_t lenNameTmp = strlen(nameTmp);
598 while ((len < lenNameTmp) && (lenSpace > 1)) {
599 ++len;
600 --lenSpace;
601 }
602 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
603 if (len < lenNameTmp) {
604 name += "...";
605 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
606 }
607 name += nameTmp;
608 }
609
610 std::string pruned = "";
611
612 return formatLine(name, size, pruned);
613}
614
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700615static std::string formatMsec(uint64_t val) {
616 static const unsigned subsecDigits = 3;
617 static const uint64_t sec = MS_PER_SEC;
618
619 static const uint64_t minute = 60 * sec;
620 static const uint64_t hour = 60 * minute;
621 static const uint64_t day = 24 * hour;
622
623 std::string output;
624 if (val < sec) return output;
625
626 if (val >= day) {
627 output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
628 val = (val % day) + day;
629 }
630 if (val >= minute) {
631 if (val >= hour) {
632 output += android::base::StringPrintf("%" PRIu64 ":",
633 (val / hour) % (day / hour));
634 }
635 output += android::base::StringPrintf(
636 (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
637 (val / minute) % (hour / minute));
638 }
639 output +=
640 android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
641 (val / sec) % (minute / sec));
642 val %= sec;
643 unsigned digits = subsecDigits;
644 while (digits && ((val % 10) == 0)) {
645 val /= 10;
646 --digits;
647 }
648 if (digits) {
649 output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
650 }
651 return output;
652}
653
Mark Salyzynee3b8382015-12-17 09:58:43 -0800654std::string LogStatistics::format(uid_t uid, pid_t pid,
655 unsigned int logMask) const {
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700656 static const uint16_t spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800657
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700658 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800659
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700660 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700661 size_t oldLength;
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700662 int16_t spaces = 1;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700663
664 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700665 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700666 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700667 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700668 output += android::base::StringPrintf("%*s%s", spaces, "",
669 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700670 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800671 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700672 if (spaces < 0) spaces = 0;
673 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800674
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700675 static const char TotalStr[] = "\nTotal";
676 spaces = 10 - strlen(TotalStr);
677 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800678
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700679 size_t totalSize = 0;
680 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700681 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700682 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700683 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700684 if (spaces < 0) spaces = 0;
685 size_t szs = sizesTotal(id);
686 totalSize += szs;
687 size_t els = elementsTotal(id);
688 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800689 output +=
690 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700691 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800692 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700693 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800694 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
695 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800696
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700697 static const char NowStr[] = "\nNow";
698 spaces = 10 - strlen(NowStr);
699 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800700
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700701 totalSize = 0;
702 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700703 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700704 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800705
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700706 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800707 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700708 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700709 if (spaces < 0) spaces = 0;
710 size_t szs = sizes(id);
711 totalSize += szs;
712 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800713 output +=
714 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700715 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800716 }
717 spaces += spaces_total;
718 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700719 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800720 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
721 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700722
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700723 static const char SpanStr[] = "\nLogspan";
724 spaces = 10 - strlen(SpanStr);
725 output += SpanStr;
726
727 // Total reports the greater of the individual maximum time span, or the
728 // validated minimum start and maximum end time span if it makes sense.
729 uint64_t minTime = UINT64_MAX;
730 uint64_t maxTime = 0;
731 uint64_t maxSpan = 0;
732 totalSize = 0;
733
734 log_id_for_each(id) {
735 if (!(logMask & (1 << id))) continue;
736
737 // validity checking
738 uint64_t oldest = mOldest[id].msec();
739 uint64_t newest = mNewest[id].msec();
740 if (newest <= oldest) {
741 spaces += spaces_total;
742 continue;
743 }
744
745 uint64_t span = newest - oldest;
746 if (span > (monthSec * MS_PER_SEC)) {
747 spaces += spaces_total;
748 continue;
749 }
750
751 // total span
752 if (minTime > oldest) minTime = oldest;
753 if (maxTime < newest) maxTime = newest;
754 if (span > maxSpan) maxSpan = span;
755 totalSize += span;
756
757 uint64_t dropped = mNewestDropped[id].msec();
758 if (dropped < oldest) dropped = oldest;
759 if (dropped > newest) dropped = newest;
760
761 oldLength = output.length();
762 output += android::base::StringPrintf("%*s%s", spaces, "",
763 formatMsec(span).c_str());
764 unsigned permille = ((newest - dropped) * 1000 + (span / 2)) / span;
765 if ((permille > 1) && (permille < 999)) {
766 output += android::base::StringPrintf("(%u", permille / 10);
767 permille %= 10;
768 if (permille) {
769 output += android::base::StringPrintf(".%u", permille);
770 }
771 output += android::base::StringPrintf("%%)");
772 }
773 spaces -= output.length() - oldLength;
774 spaces += spaces_total;
775 }
776 if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
777 (maxTime > maxSpan)) {
778 maxSpan = maxTime;
779 }
780 if (spaces < 0) spaces = 0;
781 output += android::base::StringPrintf("%*s%s", spaces, "",
782 formatMsec(maxSpan).c_str());
783
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700784 static const char OverheadStr[] = "\nOverhead";
785 spaces = 10 - strlen(OverheadStr);
786 output += OverheadStr;
787
788 totalSize = 0;
789 log_id_for_each(id) {
790 if (!(logMask & (1 << id))) continue;
791
792 size_t els = elements(id);
793 if (els) {
794 oldLength = output.length();
795 if (spaces < 0) spaces = 0;
796 // estimate the std::list overhead.
797 static const size_t overhead =
798 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800799 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700800 sizeof(std::list<LogBufferElement*>);
801 size_t szs = sizes(id) + els * overhead;
802 totalSize += szs;
803 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
804 spaces -= output.length() - oldLength;
805 }
806 spaces += spaces_total;
807 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700808 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700809 if (spaces < 0) spaces = 0;
810 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800811
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700812 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700813
Mark Salyzyn758058f2015-08-21 16:44:30 -0700814 std::string name;
815
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700816 // Chattiest by application (UID)
817 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700818 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700819
Mark Salyzyn501c3732017-03-10 14:31:54 -0800820 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
821 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800822 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700823 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700824
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700825 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800826 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
827 : "Logging for this PID:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800828 output += pidTable.format(*this, uid, pid, name);
829 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700830 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800831 name += ":";
832 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700833 }
834
Mark Salyzyn344bff42015-04-13 14:24:45 -0700835 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800836 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700837 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800838 name += ":";
839 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700840 }
841
Mark Salyzyn083b0372015-12-04 10:59:45 -0800842 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800843 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700844 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800845 name += ":";
Mark Salyzyn501c3732017-03-10 14:31:54 -0800846 output +=
847 securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800848 }
849
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700850 if (enable) {
851 name = "Chattiest TAGs";
852 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
853 name += ":";
854 output += tagNameTable.format(*this, uid, pid, name);
855 }
856
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700857 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800858}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700859
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700860namespace android {
861
862uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700863 char buffer[512];
864 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800865 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700866 if (fp) {
867 while (fgets(buffer, sizeof(buffer), fp)) {
Mark Salyzync4e48232017-05-04 13:54:46 -0700868 int uid = AID_LOGD;
869 char space = 0;
870 if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
871 isspace(space)) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700872 fclose(fp);
873 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700874 }
875 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700876 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700877 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800878 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700879}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700880}
881
882uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700883 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700884}
885
886// caller must free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800887const char* LogStatistics::pidToName(pid_t pid) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700888 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800889 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
890 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700891 if (!name) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700892 return nullptr;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700893 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700894 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700895}