LogStatistics.cpp revision f31ae3d666f6e723a7dde6734c6d8395f8bcdc11
134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn/*
234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Copyright (C) 2014 The Android Open Source Project
334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * you may not use this file except in compliance with the License.
634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * You may obtain a copy of the License at
734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
1034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
1134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
1234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * See the License for the specific language governing permissions and
1434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * limitations under the License.
1534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn */
1634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
179a03863e88da99ba010342c874252089dd771f7fMark Salyzyn#include <fcntl.h>
18b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn#include <pwd.h>
1997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <stdio.h>
2097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <string.h>
21b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn#include <sys/types.h>
2297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <unistd.h>
2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
249af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn#include <list>
259af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
26aeaaf81c2cc8366ac4f66eb3d2fc85f9b8194982Mark Salyzyn#include <android/log.h>
2734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
2834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include "LogStatistics.h"
2934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
303296291cffd13af13ea9e60a8ac1138101cf8e4cMark Salyzynsize_t LogStatistics::SizesTotal;
313296291cffd13af13ea9e60a8ac1138101cf8e4cMark Salyzyn
327718778793b106498b931dd708a466cf3a6f6a0fMark SalyzynLogStatistics::LogStatistics() : enable(false) {
3397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
3497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizes[id] = 0;
3597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElements[id] = 0;
3658b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        mDroppedElements[id] = 0;
3797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizesTotal[id] = 0;
3897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElementsTotal[id] = 0;
3934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
4034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
4134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
42720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
43720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
44501c373916e292764400dbae735f44b33378400fMark Salyzynsize_t sizesTotal() {
45501c373916e292764400dbae735f44b33378400fMark Salyzyn    return LogStatistics::sizesTotal();
46501c373916e292764400dbae735f44b33378400fMark Salyzyn}
473296291cffd13af13ea9e60a8ac1138101cf8e4cMark Salyzyn
4897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
49501c373916e292764400dbae735f44b33378400fMark Salyzynchar* pidToName(pid_t pid) {
50501c373916e292764400dbae735f44b33378400fMark Salyzyn    char* retval = NULL;
51501c373916e292764400dbae735f44b33378400fMark Salyzyn    if (pid == 0) {  // special case from auditd/klogd for kernel
52ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        retval = strdup("logd");
5397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    } else {
549a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        char buffer[512];
559a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
569a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        int fd = open(buffer, O_RDONLY);
579a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        if (fd >= 0) {
589a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            ssize_t ret = read(fd, buffer, sizeof(buffer));
599a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            if (ret > 0) {
60501c373916e292764400dbae735f44b33378400fMark Salyzyn                buffer[sizeof(buffer) - 1] = '\0';
619a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                // frameworks intermediate state
620eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn                if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
639a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                    retval = strdup(buffer);
649a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                }
659a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            }
669a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            close(fd);
679a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        }
689a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    }
699a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    return retval;
709a03863e88da99ba010342c874252089dd771f7fMark Salyzyn}
71720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
72720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
73501c373916e292764400dbae735f44b33378400fMark Salyzynvoid LogStatistics::add(LogBufferElement* element) {
74758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
75758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
7697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] += size;
7797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    ++mElements[log_id];
7834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
79a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    if (element->getDropped()) {
80a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        ++mDroppedElements[log_id];
81a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    } else {
82a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // When caller adding a chatty entry, they will have already
83a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // called add() and subtract() for each entry as they are
84a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // evaluated and trimmed, thus recording size and number of
85a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // elements, but we must recognize the manufactured dropped
86a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // entry as not contributing to the lifetime totals.
87a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        mSizesTotal[log_id] += size;
883296291cffd13af13ea9e60a8ac1138101cf8e4cMark Salyzyn        SizesTotal += size;
89a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        ++mElementsTotal[log_id];
90a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    }
91720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
92ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    if (log_id == LOG_ID_KERNEL) {
93ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        return;
94ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    }
95ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
96758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].add(element->getUid(), element);
97bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
98bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].add(element->getPid(), element);
99bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
100ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
101720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
102720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
103720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
104720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
105758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.add(element->getPid(), element);
106758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.add(element->getTid(), element);
107344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
108758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uint32_t tag = element->getTag();
109344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (tag) {
110083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        if (log_id == LOG_ID_SECURITY) {
111083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            securityTagTable.add(tag, element);
112083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        } else {
113083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            tagTable.add(tag, element);
114083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        }
115344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
11634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
11734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
118501c373916e292764400dbae735f44b33378400fMark Salyzynvoid LogStatistics::subtract(LogBufferElement* element) {
119758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
120758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
12197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] -= size;
12297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    --mElements[log_id];
12358b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    if (element->getDropped()) {
12458b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mDroppedElements[log_id];
12558b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
12634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
127ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    if (log_id == LOG_ID_KERNEL) {
128ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        return;
129ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    }
130ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
131758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].subtract(element->getUid(), element);
132bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
133bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].subtract(element->getPid(), element);
134bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
13534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
136720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
137720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
13834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
13934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
140758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.subtract(element->getPid(), element);
141758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.subtract(element->getTid(), element);
142344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
143758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uint32_t tag = element->getTag();
144344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (tag) {
145083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        if (log_id == LOG_ID_SECURITY) {
146083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            securityTagTable.subtract(tag, element);
147083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        } else {
148083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            tagTable.subtract(tag, element);
149083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        }
150344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
151c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn}
152c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
153ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// Atomically set an entry to drop
154ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// entry->setDropped(1) must follow this call, caller should do this explicitly.
155501c373916e292764400dbae735f44b33378400fMark Salyzynvoid LogStatistics::drop(LogBufferElement* element) {
156758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
157758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
158ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    mSizes[log_id] -= size;
15958b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    ++mDroppedElements[log_id];
160ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
161758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].drop(element->getUid(), element);
162bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
163bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].drop(element->getPid(), element);
164bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
165ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
166ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    if (!enable) {
167ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        return;
168ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
169ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
170758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.drop(element->getPid(), element);
171758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.drop(element->getTid(), element);
1726a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
1736a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    uint32_t tag = element->getTag();
1746a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    if (tag) {
1756a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        if (log_id == LOG_ID_SECURITY) {
1766a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            securityTagTable.drop(tag, element);
1776a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        } else {
1786a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            tagTable.drop(tag, element);
1796a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        }
1806a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
181ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn}
182ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
18397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
184501c373916e292764400dbae735f44b33378400fMark Salyzynconst char* LogStatistics::uidToName(uid_t uid) const {
18597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Local hard coded favourites
18697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (uid == AID_LOGD) {
18797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        return strdup("auditd");
18834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
18934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
190b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    // Android system
191b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    if (uid < AID_APP) {
192b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        // in bionic, thread safe as long as we copy the results
193501c373916e292764400dbae735f44b33378400fMark Salyzyn        struct passwd* pwd = getpwuid(uid);
194b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        if (pwd) {
195b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn            return strdup(pwd->pw_name);
19634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
19734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
19834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
19908739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    // Parse /data/system/packages.list
200dff44709cf462a3af7eb5770c90e3ada492295b7Jeff Sharkey    uid_t userId = uid % AID_USER_OFFSET;
201501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* name = android::uidToName(userId);
202023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn    if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
203023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn        name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
204023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn    }
20508739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    if (name) {
20608739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn        return name;
20708739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    }
208720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
209b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    // Android application
210b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    if (uid >= AID_APP) {
211501c373916e292764400dbae735f44b33378400fMark Salyzyn        struct passwd* pwd = getpwuid(uid);
212b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        if (pwd) {
213b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn            return strdup(pwd->pw_name);
214b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        }
215b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    }
216b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn
217720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    // report uid -> pid(s) -> pidToName if unique
218501c373916e292764400dbae735f44b33378400fMark Salyzyn    for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
219501c373916e292764400dbae735f44b33378400fMark Salyzyn         ++it) {
220501c373916e292764400dbae735f44b33378400fMark Salyzyn        const PidEntry& entry = it->second;
221720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
222720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        if (entry.getUid() == uid) {
223501c373916e292764400dbae735f44b33378400fMark Salyzyn            const char* nameTmp = entry.getName();
224720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
225758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (nameTmp) {
226720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                if (!name) {
227758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    name = strdup(nameTmp);
2280eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn                } else if (fastcmp<strcmp>(name, nameTmp)) {
229501c373916e292764400dbae735f44b33378400fMark Salyzyn                    free(const_cast<char*>(name));
230023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn                    name = NULL;
231023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn                    break;
232720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
233720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
234720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
235720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
236720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
23797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // No one
238720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    return name;
23934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
24034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
241501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
242758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    bool isprune = worstUidEnabledForLogid(id);
243501c373916e292764400dbae735f44b33378400fMark Salyzyn    return formatLine(android::base::StringPrintf(name.c_str(),
244501c373916e292764400dbae735f44b33378400fMark Salyzyn                                                  android_log_id_to_name(id)),
245758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Size"),
246501c373916e292764400dbae735f44b33378400fMark Salyzyn                      std::string(isprune ? "+/-  Pruned" : "")) +
247501c373916e292764400dbae735f44b33378400fMark Salyzyn           formatLine(std::string("UID   PACKAGE"), std::string("BYTES"),
248758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string(isprune ? "NUM" : ""));
249758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
250758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
251f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn// Helper to truncate name, if too long, and add name dressings
252f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzynstatic void formatTmp(const LogStatistics& stat, const char* nameTmp, uid_t uid,
253f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn                      std::string& name, std::string& size, size_t nameLen) {
254f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    const char* allocNameTmp = nullptr;
255f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    if (!nameTmp) nameTmp = allocNameTmp = stat.uidToName(uid);
256758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
257f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
258f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        size_t len = EntryBaseConstants::total_len -
259f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn                     EntryBaseConstants::pruned_len - size.length() -
260f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn                     name.length() - lenSpace - 2;
261f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        size_t lenNameTmp = strlen(nameTmp);
262f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        while ((len < lenNameTmp) && (lenSpace > 1)) {
263f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn            ++len;
264f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn            --lenSpace;
265f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        }
266f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        name += android::base::StringPrintf("%*s", (int)lenSpace, "");
267f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        if (len < lenNameTmp) {
268f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn            name += "...";
269f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn            nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
270f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        }
271f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        name += nameTmp;
272f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn        free(const_cast<char*>(allocNameTmp));
273758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
274f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn}
275758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
276f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzynstd::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
277f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    uid_t uid = getUid();
278f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    std::string name = android::base::StringPrintf("%u", uid);
279758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string size = android::base::StringPrintf("%zu", getSizes());
280758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
281f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    formatTmp(stat, nullptr, uid, name, size, 6);
282f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn
283758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
284c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn    if (worstUidEnabledForLogid(id)) {
285c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalDropped = 0;
286501c373916e292764400dbae735f44b33378400fMark Salyzyn        for (LogStatistics::uidTable_t::const_iterator it =
287501c373916e292764400dbae735f44b33378400fMark Salyzyn                 stat.uidTable[id].begin();
288501c373916e292764400dbae735f44b33378400fMark Salyzyn             it != stat.uidTable[id].end(); ++it) {
289c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            totalDropped += it->second.getDropped();
290c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
291c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t sizes = stat.sizes(id);
292c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalSize = stat.sizesTotal(id);
293c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalElements = stat.elementsTotal(id);
294501c373916e292764400dbae735f44b33378400fMark Salyzyn        float totalVirtualSize =
295501c373916e292764400dbae735f44b33378400fMark Salyzyn            (float)sizes + (float)totalDropped * totalSize / totalElements;
296c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t entrySize = getSizes();
297c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        float virtualEntrySize = entrySize;
298c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        int realPermille = virtualEntrySize * 1000.0 / sizes;
299c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t dropped = getDropped();
300c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        if (dropped) {
301c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            pruned = android::base::StringPrintf("%zu", dropped);
302c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            virtualEntrySize += (float)dropped * totalSize / totalElements;
303c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
304c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
305501c373916e292764400dbae735f44b33378400fMark Salyzyn        int permille =
306501c373916e292764400dbae735f44b33378400fMark Salyzyn            (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
307c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        if ((permille < -1) || (1 < permille)) {
308c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            std::string change;
309501c373916e292764400dbae735f44b33378400fMark Salyzyn            const char* units = "%";
310501c373916e292764400dbae735f44b33378400fMark Salyzyn            const char* prefix = (permille > 0) ? "+" : "";
311c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn
312c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if (permille > 999) {
313501c373916e292764400dbae735f44b33378400fMark Salyzyn                permille = (permille + 1000) / 100;  // Now tenths fold
314c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                units = "X";
315c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                prefix = "";
316c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
317c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if ((-99 < permille) && (permille < 99)) {
318501c373916e292764400dbae735f44b33378400fMark Salyzyn                change = android::base::StringPrintf(
319501c373916e292764400dbae735f44b33378400fMark Salyzyn                    "%s%d.%u%s", prefix, permille / 10,
320c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    ((permille < 0) ? (-permille % 10) : (permille % 10)),
321c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    units);
322c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            } else {
323501c373916e292764400dbae735f44b33378400fMark Salyzyn                change = android::base::StringPrintf(
324501c373916e292764400dbae735f44b33378400fMark Salyzyn                    "%s%d%s", prefix, (permille + 5) / 10, units);
325c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
326501c373916e292764400dbae735f44b33378400fMark Salyzyn            ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
327501c373916e292764400dbae735f44b33378400fMark Salyzyn                             pruned.length() - change.length();
328c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if ((spaces <= 0) && pruned.length()) {
329c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                spaces = 1;
330c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
331d966e226809bd446bb33651b71d7934887787c1dMark Salyzyn            if (spaces > 0) {
332c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                change += android::base::StringPrintf("%*s", (int)spaces, "");
333c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
334c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            pruned = change + pruned;
335c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
336758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
337758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
338bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    std::string output = formatLine(name, size, pruned);
339bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
340bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (uid != AID_SYSTEM) {
341bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        return output;
342bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
343bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
344bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    static const size_t maximum_sorted_entries = 32;
345501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::unique_ptr<const PidEntry* []> sorted =
346501c373916e292764400dbae735f44b33378400fMark Salyzyn        stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
347bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
348bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (!sorted.get()) {
349bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        return output;
350bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
351bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    std::string byPid;
352bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    size_t index;
353bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    bool hasDropped = false;
354bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    for (index = 0; index < maximum_sorted_entries; ++index) {
355501c373916e292764400dbae735f44b33378400fMark Salyzyn        const PidEntry* entry = sorted[index];
356bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (!entry) {
357bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            break;
358bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
359bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (entry->getSizes() <= (getSizes() / 100)) {
360bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            break;
361bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
362bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (entry->getDropped()) {
363bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            hasDropped = true;
364bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
365bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        byPid += entry->format(stat, id);
366bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
367501c373916e292764400dbae735f44b33378400fMark Salyzyn    if (index > 1) {  // print this only if interesting
368bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        std::string ditto("\" ");
369501c373916e292764400dbae735f44b33378400fMark Salyzyn        output += formatLine(std::string("  PID/UID   COMMAND LINE"), ditto,
370501c373916e292764400dbae735f44b33378400fMark Salyzyn                             hasDropped ? ditto : std::string(""));
371bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        output += byPid;
372bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
373bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
374bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    return output;
375758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
376758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
377501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string PidEntry::formatHeader(const std::string& name,
378501c373916e292764400dbae735f44b33378400fMark Salyzyn                                   log_id_t /* id */) const {
379501c373916e292764400dbae735f44b33378400fMark Salyzyn    return formatLine(name, std::string("Size"), std::string("Pruned")) +
380501c373916e292764400dbae735f44b33378400fMark Salyzyn           formatLine(std::string("  PID/UID   COMMAND LINE"),
381501c373916e292764400dbae735f44b33378400fMark Salyzyn                      std::string("BYTES"), std::string("NUM"));
382758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
383758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
384501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string PidEntry::format(const LogStatistics& stat,
385501c373916e292764400dbae735f44b33378400fMark Salyzyn                             log_id_t /* id */) const {
386758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
387ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    pid_t pid = getPid();
388ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
389501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string size = android::base::StringPrintf("%zu", getSizes());
390758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
391f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    formatTmp(stat, getName(), uid, name, size, 12);
392f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn
393758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
394758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    size_t dropped = getDropped();
395758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (dropped) {
396758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
397758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
398758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
399758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
400758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
401758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
402501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string TidEntry::formatHeader(const std::string& name,
403501c373916e292764400dbae735f44b33378400fMark Salyzyn                                   log_id_t /* id */) const {
404501c373916e292764400dbae735f44b33378400fMark Salyzyn    return formatLine(name, std::string("Size"), std::string("Pruned")) +
405501c373916e292764400dbae735f44b33378400fMark Salyzyn           formatLine(std::string("  TID/UID   COMM"), std::string("BYTES"),
406758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("NUM"));
407758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
408758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
409501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string TidEntry::format(const LogStatistics& stat,
410501c373916e292764400dbae735f44b33378400fMark Salyzyn                             log_id_t /* id */) const {
411758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
412501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
413501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string size = android::base::StringPrintf("%zu", getSizes());
414758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
415f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn    formatTmp(stat, getName(), uid, name, size, 12);
416f31ae3d666f6e723a7dde6734c6d8395f8bcdc11Mark Salyzyn
417758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
418758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    size_t dropped = getDropped();
419758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (dropped) {
420758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
421758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
422758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
423758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
424758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
425758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
426501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
427758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    bool isprune = worstUidEnabledForLogid(id);
428501c373916e292764400dbae735f44b33378400fMark Salyzyn    return formatLine(name, std::string("Size"),
429501c373916e292764400dbae735f44b33378400fMark Salyzyn                      std::string(isprune ? "Prune" : "")) +
430501c373916e292764400dbae735f44b33378400fMark Salyzyn           formatLine(std::string("    TAG/UID   TAGNAME"),
431501c373916e292764400dbae735f44b33378400fMark Salyzyn                      std::string("BYTES"), std::string(isprune ? "NUM" : ""));
432758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
433758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
434501c373916e292764400dbae735f44b33378400fMark Salyzynstd::string TagEntry::format(const LogStatistics& /* stat */,
435501c373916e292764400dbae735f44b33378400fMark Salyzyn                             log_id_t /* id */) const {
436758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name;
437758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
438758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (uid == (uid_t)-1) {
439501c373916e292764400dbae735f44b33378400fMark Salyzyn        name = android::base::StringPrintf("%7u", getKey());
440ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    } else {
441501c373916e292764400dbae735f44b33378400fMark Salyzyn        name = android::base::StringPrintf("%7u/%u", getKey(), uid);
442ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
443501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* nameTmp = getName();
444758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
445758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
446501c373916e292764400dbae735f44b33378400fMark Salyzyn            "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
447758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
448758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
449501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string size = android::base::StringPrintf("%zu", getSizes());
450758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
451758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
4526a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    size_t dropped = getDropped();
4536a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    if (dropped) {
4546a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
4556a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
456758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
457758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
45834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
45934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
460ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzynstd::string LogStatistics::format(uid_t uid, pid_t pid,
461ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                                  unsigned int logMask) const {
4629a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    static const unsigned short spaces_total = 19;
46334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
46497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on total logging, current and for all time
46597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
466decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn    std::string output = "size/num";
46734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t oldLength;
46897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    short spaces = 1;
46934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
47097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
4719af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
47297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
4739af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (spaces < 0) spaces = 0;
474decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn        output += android::base::StringPrintf("%*s%s", spaces, "",
475decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn                                              android_log_id_to_name(id));
47697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
47797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    }
4789af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
4799af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*sTotal", spaces, "");
480c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
4819af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char TotalStr[] = "\nTotal";
4829af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(TotalStr);
4839af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += TotalStr;
484c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
4859af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    size_t totalSize = 0;
4869af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    size_t totalEls = 0;
48797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
4889af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
48997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
4909af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (spaces < 0) spaces = 0;
4919af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t szs = sizesTotal(id);
4929af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        totalSize += szs;
4939af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t els = elementsTotal(id);
4949af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        totalEls += els;
495501c373916e292764400dbae735f44b33378400fMark Salyzyn        output +=
496501c373916e292764400dbae735f44b33378400fMark Salyzyn            android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
49797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
49834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
4999af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
500501c373916e292764400dbae735f44b33378400fMark Salyzyn    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
501501c373916e292764400dbae735f44b33378400fMark Salyzyn                                          totalEls);
50234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
5039af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char NowStr[] = "\nNow";
5049af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(NowStr);
5059af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += NowStr;
50634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
5079af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalSize = 0;
5089af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalEls = 0;
50997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
5109af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
5119af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5129af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t els = elements(id);
5139af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (els) {
5149af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            oldLength = output.length();
5159af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            if (spaces < 0) spaces = 0;
5169af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            size_t szs = sizes(id);
5179af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalSize += szs;
5189af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalEls += els;
519501c373916e292764400dbae735f44b33378400fMark Salyzyn            output +=
520501c373916e292764400dbae735f44b33378400fMark Salyzyn                android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
5219af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            spaces -= output.length() - oldLength;
52234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
5239af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        spaces += spaces_total;
5249af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    }
5259af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
526501c373916e292764400dbae735f44b33378400fMark Salyzyn    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
527501c373916e292764400dbae735f44b33378400fMark Salyzyn                                          totalEls);
5289af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5299af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char OverheadStr[] = "\nOverhead";
5309af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(OverheadStr);
5319af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += OverheadStr;
5329af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5339af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalSize = 0;
5349af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    log_id_for_each(id) {
5359af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
53634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
53797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        size_t els = elements(id);
53834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        if (els) {
53997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            oldLength = output.length();
5409af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            if (spaces < 0) spaces = 0;
5419af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            // estimate the std::list overhead.
5429af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            static const size_t overhead =
5439af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn                ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
544501c373916e292764400dbae735f44b33378400fMark Salyzyn                 -sizeof(uint64_t)) +
5459af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn                sizeof(std::list<LogBufferElement*>);
5469af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            size_t szs = sizes(id) + els * overhead;
5479af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalSize += szs;
5489af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
54997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            spaces -= output.length() - oldLength;
55034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
55134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        spaces += spaces_total;
55234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
5536d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    totalSize += sizeOf();
5549af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
5559af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
55634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
55797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on Chattiest
5588e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
559758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name;
560758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
56197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Chattiest by application (UID)
56297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
5639af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
5648e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
565501c373916e292764400dbae735f44b33378400fMark Salyzyn        name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
566501c373916e292764400dbae735f44b33378400fMark Salyzyn                                 : "Logging for your UID in %s log buffer:";
567ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += uidTable[id].format(*this, uid, pid, name, id);
568720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
56997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
570720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (enable) {
571501c373916e292764400dbae735f44b33378400fMark Salyzyn        name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
572501c373916e292764400dbae735f44b33378400fMark Salyzyn                                           : "Logging for this PID:";
573ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += pidTable.format(*this, uid, pid, name);
574ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest TIDs";
5759af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
576ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
577ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += tidTable.format(*this, uid, pid, name);
57817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
57917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
580344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
581ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest events log buffer TAGs";
5829af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
583ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
584ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
585344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
586344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
587083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
588ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest security log buffer TAGs";
5899af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
590ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
591501c373916e292764400dbae735f44b33378400fMark Salyzyn        output +=
592501c373916e292764400dbae735f44b33378400fMark Salyzyn            securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
593083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    }
594083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn
59573160acc5cb5236b30327569e6b51dbfe73e4a0fMark Salyzyn    return output;
59634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
5974ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn
598720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
599720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
600720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t pidToUid(pid_t pid) {
60197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    char buffer[512];
60297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
603501c373916e292764400dbae735f44b33378400fMark Salyzyn    FILE* fp = fopen(buffer, "r");
60497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (fp) {
60597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        while (fgets(buffer, sizeof(buffer), fp)) {
60697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            int uid;
607c32afdf913f082235b1e66f5a57678c7f0723129Mark Salyzyn            if (sscanf(buffer, "Uid: %d", &uid) == 1) {
60897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                fclose(fp);
60997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                return uid;
6104ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn            }
6114ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn        }
61297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        fclose(fp);
6134ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn    }
614501c373916e292764400dbae735f44b33378400fMark Salyzyn    return AID_LOGD;  // associate this with the logger
6154ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn}
616720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
617720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
618720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t LogStatistics::pidToUid(pid_t pid) {
619511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    return pidTable.add(pid)->second.getUid();
620720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
621720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
622720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn// caller must free character string
623501c373916e292764400dbae735f44b33378400fMark Salyzynconst char* LogStatistics::pidToName(pid_t pid) const {
624758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    // An inconvenient truth ... getName() can alter the object
625501c373916e292764400dbae735f44b33378400fMark Salyzyn    pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
626501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* name = writablePidTable.add(pid)->second.getName();
62781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    if (!name) {
62881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        return NULL;
629720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
63081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    return strdup(name);
631720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
632