LogStatistics.cpp revision 81b3eabc49736b89c4f99940f79785074955eaa5
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
1797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <algorithm> // std::max
189a03863e88da99ba010342c874252089dd771f7fMark Salyzyn#include <fcntl.h>
1997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <stdio.h>
2097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <string.h>
2197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <unistd.h>
2234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <log/logger.h>
2434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <private/android_filesystem_config.h>
2534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <utils/String8.h>
2634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
2734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include "LogStatistics.h"
2834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
29720f6d1d55d936d98cc9752e96f479e03e6d5009Mark SalyzynLogStatistics::LogStatistics()
30720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        : enable(false) {
3197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
3297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizes[id] = 0;
3397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElements[id] = 0;
3497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizesTotal[id] = 0;
3597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElementsTotal[id] = 0;
3634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
3734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
3834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
39720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
40720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
4197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
4281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynchar *pidToName(pid_t pid) {
439a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    char *retval = NULL;
44df5aa61f05ccbef441cf8b024d4bbc1b717451f9Mark Salyzyn    if (pid == 0) { // special case from auditd for kernel
45df5aa61f05ccbef441cf8b024d4bbc1b717451f9Mark Salyzyn        retval = strdup("logd.auditd");
4697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    } else {
479a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        char buffer[512];
489a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
499a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        int fd = open(buffer, O_RDONLY);
509a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        if (fd >= 0) {
519a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            ssize_t ret = read(fd, buffer, sizeof(buffer));
529a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            if (ret > 0) {
539a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                buffer[sizeof(buffer)-1] = '\0';
549a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                // frameworks intermediate state
559a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                if (strcmp(buffer, "<pre-initialized>")) {
569a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                    retval = strdup(buffer);
579a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                }
589a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            }
599a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            close(fd);
609a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        }
619a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    }
629a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    return retval;
639a03863e88da99ba010342c874252089dd771f7fMark Salyzyn}
649a03863e88da99ba010342c874252089dd771f7fMark Salyzyn
65720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
66720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
6797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::add(LogBufferElement *e) {
6897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_t log_id = e->getLogId();
6997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    unsigned short size = e->getMsgLen();
7097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] += size;
7197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    ++mElements[log_id];
7234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
7381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    uidTable[log_id].add(e->getUid(), e);
74c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
7597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizesTotal[log_id] += size;
7697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    ++mElementsTotal[log_id];
77720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
78720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
79720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
80720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
81720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
8281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    pidTable.add(e->getPid(), e);
8334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
8434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
8597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::subtract(LogBufferElement *e) {
8697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_t log_id = e->getLogId();
8797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    unsigned short size = e->getMsgLen();
8897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] -= size;
8997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    --mElements[log_id];
9034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
9181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    uidTable[log_id].subtract(e->getUid(), e);
9234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
93720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
94720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
9534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
9634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
9781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    pidTable.subtract(e->getPid(), e);
98c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn}
99c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
100ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// Atomically set an entry to drop
101ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// entry->setDropped(1) must follow this call, caller should do this explicitly.
102ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzynvoid LogStatistics::drop(LogBufferElement *e) {
103ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    log_id_t log_id = e->getLogId();
104ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    unsigned short size = e->getMsgLen();
105ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    mSizes[log_id] -= size;
106ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
10781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    uidTable[log_id].drop(e->getUid(), e);
108ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
109ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    if (!enable) {
110ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        return;
111ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
112ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
11381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    pidTable.drop(e->getPid(), e);
114ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn}
115ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
11697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
11797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynchar *LogStatistics::uidToName(uid_t uid) {
11897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Local hard coded favourites
11997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (uid == AID_LOGD) {
12097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        return strdup("auditd");
12134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
12234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
12397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Android hard coded
12497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    const struct android_id_info *info = android_ids;
12534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
12697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    for (size_t i = 0; i < android_id_count; ++i) {
12797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (info->aid == uid) {
12897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            return strdup(info->name);
12934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
13097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        ++info;
13134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
13234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
13308739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    // Parse /data/system/packages.list
13408739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    char *name = android::uidToName(uid);
13508739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    if (name) {
13608739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn        return name;
13708739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    }
138720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
139720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    // report uid -> pid(s) -> pidToName if unique
140720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    ssize_t index = -1;
141720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    while ((index = pidTable.next(index)) != -1) {
142720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        const PidEntry &entry = pidTable.entryAt(index);
143720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
144720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        if (entry.getUid() == uid) {
145720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            const char *n = entry.getName();
146720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
147720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            if (n) {
148720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                if (!name) {
149720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                    name = strdup(n);
150720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                } else if (strcmp(name, n)) {
151720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                    free(name);
152720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                    return NULL;
153720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
154720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
155720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
156720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
157720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
15897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // No one
159720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    return name;
16034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
16134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
16297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynstatic void format_line(android::String8 &output,
163ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        android::String8 &name, android::String8 &size, android::String8 &pruned) {
164ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    static const size_t pruned_len = 6;
165ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    static const size_t total_len = 70 + pruned_len;
166ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
167ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    ssize_t drop_len = std::max(pruned.length() + 1, pruned_len);
168ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    ssize_t size_len = std::max(size.length() + 1,
169ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                                total_len - name.length() - drop_len - 1);
170ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
171ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    if (pruned.length()) {
172ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        output.appendFormat("%s%*s%*s\n", name.string(),
173ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                                          (int)size_len, size.string(),
174ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                                          (int)drop_len, pruned.string());
175ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    } else {
176ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        output.appendFormat("%s%*s\n", name.string(),
177ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                                       (int)size_len, size.string());
178ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
17934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
18034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
18197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzynvoid LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) {
1829a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    static const unsigned short spaces_total = 19;
18334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
18434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    if (*buf) {
185239605ef64d34ced82c97870e3f3f5c4145be58cGreg Hackmann        free(*buf);
18634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        *buf = NULL;
18734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
18834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
18997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on total logging, current and for all time
19097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
19197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    android::String8 output("size/num");
19234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t oldLength;
19397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    short spaces = 1;
19434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
19597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
19697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (!(logMask & (1 << id))) {
197c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn            continue;
198c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn        }
19997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
200c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn        if (spaces < 0) {
201c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn            spaces = 0;
202c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn        }
20397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        output.appendFormat("%*s%s", spaces, "", android_log_id_to_name(id));
20497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
20597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    }
206c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
20797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    spaces = 4;
20897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    output.appendFormat("\nTotal");
209c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
21097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
21197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (!(logMask & (1 << id))) {
21297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            continue;
21334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
21497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
21597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (spaces < 0) {
21697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            spaces = 0;
217e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn        }
21897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        output.appendFormat("%*s%zu/%zu", spaces, "",
21997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                            sizesTotal(id), elementsTotal(id));
22097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
22134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
22234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
22397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    spaces = 6;
22497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    output.appendFormat("\nNow");
22534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
22697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
22797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (!(logMask & (1 << id))) {
22834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn            continue;
22934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
23034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
23197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        size_t els = elements(id);
23234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        if (els) {
23397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            oldLength = output.length();
234e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn            if (spaces < 0) {
235e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn                spaces = 0;
236e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn            }
23797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            output.appendFormat("%*s%zu/%zu", spaces, "", sizes(id), els);
23897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            spaces -= output.length() - oldLength;
23934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
24034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        spaces += spaces_total;
24134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
24234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
24397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on Chattiest
2448e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
24597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Chattiest by application (UID)
246720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    static const size_t maximum_sorted_entries = 32;
24797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
24897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        if (!(logMask & (1 << id))) {
2498e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn            continue;
2508e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn        }
2518e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
252720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        bool headerPrinted = false;
253720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        std::unique_ptr<const UidEntry *[]> sorted = sort(maximum_sorted_entries, id);
254720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        ssize_t index = -1;
255720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        while ((index = uidTable_t::next(index, sorted, maximum_sorted_entries)) >= 0) {
25697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            const UidEntry *entry = sorted[index];
25797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            uid_t u = entry->getKey();
25897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            if ((uid != AID_ROOT) && (u != uid)) {
25934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn                continue;
26034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn            }
26134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
262720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            if (!headerPrinted) {
2635720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                output.appendFormat("\n\n");
2645720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                android::String8 name("");
26597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                if (uid == AID_ROOT) {
2665720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                    name.appendFormat(
2675720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                        "Chattiest UIDs in %s log buffer:",
26897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                        android_log_id_to_name(id));
26997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                } else {
2705720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                    name.appendFormat(
2715720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                        "Logging for your UID in %s log buffer:",
27297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                        android_log_id_to_name(id));
273e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn                }
274ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                android::String8 size("Size");
275ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                android::String8 pruned("Pruned");
276ae769238391f7f9fa5c03a436d5f1fd73130e6bdMark Salyzyn                if (!worstUidEnabledForLogid(id)) {
277ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                    pruned.setTo("");
278ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                }
279ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                format_line(output, name, size, pruned);
2805720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn
2815720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                name.setTo("UID   PACKAGE");
2825720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                size.setTo("BYTES");
2835720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                pruned.setTo("LINES");
2845720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                if (!worstUidEnabledForLogid(id)) {
2855720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                    pruned.setTo("");
2865720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                }
2875720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                format_line(output, name, size, pruned);
2885720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn
289720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                headerPrinted = true;
29034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn            }
29134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
29297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            android::String8 name("");
29397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            name.appendFormat("%u", u);
29497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            char *n = uidToName(u);
29597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            if (n) {
29697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                name.appendFormat("%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n);
29797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                free(n);
29834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn            }
29934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
30097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            android::String8 size("");
301720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            size.appendFormat("%zu", entry->getSizes());
30234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
303ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            android::String8 pruned("");
304ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            size_t dropped = entry->getDropped();
305ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            if (dropped) {
306ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                pruned.appendFormat("%zu", dropped);
307ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            }
308ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
309ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            format_line(output, name, size, pruned);
31034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
311720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
31297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
313720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (enable) {
31481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        // Pid table
315720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        bool headerPrinted = false;
316720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries);
317720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        ssize_t index = -1;
318720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        while ((index = pidTable.next(index, sorted, maximum_sorted_entries)) >= 0) {
319720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            const PidEntry *entry = sorted[index];
320720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            uid_t u = entry->getUid();
321720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            if ((uid != AID_ROOT) && (u != uid)) {
322720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                continue;
323720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
324720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
325720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            if (!headerPrinted) {
3265720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                output.appendFormat("\n\n");
3275720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                android::String8 name("");
328720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                if (uid == AID_ROOT) {
3295720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                    name.appendFormat("Chattiest PIDs:");
330720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                } else {
3315720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                    name.appendFormat("Logging for this PID:");
332720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
333720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                android::String8 size("Size");
334ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                android::String8 pruned("Pruned");
335ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                format_line(output, name, size, pruned);
3365720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn
3375720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                name.setTo("  PID/UID   COMMAND LINE");
3385720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                size.setTo("BYTES");
3395720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                pruned.setTo("LINES");
3405720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn                format_line(output, name, size, pruned);
3415720d2c168f17afb57eefb6ed762a120a24c8ecbMark Salyzyn
342720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                headerPrinted = true;
343720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
344720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
345720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            android::String8 name("");
346720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            name.appendFormat("%5u/%u", entry->getKey(), u);
347720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            const char *n = entry->getName();
348720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            if (n) {
349720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n);
350720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            } else {
351720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                char *un = uidToName(u);
352720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                if (un) {
353720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                    name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un);
354720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                    free(un);
355720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
356720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
357720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
358720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            android::String8 size("");
359720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            size.appendFormat("%zu", entry->getSizes());
360720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
361ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            android::String8 pruned("");
362ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            size_t dropped = entry->getDropped();
363ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            if (dropped) {
364ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn                pruned.appendFormat("%zu", dropped);
365ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            }
366ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
367ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn            format_line(output, name, size, pruned);
368720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
36934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
37034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
37197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    *buf = strdup(output.string());
37234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
3734ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn
374720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
375720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
376720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t pidToUid(pid_t pid) {
37797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    char buffer[512];
37897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
37997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    FILE *fp = fopen(buffer, "r");
38097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (fp) {
38197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        while (fgets(buffer, sizeof(buffer), fp)) {
38297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            int uid;
383c32afdf913f082235b1e66f5a57678c7f0723129Mark Salyzyn            if (sscanf(buffer, "Uid: %d", &uid) == 1) {
38497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                fclose(fp);
38597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                return uid;
3864ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn            }
3874ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn        }
38897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        fclose(fp);
3894ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn    }
390e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    return AID_LOGD; // associate this with the logger
3914ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn}
392720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
393720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
394720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
395720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t LogStatistics::pidToUid(pid_t pid) {
39681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    return pidTable.entryAt(pidTable.add(pid)).getUid();
397720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
398720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
399720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn// caller must free character string
400720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynchar *LogStatistics::pidToName(pid_t pid) {
40181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    const char *name = pidTable.entryAt(pidTable.add(pid)).getName();
40281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    if (!name) {
40381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        return NULL;
404720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
40581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    return strdup(name);
406720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
407