blob: b41aca5bf569c9b4aa33e602ceb854d64bc7001c [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 Salyzyn02dd2f42017-04-14 09:46:57 -070018#include <inttypes.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070019#include <pwd.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070020#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070021#include <string.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070022#include <sys/types.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070023#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080024
Mark Salyzyn9af33ee2016-10-05 12:34:37 -070025#include <list>
26
Mark Salyzynaeaaf812016-09-30 13:30:33 -070027#include <android/log.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080028
29#include "LogStatistics.h"
30
Mark Salyzyn32962912016-09-12 10:29:17 -070031size_t LogStatistics::SizesTotal;
32
Mark Salyzyn77187782015-05-12 15:21:31 -070033LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070034 log_id_for_each(id) {
35 mSizes[id] = 0;
36 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070037 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070038 mSizesTotal[id] = 0;
39 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080040 }
41}
42
Mark Salyzyn720f6d12015-03-16 08:26:05 -070043namespace android {
44
Mark Salyzyn501c3732017-03-10 14:31:54 -080045size_t sizesTotal() {
46 return LogStatistics::sizesTotal();
47}
Mark Salyzyn32962912016-09-12 10:29:17 -070048
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070049// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080050char* pidToName(pid_t pid) {
51 char* retval = NULL;
52 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070053 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070054 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070055 char buffer[512];
56 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
57 int fd = open(buffer, O_RDONLY);
58 if (fd >= 0) {
59 ssize_t ret = read(fd, buffer, sizeof(buffer));
60 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080061 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070062 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080063 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070064 retval = strdup(buffer);
65 }
66 }
67 close(fd);
68 }
69 }
70 return retval;
71}
Mark Salyzyn720f6d12015-03-16 08:26:05 -070072}
73
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070074void LogStatistics::addTotal(LogBufferElement* element) {
75 if (element->getDropped()) return;
76
77 log_id_t log_id = element->getLogId();
78 unsigned short size = element->getMsgLen();
79 mSizesTotal[log_id] += size;
80 SizesTotal += size;
81 ++mElementsTotal[log_id];
82}
83
Mark Salyzyn501c3732017-03-10 14:31:54 -080084void LogStatistics::add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -070085 log_id_t log_id = element->getLogId();
86 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080087 mSizes[log_id] += size;
88 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070089
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070090 // When caller adding a chatty entry, they will have already
91 // called add() and subtract() for each entry as they are
92 // evaluated and trimmed, thus recording size and number of
93 // elements, but we must recognize the manufactured dropped
94 // entry as not contributing to the lifetime totals.
Mark Salyzyna2c02222016-12-13 10:31:29 -080095 if (element->getDropped()) {
96 ++mDroppedElements[log_id];
97 } else {
Mark Salyzyna2c02222016-12-13 10:31:29 -080098 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -070099 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -0800100 ++mElementsTotal[log_id];
101 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700102
Mark Salyzynae4d9282014-10-15 08:49:39 -0700103 if (log_id == LOG_ID_KERNEL) {
104 return;
105 }
106
Mark Salyzyn758058f2015-08-21 16:44:30 -0700107 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700108 if (element->getUid() == AID_SYSTEM) {
109 pidSystemTable[log_id].add(element->getPid(), element);
110 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700111
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112 if (!enable) {
113 return;
114 }
115
Mark Salyzyn758058f2015-08-21 16:44:30 -0700116 pidTable.add(element->getPid(), element);
117 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700118
Mark Salyzyn758058f2015-08-21 16:44:30 -0700119 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700120 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800121 if (log_id == LOG_ID_SECURITY) {
122 securityTagTable.add(tag, element);
123 } else {
124 tagTable.add(tag, element);
125 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700126 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800127}
128
Mark Salyzyn501c3732017-03-10 14:31:54 -0800129void LogStatistics::subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700130 log_id_t log_id = element->getLogId();
131 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800132 mSizes[log_id] -= size;
133 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700134 if (element->getDropped()) {
135 --mDroppedElements[log_id];
136 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700137
Mark Salyzynae4d9282014-10-15 08:49:39 -0700138 if (log_id == LOG_ID_KERNEL) {
139 return;
140 }
141
Mark Salyzyn758058f2015-08-21 16:44:30 -0700142 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700143 if (element->getUid() == AID_SYSTEM) {
144 pidSystemTable[log_id].subtract(element->getPid(), element);
145 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800146
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700147 if (!enable) {
148 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800149 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700150
Mark Salyzyn758058f2015-08-21 16:44:30 -0700151 pidTable.subtract(element->getPid(), element);
152 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700153
Mark Salyzyn758058f2015-08-21 16:44:30 -0700154 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700155 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800156 if (log_id == LOG_ID_SECURITY) {
157 securityTagTable.subtract(tag, element);
158 } else {
159 tagTable.subtract(tag, element);
160 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700161 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800162}
163
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700164// Atomically set an entry to drop
165// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800166void LogStatistics::drop(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700167 log_id_t log_id = element->getLogId();
168 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700169 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700170 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700171
Mark Salyzyn758058f2015-08-21 16:44:30 -0700172 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700173 if (element->getUid() == AID_SYSTEM) {
174 pidSystemTable[log_id].drop(element->getPid(), element);
175 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700176
177 if (!enable) {
178 return;
179 }
180
Mark Salyzyn758058f2015-08-21 16:44:30 -0700181 pidTable.drop(element->getPid(), element);
182 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700183
184 uint32_t tag = element->getTag();
185 if (tag) {
186 if (log_id == LOG_ID_SECURITY) {
187 securityTagTable.drop(tag, element);
188 } else {
189 tagTable.drop(tag, element);
190 }
191 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700192}
193
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700194// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800195const char* LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700196 // Local hard coded favourites
197 if (uid == AID_LOGD) {
198 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800199 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700200
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700201 // Android system
202 if (uid < AID_APP) {
203 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800204 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700205 if (pwd) {
206 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700207 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800208 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700209
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700210 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700211 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800212 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700213 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
214 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
215 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700216 if (name) {
217 return name;
218 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700219
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700220 // Android application
221 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800222 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700223 if (pwd) {
224 return strdup(pwd->pw_name);
225 }
226 }
227
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700228 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800229 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
230 ++it) {
231 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700232
233 if (entry.getUid() == uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800234 const char* nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700235
Mark Salyzyn758058f2015-08-21 16:44:30 -0700236 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700237 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700238 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800239 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800240 free(const_cast<char*>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700241 name = NULL;
242 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700243 }
244 }
245 }
246 }
247
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700248 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700249 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800250}
251
Mark Salyzyn501c3732017-03-10 14:31:54 -0800252std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700253 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800254 return formatLine(android::base::StringPrintf(name.c_str(),
255 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700256 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800257 std::string(isprune ? "+/- Pruned" : "")) +
258 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700259 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800260}
261
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700262// Helper to truncate name, if too long, and add name dressings
263static void formatTmp(const LogStatistics& stat, const char* nameTmp, uid_t uid,
264 std::string& name, std::string& size, size_t nameLen) {
265 const char* allocNameTmp = nullptr;
266 if (!nameTmp) nameTmp = allocNameTmp = stat.uidToName(uid);
267 if (nameTmp) {
268 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
269 size_t len = EntryBaseConstants::total_len -
270 EntryBaseConstants::pruned_len - size.length() -
271 name.length() - lenSpace - 2;
272 size_t lenNameTmp = strlen(nameTmp);
273 while ((len < lenNameTmp) && (lenSpace > 1)) {
274 ++len;
275 --lenSpace;
276 }
277 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
278 if (len < lenNameTmp) {
279 name += "...";
280 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
281 }
282 name += nameTmp;
283 free(const_cast<char*>(allocNameTmp));
284 }
285}
286
Mark Salyzyn501c3732017-03-10 14:31:54 -0800287std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800288 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700289 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700290 std::string size = android::base::StringPrintf("%zu", getSizes());
291
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700292 formatTmp(stat, nullptr, uid, name, size, 6);
293
Mark Salyzyn758058f2015-08-21 16:44:30 -0700294 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700295 if (worstUidEnabledForLogid(id)) {
296 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800297 for (LogStatistics::uidTable_t::const_iterator it =
298 stat.uidTable[id].begin();
299 it != stat.uidTable[id].end(); ++it) {
Mark Salyzync723df82015-08-24 11:08:00 -0700300 totalDropped += it->second.getDropped();
301 }
302 size_t sizes = stat.sizes(id);
303 size_t totalSize = stat.sizesTotal(id);
304 size_t totalElements = stat.elementsTotal(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800305 float totalVirtualSize =
306 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700307 size_t entrySize = getSizes();
308 float virtualEntrySize = entrySize;
309 int realPermille = virtualEntrySize * 1000.0 / sizes;
310 size_t dropped = getDropped();
311 if (dropped) {
312 pruned = android::base::StringPrintf("%zu", dropped);
313 virtualEntrySize += (float)dropped * totalSize / totalElements;
314 }
315 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800316 int permille =
317 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700318 if ((permille < -1) || (1 < permille)) {
319 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800320 const char* units = "%";
321 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700322
323 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800324 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700325 units = "X";
326 prefix = "";
327 }
328 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800329 change = android::base::StringPrintf(
330 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700331 ((permille < 0) ? (-permille % 10) : (permille % 10)),
332 units);
333 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800334 change = android::base::StringPrintf(
335 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700336 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800337 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
338 pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700339 if ((spaces <= 0) && pruned.length()) {
340 spaces = 1;
341 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000342 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700343 change += android::base::StringPrintf("%*s", (int)spaces, "");
344 }
345 pruned = change + pruned;
346 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700347 }
348
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700349 std::string output = formatLine(name, size, pruned);
350
351 if (uid != AID_SYSTEM) {
352 return output;
353 }
354
355 static const size_t maximum_sorted_entries = 32;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800356 std::unique_ptr<const PidEntry* []> sorted =
357 stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700358
359 if (!sorted.get()) {
360 return output;
361 }
362 std::string byPid;
363 size_t index;
364 bool hasDropped = false;
365 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800366 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700367 if (!entry) {
368 break;
369 }
370 if (entry->getSizes() <= (getSizes() / 100)) {
371 break;
372 }
373 if (entry->getDropped()) {
374 hasDropped = true;
375 }
376 byPid += entry->format(stat, id);
377 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800378 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700379 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800380 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
381 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700382 output += byPid;
383 }
384
385 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700386}
387
Mark Salyzyn501c3732017-03-10 14:31:54 -0800388std::string PidEntry::formatHeader(const std::string& name,
389 log_id_t /* id */) const {
390 return formatLine(name, std::string("Size"), std::string("Pruned")) +
391 formatLine(std::string(" PID/UID COMMAND LINE"),
392 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700393}
394
Mark Salyzyn501c3732017-03-10 14:31:54 -0800395std::string PidEntry::format(const LogStatistics& stat,
396 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700397 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800398 pid_t pid = getPid();
399 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800400 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700401
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700402 formatTmp(stat, getName(), uid, name, size, 12);
403
Mark Salyzyn758058f2015-08-21 16:44:30 -0700404 std::string pruned = "";
405 size_t dropped = getDropped();
406 if (dropped) {
407 pruned = android::base::StringPrintf("%zu", dropped);
408 }
409
410 return formatLine(name, size, pruned);
411}
412
Mark Salyzyn501c3732017-03-10 14:31:54 -0800413std::string TidEntry::formatHeader(const std::string& name,
414 log_id_t /* id */) const {
415 return formatLine(name, std::string("Size"), std::string("Pruned")) +
416 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700417 std::string("NUM"));
418}
419
Mark Salyzyn501c3732017-03-10 14:31:54 -0800420std::string TidEntry::format(const LogStatistics& stat,
421 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700422 uid_t uid = getUid();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800423 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800424 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700425
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700426 formatTmp(stat, getName(), uid, name, size, 12);
427
Mark Salyzyn758058f2015-08-21 16:44:30 -0700428 std::string pruned = "";
429 size_t dropped = getDropped();
430 if (dropped) {
431 pruned = android::base::StringPrintf("%zu", dropped);
432 }
433
434 return formatLine(name, size, pruned);
435}
436
Mark Salyzyn501c3732017-03-10 14:31:54 -0800437std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700438 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800439 return formatLine(name, std::string("Size"),
440 std::string(isprune ? "Prune" : "")) +
441 formatLine(std::string(" TAG/UID TAGNAME"),
442 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700443}
444
Mark Salyzyn501c3732017-03-10 14:31:54 -0800445std::string TagEntry::format(const LogStatistics& /* stat */,
446 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700447 std::string name;
448 uid_t uid = getUid();
449 if (uid == (uid_t)-1) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800450 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700451 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800452 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700453 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800454 const char* nameTmp = getName();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700455 if (nameTmp) {
456 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800457 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700458 }
459
Mark Salyzyn501c3732017-03-10 14:31:54 -0800460 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700461
462 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700463 size_t dropped = getDropped();
464 if (dropped) {
465 pruned = android::base::StringPrintf("%zu", dropped);
466 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700467
468 return formatLine(name, size, pruned);
469}
470
Mark Salyzynee3b8382015-12-17 09:58:43 -0800471std::string LogStatistics::format(uid_t uid, pid_t pid,
472 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700473 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800474
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700475 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800476
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700477 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700478 size_t oldLength;
479 short spaces = 1;
480
481 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700482 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700483 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700484 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700485 output += android::base::StringPrintf("%*s%s", spaces, "",
486 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700487 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800488 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700489 if (spaces < 0) spaces = 0;
490 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800491
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700492 static const char TotalStr[] = "\nTotal";
493 spaces = 10 - strlen(TotalStr);
494 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800495
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700496 size_t totalSize = 0;
497 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700498 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700499 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700500 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700501 if (spaces < 0) spaces = 0;
502 size_t szs = sizesTotal(id);
503 totalSize += szs;
504 size_t els = elementsTotal(id);
505 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800506 output +=
507 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700508 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800509 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700510 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800511 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
512 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800513
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700514 static const char NowStr[] = "\nNow";
515 spaces = 10 - strlen(NowStr);
516 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800517
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700518 totalSize = 0;
519 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700520 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700521 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800522
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700523 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800524 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700525 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700526 if (spaces < 0) spaces = 0;
527 size_t szs = sizes(id);
528 totalSize += szs;
529 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800530 output +=
531 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700532 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800533 }
534 spaces += spaces_total;
535 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700536 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800537 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
538 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700539
540 static const char OverheadStr[] = "\nOverhead";
541 spaces = 10 - strlen(OverheadStr);
542 output += OverheadStr;
543
544 totalSize = 0;
545 log_id_for_each(id) {
546 if (!(logMask & (1 << id))) continue;
547
548 size_t els = elements(id);
549 if (els) {
550 oldLength = output.length();
551 if (spaces < 0) spaces = 0;
552 // estimate the std::list overhead.
553 static const size_t overhead =
554 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800555 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700556 sizeof(std::list<LogBufferElement*>);
557 size_t szs = sizes(id) + els * overhead;
558 totalSize += szs;
559 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
560 spaces -= output.length() - oldLength;
561 }
562 spaces += spaces_total;
563 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700564 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700565 if (spaces < 0) spaces = 0;
566 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800567
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700568 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700569
Mark Salyzyn758058f2015-08-21 16:44:30 -0700570 std::string name;
571
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700572 // Chattiest by application (UID)
573 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700574 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700575
Mark Salyzyn501c3732017-03-10 14:31:54 -0800576 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
577 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800578 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700579 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700580
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700581 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800582 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
583 : "Logging for this PID:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800584 output += pidTable.format(*this, uid, pid, name);
585 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700586 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800587 name += ":";
588 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700589 }
590
Mark Salyzyn344bff42015-04-13 14:24:45 -0700591 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800592 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700593 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800594 name += ":";
595 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700596 }
597
Mark Salyzyn083b0372015-12-04 10:59:45 -0800598 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800599 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700600 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800601 name += ":";
Mark Salyzyn501c3732017-03-10 14:31:54 -0800602 output +=
603 securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800604 }
605
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700606 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800607}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700608
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700609namespace android {
610
611uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700612 char buffer[512];
613 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800614 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700615 if (fp) {
616 while (fgets(buffer, sizeof(buffer), fp)) {
617 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700618 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700619 fclose(fp);
620 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700621 }
622 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700623 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700624 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800625 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700626}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700627}
628
629uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700630 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700631}
632
633// caller must free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800634const char* LogStatistics::pidToName(pid_t pid) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700635 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800636 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
637 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700638 if (!name) {
639 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700640 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700641 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700642}