1*598139dcSAndroid Build Coastguard Worker /* 2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*598139dcSAndroid Build Coastguard Worker * 4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*598139dcSAndroid Build Coastguard Worker * 8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*598139dcSAndroid Build Coastguard Worker * 10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*598139dcSAndroid Build Coastguard Worker * limitations under the License. 15*598139dcSAndroid Build Coastguard Worker */ 16*598139dcSAndroid Build Coastguard Worker 17*598139dcSAndroid Build Coastguard Worker #pragma once 18*598139dcSAndroid Build Coastguard Worker 19*598139dcSAndroid Build Coastguard Worker #include <ctype.h> 20*598139dcSAndroid Build Coastguard Worker #include <inttypes.h> 21*598139dcSAndroid Build Coastguard Worker #include <stdint.h> 22*598139dcSAndroid Build Coastguard Worker #include <stdlib.h> 23*598139dcSAndroid Build Coastguard Worker #include <string.h> 24*598139dcSAndroid Build Coastguard Worker #include <sys/types.h> 25*598139dcSAndroid Build Coastguard Worker 26*598139dcSAndroid Build Coastguard Worker #include <algorithm> // std::max 27*598139dcSAndroid Build Coastguard Worker #include <array> 28*598139dcSAndroid Build Coastguard Worker #include <memory> 29*598139dcSAndroid Build Coastguard Worker #include <mutex> 30*598139dcSAndroid Build Coastguard Worker #include <string> 31*598139dcSAndroid Build Coastguard Worker #include <string_view> 32*598139dcSAndroid Build Coastguard Worker #include <unordered_map> 33*598139dcSAndroid Build Coastguard Worker 34*598139dcSAndroid Build Coastguard Worker #include <android-base/stringprintf.h> 35*598139dcSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h> 36*598139dcSAndroid Build Coastguard Worker #include <android/log.h> 37*598139dcSAndroid Build Coastguard Worker #include <log/log_time.h> 38*598139dcSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h> 39*598139dcSAndroid Build Coastguard Worker #include <utils/FastStrcmp.h> 40*598139dcSAndroid Build Coastguard Worker 41*598139dcSAndroid Build Coastguard Worker #include "LogUtils.h" 42*598139dcSAndroid Build Coastguard Worker 43*598139dcSAndroid Build Coastguard Worker #define log_id_for_each(i) \ 44*598139dcSAndroid Build Coastguard Worker for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1)) 45*598139dcSAndroid Build Coastguard Worker 46*598139dcSAndroid Build Coastguard Worker class LogStatistics; 47*598139dcSAndroid Build Coastguard Worker class UidEntry; 48*598139dcSAndroid Build Coastguard Worker class PidEntry; 49*598139dcSAndroid Build Coastguard Worker 50*598139dcSAndroid Build Coastguard Worker struct LogStatisticsElement { 51*598139dcSAndroid Build Coastguard Worker uid_t uid; 52*598139dcSAndroid Build Coastguard Worker pid_t pid; 53*598139dcSAndroid Build Coastguard Worker pid_t tid; 54*598139dcSAndroid Build Coastguard Worker uint32_t tag; 55*598139dcSAndroid Build Coastguard Worker log_time realtime; 56*598139dcSAndroid Build Coastguard Worker const char* msg; 57*598139dcSAndroid Build Coastguard Worker uint16_t msg_len; 58*598139dcSAndroid Build Coastguard Worker log_id_t log_id; 59*598139dcSAndroid Build Coastguard Worker uint16_t total_len; 60*598139dcSAndroid Build Coastguard Worker }; 61*598139dcSAndroid Build Coastguard Worker 62*598139dcSAndroid Build Coastguard Worker template <typename TKey, typename TEntry> 63*598139dcSAndroid Build Coastguard Worker class LogHashtable { 64*598139dcSAndroid Build Coastguard Worker std::unordered_map<TKey, TEntry> map; 65*598139dcSAndroid Build Coastguard Worker bucket_size()66*598139dcSAndroid Build Coastguard Worker size_t bucket_size() const { 67*598139dcSAndroid Build Coastguard Worker size_t count = 0; 68*598139dcSAndroid Build Coastguard Worker for (size_t idx = 0; idx < map.bucket_count(); ++idx) { 69*598139dcSAndroid Build Coastguard Worker size_t bucket_size = map.bucket_size(idx); 70*598139dcSAndroid Build Coastguard Worker if (bucket_size == 0) bucket_size = 1; 71*598139dcSAndroid Build Coastguard Worker count += bucket_size; 72*598139dcSAndroid Build Coastguard Worker } 73*598139dcSAndroid Build Coastguard Worker float load_factor = map.max_load_factor(); 74*598139dcSAndroid Build Coastguard Worker if (load_factor < 1.0) return count; 75*598139dcSAndroid Build Coastguard Worker return count * load_factor; 76*598139dcSAndroid Build Coastguard Worker } 77*598139dcSAndroid Build Coastguard Worker 78*598139dcSAndroid Build Coastguard Worker static const size_t unordered_map_per_entry_overhead = sizeof(void*); 79*598139dcSAndroid Build Coastguard Worker static const size_t unordered_map_bucket_overhead = sizeof(void*); 80*598139dcSAndroid Build Coastguard Worker 81*598139dcSAndroid Build Coastguard Worker public: size()82*598139dcSAndroid Build Coastguard Worker size_t size() const { 83*598139dcSAndroid Build Coastguard Worker return map.size(); 84*598139dcSAndroid Build Coastguard Worker } 85*598139dcSAndroid Build Coastguard Worker 86*598139dcSAndroid Build Coastguard Worker // Estimate unordered_map memory usage. sizeOf()87*598139dcSAndroid Build Coastguard Worker size_t sizeOf() const { 88*598139dcSAndroid Build Coastguard Worker return sizeof(*this) + 89*598139dcSAndroid Build Coastguard Worker (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) + 90*598139dcSAndroid Build Coastguard Worker (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead); 91*598139dcSAndroid Build Coastguard Worker } 92*598139dcSAndroid Build Coastguard Worker 93*598139dcSAndroid Build Coastguard Worker typedef typename std::unordered_map<TKey, TEntry>::iterator iterator; 94*598139dcSAndroid Build Coastguard Worker typedef 95*598139dcSAndroid Build Coastguard Worker typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator; 96*598139dcSAndroid Build Coastguard Worker 97*598139dcSAndroid Build Coastguard Worker // Returns a sorted array of up to len highest entries sorted by size. If fewer than len 98*598139dcSAndroid Build Coastguard Worker // entries are found, their positions are set to nullptr. 99*598139dcSAndroid Build Coastguard Worker template <size_t len> MaxEntries(uid_t uid,pid_t pid,std::array<const TKey *,len> & out_keys,std::array<const TEntry *,len> & out_entries)100*598139dcSAndroid Build Coastguard Worker void MaxEntries(uid_t uid, pid_t pid, std::array<const TKey*, len>& out_keys, 101*598139dcSAndroid Build Coastguard Worker std::array<const TEntry*, len>& out_entries) const { 102*598139dcSAndroid Build Coastguard Worker out_keys.fill(nullptr); 103*598139dcSAndroid Build Coastguard Worker out_entries.fill(nullptr); 104*598139dcSAndroid Build Coastguard Worker for (const auto& [key, entry] : map) { 105*598139dcSAndroid Build Coastguard Worker uid_t entry_uid = 0; 106*598139dcSAndroid Build Coastguard Worker if constexpr (std::is_same_v<TEntry, UidEntry>) { 107*598139dcSAndroid Build Coastguard Worker entry_uid = key; 108*598139dcSAndroid Build Coastguard Worker } else { 109*598139dcSAndroid Build Coastguard Worker entry_uid = entry.uid(); 110*598139dcSAndroid Build Coastguard Worker } 111*598139dcSAndroid Build Coastguard Worker if (uid != AID_ROOT && uid != entry_uid) { 112*598139dcSAndroid Build Coastguard Worker continue; 113*598139dcSAndroid Build Coastguard Worker } 114*598139dcSAndroid Build Coastguard Worker pid_t entry_pid = 0; 115*598139dcSAndroid Build Coastguard Worker if constexpr (std::is_same_v<TEntry, PidEntry>) { 116*598139dcSAndroid Build Coastguard Worker entry_pid = key; 117*598139dcSAndroid Build Coastguard Worker } else { 118*598139dcSAndroid Build Coastguard Worker entry_pid = entry.pid(); 119*598139dcSAndroid Build Coastguard Worker } 120*598139dcSAndroid Build Coastguard Worker if (pid && entry_pid && pid != entry_pid) { 121*598139dcSAndroid Build Coastguard Worker continue; 122*598139dcSAndroid Build Coastguard Worker } 123*598139dcSAndroid Build Coastguard Worker 124*598139dcSAndroid Build Coastguard Worker size_t sizes = entry.getSizes(); 125*598139dcSAndroid Build Coastguard Worker ssize_t index = len - 1; 126*598139dcSAndroid Build Coastguard Worker while ((!out_entries[index] || sizes > out_entries[index]->getSizes()) && --index >= 0) 127*598139dcSAndroid Build Coastguard Worker ; 128*598139dcSAndroid Build Coastguard Worker if (++index < (ssize_t)len) { 129*598139dcSAndroid Build Coastguard Worker size_t num = len - index - 1; 130*598139dcSAndroid Build Coastguard Worker if (num) { 131*598139dcSAndroid Build Coastguard Worker memmove(&out_keys[index + 1], &out_keys[index], num * sizeof(const TKey*)); 132*598139dcSAndroid Build Coastguard Worker memmove(&out_entries[index + 1], &out_entries[index], 133*598139dcSAndroid Build Coastguard Worker num * sizeof(const TEntry*)); 134*598139dcSAndroid Build Coastguard Worker } 135*598139dcSAndroid Build Coastguard Worker out_keys[index] = &key; 136*598139dcSAndroid Build Coastguard Worker out_entries[index] = &entry; 137*598139dcSAndroid Build Coastguard Worker } 138*598139dcSAndroid Build Coastguard Worker } 139*598139dcSAndroid Build Coastguard Worker } 140*598139dcSAndroid Build Coastguard Worker Add(const TKey & key,const LogStatisticsElement & element)141*598139dcSAndroid Build Coastguard Worker iterator Add(const TKey& key, const LogStatisticsElement& element) { 142*598139dcSAndroid Build Coastguard Worker iterator it = map.find(key); 143*598139dcSAndroid Build Coastguard Worker if (it == map.end()) { 144*598139dcSAndroid Build Coastguard Worker it = map.insert(std::make_pair(key, TEntry(element))).first; 145*598139dcSAndroid Build Coastguard Worker } else { 146*598139dcSAndroid Build Coastguard Worker it->second.Add(element); 147*598139dcSAndroid Build Coastguard Worker } 148*598139dcSAndroid Build Coastguard Worker return it; 149*598139dcSAndroid Build Coastguard Worker } 150*598139dcSAndroid Build Coastguard Worker Add(const TKey & key)151*598139dcSAndroid Build Coastguard Worker iterator Add(const TKey& key) { 152*598139dcSAndroid Build Coastguard Worker iterator it = map.find(key); 153*598139dcSAndroid Build Coastguard Worker if (it == map.end()) { 154*598139dcSAndroid Build Coastguard Worker it = map.insert(std::make_pair(key, TEntry(key))).first; 155*598139dcSAndroid Build Coastguard Worker } else { 156*598139dcSAndroid Build Coastguard Worker it->second.Add(key); 157*598139dcSAndroid Build Coastguard Worker } 158*598139dcSAndroid Build Coastguard Worker return it; 159*598139dcSAndroid Build Coastguard Worker } 160*598139dcSAndroid Build Coastguard Worker Subtract(const TKey & key,const LogStatisticsElement & element)161*598139dcSAndroid Build Coastguard Worker void Subtract(const TKey& key, const LogStatisticsElement& element) { 162*598139dcSAndroid Build Coastguard Worker iterator it = map.find(key); 163*598139dcSAndroid Build Coastguard Worker if (it != map.end() && it->second.Subtract(element)) { 164*598139dcSAndroid Build Coastguard Worker map.erase(it); 165*598139dcSAndroid Build Coastguard Worker } 166*598139dcSAndroid Build Coastguard Worker } 167*598139dcSAndroid Build Coastguard Worker Drop(const TKey & key,const LogStatisticsElement & element)168*598139dcSAndroid Build Coastguard Worker void Drop(const TKey& key, const LogStatisticsElement& element) { 169*598139dcSAndroid Build Coastguard Worker iterator it = map.find(key); 170*598139dcSAndroid Build Coastguard Worker if (it != map.end()) { 171*598139dcSAndroid Build Coastguard Worker it->second.Drop(element); 172*598139dcSAndroid Build Coastguard Worker } 173*598139dcSAndroid Build Coastguard Worker } 174*598139dcSAndroid Build Coastguard Worker Erase(const TKey & key,const LogStatisticsElement & element)175*598139dcSAndroid Build Coastguard Worker void Erase(const TKey& key, const LogStatisticsElement& element) { 176*598139dcSAndroid Build Coastguard Worker iterator it = map.find(key); 177*598139dcSAndroid Build Coastguard Worker if (it != map.end()) { 178*598139dcSAndroid Build Coastguard Worker it->second.Erase(element); 179*598139dcSAndroid Build Coastguard Worker } 180*598139dcSAndroid Build Coastguard Worker } 181*598139dcSAndroid Build Coastguard Worker begin()182*598139dcSAndroid Build Coastguard Worker iterator begin() { return map.begin(); } begin()183*598139dcSAndroid Build Coastguard Worker const_iterator begin() const { return map.begin(); } end()184*598139dcSAndroid Build Coastguard Worker iterator end() { return map.end(); } end()185*598139dcSAndroid Build Coastguard Worker const_iterator end() const { return map.end(); } 186*598139dcSAndroid Build Coastguard Worker }; 187*598139dcSAndroid Build Coastguard Worker 188*598139dcSAndroid Build Coastguard Worker class EntryBase { 189*598139dcSAndroid Build Coastguard Worker public: EntryBase()190*598139dcSAndroid Build Coastguard Worker EntryBase() : size_(0) {} EntryBase(const LogStatisticsElement & element)191*598139dcSAndroid Build Coastguard Worker explicit EntryBase(const LogStatisticsElement& element) : size_(element.total_len) {} 192*598139dcSAndroid Build Coastguard Worker getSizes()193*598139dcSAndroid Build Coastguard Worker size_t getSizes() const { return size_; } 194*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)195*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { size_ += element.total_len; } Subtract(const LogStatisticsElement & element)196*598139dcSAndroid Build Coastguard Worker bool Subtract(const LogStatisticsElement& element) { 197*598139dcSAndroid Build Coastguard Worker size_ -= element.total_len; 198*598139dcSAndroid Build Coastguard Worker return size_ == 0; 199*598139dcSAndroid Build Coastguard Worker } Drop(const LogStatisticsElement & element)200*598139dcSAndroid Build Coastguard Worker void Drop(const LogStatisticsElement& element) { size_ -= element.msg_len; } Erase(const LogStatisticsElement & element)201*598139dcSAndroid Build Coastguard Worker void Erase(const LogStatisticsElement& element) { size_ -= element.total_len; } 202*598139dcSAndroid Build Coastguard Worker 203*598139dcSAndroid Build Coastguard Worker static constexpr size_t PRUNED_LEN = 14; 204*598139dcSAndroid Build Coastguard Worker static constexpr size_t TOTAL_LEN = 80; 205*598139dcSAndroid Build Coastguard Worker formatLine(const std::string & name,const std::string & size,const std::string & pruned)206*598139dcSAndroid Build Coastguard Worker static std::string formatLine(const std::string& name, 207*598139dcSAndroid Build Coastguard Worker const std::string& size, 208*598139dcSAndroid Build Coastguard Worker const std::string& pruned) { 209*598139dcSAndroid Build Coastguard Worker ssize_t drop_len = std::max(pruned.length() + 1, PRUNED_LEN); 210*598139dcSAndroid Build Coastguard Worker ssize_t size_len = std::max(size.length() + 1, TOTAL_LEN - name.length() - drop_len - 1); 211*598139dcSAndroid Build Coastguard Worker 212*598139dcSAndroid Build Coastguard Worker std::string ret = android::base::StringPrintf( 213*598139dcSAndroid Build Coastguard Worker "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(), 214*598139dcSAndroid Build Coastguard Worker (int)drop_len, pruned.c_str()); 215*598139dcSAndroid Build Coastguard Worker // remove any trailing spaces 216*598139dcSAndroid Build Coastguard Worker size_t pos = ret.size(); 217*598139dcSAndroid Build Coastguard Worker size_t len = 0; 218*598139dcSAndroid Build Coastguard Worker while (pos && isspace(ret[--pos])) ++len; 219*598139dcSAndroid Build Coastguard Worker if (len) ret.erase(pos + 1, len); 220*598139dcSAndroid Build Coastguard Worker return ret + "\n"; 221*598139dcSAndroid Build Coastguard Worker } 222*598139dcSAndroid Build Coastguard Worker 223*598139dcSAndroid Build Coastguard Worker private: 224*598139dcSAndroid Build Coastguard Worker size_t size_; 225*598139dcSAndroid Build Coastguard Worker }; 226*598139dcSAndroid Build Coastguard Worker 227*598139dcSAndroid Build Coastguard Worker class UidEntry : public EntryBase { 228*598139dcSAndroid Build Coastguard Worker public: UidEntry(const LogStatisticsElement & element)229*598139dcSAndroid Build Coastguard Worker explicit UidEntry(const LogStatisticsElement& element) 230*598139dcSAndroid Build Coastguard Worker : EntryBase(element), pid_(element.pid) {} 231*598139dcSAndroid Build Coastguard Worker pid()232*598139dcSAndroid Build Coastguard Worker pid_t pid() const { return pid_; } 233*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)234*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { 235*598139dcSAndroid Build Coastguard Worker if (pid_ != element.pid) { 236*598139dcSAndroid Build Coastguard Worker pid_ = -1; 237*598139dcSAndroid Build Coastguard Worker } 238*598139dcSAndroid Build Coastguard Worker EntryBase::Add(element); 239*598139dcSAndroid Build Coastguard Worker } 240*598139dcSAndroid Build Coastguard Worker 241*598139dcSAndroid Build Coastguard Worker std::string formatHeader(const std::string& name, log_id_t id) const; 242*598139dcSAndroid Build Coastguard Worker std::string format(const LogStatistics& stat, log_id_t id, uid_t uid) const; 243*598139dcSAndroid Build Coastguard Worker 244*598139dcSAndroid Build Coastguard Worker private: 245*598139dcSAndroid Build Coastguard Worker pid_t pid_; 246*598139dcSAndroid Build Coastguard Worker }; 247*598139dcSAndroid Build Coastguard Worker 248*598139dcSAndroid Build Coastguard Worker namespace android { 249*598139dcSAndroid Build Coastguard Worker uid_t pidToUid(pid_t pid); 250*598139dcSAndroid Build Coastguard Worker } 251*598139dcSAndroid Build Coastguard Worker 252*598139dcSAndroid Build Coastguard Worker class PidEntry : public EntryBase { 253*598139dcSAndroid Build Coastguard Worker public: PidEntry(pid_t pid)254*598139dcSAndroid Build Coastguard Worker explicit PidEntry(pid_t pid) 255*598139dcSAndroid Build Coastguard Worker : EntryBase(), uid_(android::pidToUid(pid)), name_(android::pidToName(pid)) {} PidEntry(const LogStatisticsElement & element)256*598139dcSAndroid Build Coastguard Worker explicit PidEntry(const LogStatisticsElement& element) 257*598139dcSAndroid Build Coastguard Worker : EntryBase(element), uid_(element.uid), name_(android::pidToName(element.pid)) {} PidEntry(const PidEntry & element)258*598139dcSAndroid Build Coastguard Worker PidEntry(const PidEntry& element) 259*598139dcSAndroid Build Coastguard Worker : EntryBase(element), 260*598139dcSAndroid Build Coastguard Worker uid_(element.uid_), 261*598139dcSAndroid Build Coastguard Worker name_(element.name_ ? strdup(element.name_) : nullptr) {} ~PidEntry()262*598139dcSAndroid Build Coastguard Worker ~PidEntry() { free(name_); } 263*598139dcSAndroid Build Coastguard Worker uid()264*598139dcSAndroid Build Coastguard Worker uid_t uid() const { return uid_; } name()265*598139dcSAndroid Build Coastguard Worker const char* name() const { return name_; } 266*598139dcSAndroid Build Coastguard Worker Add(pid_t new_pid)267*598139dcSAndroid Build Coastguard Worker void Add(pid_t new_pid) { 268*598139dcSAndroid Build Coastguard Worker if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) { 269*598139dcSAndroid Build Coastguard Worker free(name_); 270*598139dcSAndroid Build Coastguard Worker name_ = nullptr; 271*598139dcSAndroid Build Coastguard Worker } 272*598139dcSAndroid Build Coastguard Worker if (!name_) { 273*598139dcSAndroid Build Coastguard Worker name_ = android::pidToName(new_pid); 274*598139dcSAndroid Build Coastguard Worker } 275*598139dcSAndroid Build Coastguard Worker } 276*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)277*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { 278*598139dcSAndroid Build Coastguard Worker uid_t incoming_uid = element.uid; 279*598139dcSAndroid Build Coastguard Worker if (uid() != incoming_uid) { 280*598139dcSAndroid Build Coastguard Worker uid_ = incoming_uid; 281*598139dcSAndroid Build Coastguard Worker free(name_); 282*598139dcSAndroid Build Coastguard Worker name_ = android::pidToName(element.pid); 283*598139dcSAndroid Build Coastguard Worker } else { 284*598139dcSAndroid Build Coastguard Worker Add(element.pid); 285*598139dcSAndroid Build Coastguard Worker } 286*598139dcSAndroid Build Coastguard Worker EntryBase::Add(element); 287*598139dcSAndroid Build Coastguard Worker } 288*598139dcSAndroid Build Coastguard Worker 289*598139dcSAndroid Build Coastguard Worker std::string formatHeader(const std::string& name, log_id_t id) const; 290*598139dcSAndroid Build Coastguard Worker std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const; 291*598139dcSAndroid Build Coastguard Worker 292*598139dcSAndroid Build Coastguard Worker private: 293*598139dcSAndroid Build Coastguard Worker uid_t uid_; 294*598139dcSAndroid Build Coastguard Worker char* name_; 295*598139dcSAndroid Build Coastguard Worker }; 296*598139dcSAndroid Build Coastguard Worker 297*598139dcSAndroid Build Coastguard Worker class TidEntry : public EntryBase { 298*598139dcSAndroid Build Coastguard Worker public: TidEntry(pid_t tid,pid_t pid)299*598139dcSAndroid Build Coastguard Worker TidEntry(pid_t tid, pid_t pid) 300*598139dcSAndroid Build Coastguard Worker : EntryBase(), pid_(pid), uid_(android::pidToUid(tid)), name_(android::tidToName(tid)) {} TidEntry(const LogStatisticsElement & element)301*598139dcSAndroid Build Coastguard Worker explicit TidEntry(const LogStatisticsElement& element) 302*598139dcSAndroid Build Coastguard Worker : EntryBase(element), 303*598139dcSAndroid Build Coastguard Worker pid_(element.pid), 304*598139dcSAndroid Build Coastguard Worker uid_(element.uid), 305*598139dcSAndroid Build Coastguard Worker name_(android::tidToName(element.tid)) {} TidEntry(const TidEntry & element)306*598139dcSAndroid Build Coastguard Worker TidEntry(const TidEntry& element) 307*598139dcSAndroid Build Coastguard Worker : EntryBase(element), 308*598139dcSAndroid Build Coastguard Worker pid_(element.pid_), 309*598139dcSAndroid Build Coastguard Worker uid_(element.uid_), 310*598139dcSAndroid Build Coastguard Worker name_(element.name_ ? strdup(element.name_) : nullptr) {} ~TidEntry()311*598139dcSAndroid Build Coastguard Worker ~TidEntry() { free(name_); } 312*598139dcSAndroid Build Coastguard Worker pid()313*598139dcSAndroid Build Coastguard Worker pid_t pid() const { return pid_; } uid()314*598139dcSAndroid Build Coastguard Worker uid_t uid() const { return uid_; } name()315*598139dcSAndroid Build Coastguard Worker const char* name() const { return name_; } 316*598139dcSAndroid Build Coastguard Worker Add(pid_t incomingTid)317*598139dcSAndroid Build Coastguard Worker void Add(pid_t incomingTid) { 318*598139dcSAndroid Build Coastguard Worker if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) { 319*598139dcSAndroid Build Coastguard Worker free(name_); 320*598139dcSAndroid Build Coastguard Worker name_ = nullptr; 321*598139dcSAndroid Build Coastguard Worker } 322*598139dcSAndroid Build Coastguard Worker if (!name_) { 323*598139dcSAndroid Build Coastguard Worker name_ = android::tidToName(incomingTid); 324*598139dcSAndroid Build Coastguard Worker } 325*598139dcSAndroid Build Coastguard Worker } 326*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)327*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { 328*598139dcSAndroid Build Coastguard Worker uid_t incoming_uid = element.uid; 329*598139dcSAndroid Build Coastguard Worker pid_t incoming_pid = element.pid; 330*598139dcSAndroid Build Coastguard Worker if (uid() != incoming_uid || pid() != incoming_pid) { 331*598139dcSAndroid Build Coastguard Worker uid_ = incoming_uid; 332*598139dcSAndroid Build Coastguard Worker pid_ = incoming_pid; 333*598139dcSAndroid Build Coastguard Worker free(name_); 334*598139dcSAndroid Build Coastguard Worker name_ = android::tidToName(element.tid); 335*598139dcSAndroid Build Coastguard Worker } else { 336*598139dcSAndroid Build Coastguard Worker Add(element.tid); 337*598139dcSAndroid Build Coastguard Worker } 338*598139dcSAndroid Build Coastguard Worker EntryBase::Add(element); 339*598139dcSAndroid Build Coastguard Worker } 340*598139dcSAndroid Build Coastguard Worker 341*598139dcSAndroid Build Coastguard Worker std::string formatHeader(const std::string& name, log_id_t id) const; 342*598139dcSAndroid Build Coastguard Worker std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const; 343*598139dcSAndroid Build Coastguard Worker 344*598139dcSAndroid Build Coastguard Worker private: 345*598139dcSAndroid Build Coastguard Worker pid_t pid_; 346*598139dcSAndroid Build Coastguard Worker uid_t uid_; 347*598139dcSAndroid Build Coastguard Worker char* name_; 348*598139dcSAndroid Build Coastguard Worker }; 349*598139dcSAndroid Build Coastguard Worker 350*598139dcSAndroid Build Coastguard Worker class TagEntry : public EntryBase { 351*598139dcSAndroid Build Coastguard Worker public: TagEntry(const LogStatisticsElement & element)352*598139dcSAndroid Build Coastguard Worker explicit TagEntry(const LogStatisticsElement& element) 353*598139dcSAndroid Build Coastguard Worker : EntryBase(element), tag_(element.tag), pid_(element.pid), uid_(element.uid) {} 354*598139dcSAndroid Build Coastguard Worker key()355*598139dcSAndroid Build Coastguard Worker uint32_t key() const { return tag_; } pid()356*598139dcSAndroid Build Coastguard Worker pid_t pid() const { return pid_; } uid()357*598139dcSAndroid Build Coastguard Worker uid_t uid() const { return uid_; } name()358*598139dcSAndroid Build Coastguard Worker const char* name() const { return android::tagToName(tag_); } 359*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)360*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { 361*598139dcSAndroid Build Coastguard Worker if (uid_ != element.uid) { 362*598139dcSAndroid Build Coastguard Worker uid_ = -1; 363*598139dcSAndroid Build Coastguard Worker } 364*598139dcSAndroid Build Coastguard Worker if (pid_ != element.pid) { 365*598139dcSAndroid Build Coastguard Worker pid_ = -1; 366*598139dcSAndroid Build Coastguard Worker } 367*598139dcSAndroid Build Coastguard Worker EntryBase::Add(element); 368*598139dcSAndroid Build Coastguard Worker } 369*598139dcSAndroid Build Coastguard Worker 370*598139dcSAndroid Build Coastguard Worker std::string formatHeader(const std::string& name, log_id_t id) const; 371*598139dcSAndroid Build Coastguard Worker std::string format(const LogStatistics& stat, log_id_t id, uint32_t) const; 372*598139dcSAndroid Build Coastguard Worker 373*598139dcSAndroid Build Coastguard Worker private: 374*598139dcSAndroid Build Coastguard Worker const uint32_t tag_; 375*598139dcSAndroid Build Coastguard Worker pid_t pid_; 376*598139dcSAndroid Build Coastguard Worker uid_t uid_; 377*598139dcSAndroid Build Coastguard Worker }; 378*598139dcSAndroid Build Coastguard Worker 379*598139dcSAndroid Build Coastguard Worker class TagNameEntry : public EntryBase { 380*598139dcSAndroid Build Coastguard Worker public: TagNameEntry(const LogStatisticsElement & element)381*598139dcSAndroid Build Coastguard Worker explicit TagNameEntry(const LogStatisticsElement& element) 382*598139dcSAndroid Build Coastguard Worker : EntryBase(element), tid_(element.tid), pid_(element.pid), uid_(element.uid) {} 383*598139dcSAndroid Build Coastguard Worker tid()384*598139dcSAndroid Build Coastguard Worker pid_t tid() const { return tid_; } pid()385*598139dcSAndroid Build Coastguard Worker pid_t pid() const { return pid_; } uid()386*598139dcSAndroid Build Coastguard Worker uid_t uid() const { return uid_; } 387*598139dcSAndroid Build Coastguard Worker Add(const LogStatisticsElement & element)388*598139dcSAndroid Build Coastguard Worker void Add(const LogStatisticsElement& element) { 389*598139dcSAndroid Build Coastguard Worker if (uid_ != element.uid) { 390*598139dcSAndroid Build Coastguard Worker uid_ = -1; 391*598139dcSAndroid Build Coastguard Worker } 392*598139dcSAndroid Build Coastguard Worker if (pid_ != element.pid) { 393*598139dcSAndroid Build Coastguard Worker pid_ = -1; 394*598139dcSAndroid Build Coastguard Worker } 395*598139dcSAndroid Build Coastguard Worker if (tid_ != element.tid) { 396*598139dcSAndroid Build Coastguard Worker tid_ = -1; 397*598139dcSAndroid Build Coastguard Worker } 398*598139dcSAndroid Build Coastguard Worker EntryBase::Add(element); 399*598139dcSAndroid Build Coastguard Worker } 400*598139dcSAndroid Build Coastguard Worker 401*598139dcSAndroid Build Coastguard Worker std::string formatHeader(const std::string& name, log_id_t id) const; 402*598139dcSAndroid Build Coastguard Worker std::string format(const LogStatistics& stat, log_id_t id, const std::string& key_name) const; 403*598139dcSAndroid Build Coastguard Worker 404*598139dcSAndroid Build Coastguard Worker private: 405*598139dcSAndroid Build Coastguard Worker pid_t tid_; 406*598139dcSAndroid Build Coastguard Worker pid_t pid_; 407*598139dcSAndroid Build Coastguard Worker uid_t uid_; 408*598139dcSAndroid Build Coastguard Worker }; 409*598139dcSAndroid Build Coastguard Worker 410*598139dcSAndroid Build Coastguard Worker class LogStatistics { 411*598139dcSAndroid Build Coastguard Worker friend UidEntry; 412*598139dcSAndroid Build Coastguard Worker friend PidEntry; 413*598139dcSAndroid Build Coastguard Worker friend TidEntry; 414*598139dcSAndroid Build Coastguard Worker 415*598139dcSAndroid Build Coastguard Worker size_t mSizes[LOG_ID_MAX] GUARDED_BY(lock_); 416*598139dcSAndroid Build Coastguard Worker size_t mElements[LOG_ID_MAX] GUARDED_BY(lock_); 417*598139dcSAndroid Build Coastguard Worker size_t mSizesTotal[LOG_ID_MAX] GUARDED_BY(lock_); 418*598139dcSAndroid Build Coastguard Worker size_t mElementsTotal[LOG_ID_MAX] GUARDED_BY(lock_); 419*598139dcSAndroid Build Coastguard Worker log_time mOldest[LOG_ID_MAX] GUARDED_BY(lock_); 420*598139dcSAndroid Build Coastguard Worker log_time mNewest[LOG_ID_MAX] GUARDED_BY(lock_); 421*598139dcSAndroid Build Coastguard Worker static std::atomic<size_t> SizesTotal; 422*598139dcSAndroid Build Coastguard Worker bool enable; 423*598139dcSAndroid Build Coastguard Worker 424*598139dcSAndroid Build Coastguard Worker // uid to size list 425*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<uid_t, UidEntry> uidTable_t; 426*598139dcSAndroid Build Coastguard Worker uidTable_t uidTable[LOG_ID_MAX] GUARDED_BY(lock_); 427*598139dcSAndroid Build Coastguard Worker 428*598139dcSAndroid Build Coastguard Worker // pid of system to size list 429*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t; 430*598139dcSAndroid Build Coastguard Worker pidSystemTable_t pidSystemTable[LOG_ID_MAX] GUARDED_BY(lock_); 431*598139dcSAndroid Build Coastguard Worker 432*598139dcSAndroid Build Coastguard Worker // pid to uid list 433*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<pid_t, PidEntry> pidTable_t; 434*598139dcSAndroid Build Coastguard Worker pidTable_t pidTable GUARDED_BY(lock_); 435*598139dcSAndroid Build Coastguard Worker 436*598139dcSAndroid Build Coastguard Worker // tid to uid list 437*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<pid_t, TidEntry> tidTable_t; 438*598139dcSAndroid Build Coastguard Worker tidTable_t tidTable GUARDED_BY(lock_); 439*598139dcSAndroid Build Coastguard Worker 440*598139dcSAndroid Build Coastguard Worker // tag list 441*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<uint32_t, TagEntry> tagTable_t; 442*598139dcSAndroid Build Coastguard Worker tagTable_t tagTable GUARDED_BY(lock_); 443*598139dcSAndroid Build Coastguard Worker 444*598139dcSAndroid Build Coastguard Worker // security tag list 445*598139dcSAndroid Build Coastguard Worker tagTable_t securityTagTable GUARDED_BY(lock_); 446*598139dcSAndroid Build Coastguard Worker 447*598139dcSAndroid Build Coastguard Worker // global tag list 448*598139dcSAndroid Build Coastguard Worker typedef LogHashtable<std::string, TagNameEntry> tagNameTable_t; 449*598139dcSAndroid Build Coastguard Worker tagNameTable_t tagNameTable; 450*598139dcSAndroid Build Coastguard Worker sizeOf()451*598139dcSAndroid Build Coastguard Worker size_t sizeOf() const REQUIRES(lock_) { 452*598139dcSAndroid Build Coastguard Worker size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() + 453*598139dcSAndroid Build Coastguard Worker tagTable.sizeOf() + securityTagTable.sizeOf() + 454*598139dcSAndroid Build Coastguard Worker tagNameTable.sizeOf() + 455*598139dcSAndroid Build Coastguard Worker (pidTable.size() * sizeof(pidTable_t::iterator)) + 456*598139dcSAndroid Build Coastguard Worker (tagTable.size() * sizeof(tagTable_t::iterator)); 457*598139dcSAndroid Build Coastguard Worker for (const auto& it : pidTable) { 458*598139dcSAndroid Build Coastguard Worker const char* name = it.second.name(); 459*598139dcSAndroid Build Coastguard Worker if (name) size += strlen(name) + 1; 460*598139dcSAndroid Build Coastguard Worker } 461*598139dcSAndroid Build Coastguard Worker for (const auto& it : tidTable) { 462*598139dcSAndroid Build Coastguard Worker const char* name = it.second.name(); 463*598139dcSAndroid Build Coastguard Worker if (name) size += strlen(name) + 1; 464*598139dcSAndroid Build Coastguard Worker } 465*598139dcSAndroid Build Coastguard Worker for (const auto& it : tagNameTable) { 466*598139dcSAndroid Build Coastguard Worker size += sizeof(std::string); 467*598139dcSAndroid Build Coastguard Worker size_t len = it.first.size(); 468*598139dcSAndroid Build Coastguard Worker // Account for short string optimization: if the string's length is <= 22 bytes for 64 469*598139dcSAndroid Build Coastguard Worker // bit or <= 10 bytes for 32 bit, then there is no additional allocation. 470*598139dcSAndroid Build Coastguard Worker if ((sizeof(std::string) == 24 && len > 22) || 471*598139dcSAndroid Build Coastguard Worker (sizeof(std::string) != 24 && len > 10)) { 472*598139dcSAndroid Build Coastguard Worker size += len; 473*598139dcSAndroid Build Coastguard Worker } 474*598139dcSAndroid Build Coastguard Worker } 475*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) { 476*598139dcSAndroid Build Coastguard Worker size += uidTable[id].sizeOf(); 477*598139dcSAndroid Build Coastguard Worker size += uidTable[id].size() * sizeof(uidTable_t::iterator); 478*598139dcSAndroid Build Coastguard Worker size += pidSystemTable[id].sizeOf(); 479*598139dcSAndroid Build Coastguard Worker size += pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator); 480*598139dcSAndroid Build Coastguard Worker } 481*598139dcSAndroid Build Coastguard Worker return size; 482*598139dcSAndroid Build Coastguard Worker } 483*598139dcSAndroid Build Coastguard Worker 484*598139dcSAndroid Build Coastguard Worker public: 485*598139dcSAndroid Build Coastguard Worker LogStatistics(bool enable_statistics, bool track_total_size, 486*598139dcSAndroid Build Coastguard Worker std::optional<log_time> start_time = {}); 487*598139dcSAndroid Build Coastguard Worker 488*598139dcSAndroid Build Coastguard Worker void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_); 489*598139dcSAndroid Build Coastguard Worker 490*598139dcSAndroid Build Coastguard Worker // Add is for adding an element to the log buffer. 491*598139dcSAndroid Build Coastguard Worker // Add the total size of the element to statistics. 492*598139dcSAndroid Build Coastguard Worker void Add(LogStatisticsElement entry) EXCLUDES(lock_); 493*598139dcSAndroid Build Coastguard Worker // Subtract is for removing an element from the log buffer. 494*598139dcSAndroid Build Coastguard Worker // Subtract the total size of the element from statistics. 495*598139dcSAndroid Build Coastguard Worker void Subtract(LogStatisticsElement entry) EXCLUDES(lock_); 496*598139dcSAndroid Build Coastguard Worker 497*598139dcSAndroid Build Coastguard Worker bool ShouldPrune(log_id id, unsigned long max_size, unsigned long* prune_rows) const 498*598139dcSAndroid Build Coastguard Worker EXCLUDES(lock_); 499*598139dcSAndroid Build Coastguard Worker 500*598139dcSAndroid Build Coastguard Worker // Return the consumed size of the given buffer. Sizes(log_id_t id)501*598139dcSAndroid Build Coastguard Worker size_t Sizes(log_id_t id) const EXCLUDES(lock_) { 502*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_}; 503*598139dcSAndroid Build Coastguard Worker if (overhead_[id]) { 504*598139dcSAndroid Build Coastguard Worker return *overhead_[id]; 505*598139dcSAndroid Build Coastguard Worker } 506*598139dcSAndroid Build Coastguard Worker return mSizes[id]; 507*598139dcSAndroid Build Coastguard Worker } 508*598139dcSAndroid Build Coastguard Worker 509*598139dcSAndroid Build Coastguard Worker // Return the uncompressed size of the contents of the given buffer. SizeReadable(log_id_t id)510*598139dcSAndroid Build Coastguard Worker size_t SizeReadable(log_id_t id) const EXCLUDES(lock_) { 511*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_}; 512*598139dcSAndroid Build Coastguard Worker return mSizes[id]; 513*598139dcSAndroid Build Coastguard Worker } 514*598139dcSAndroid Build Coastguard Worker 515*598139dcSAndroid Build Coastguard Worker // TODO: Get rid of this entirely. sizesTotal()516*598139dcSAndroid Build Coastguard Worker static size_t sizesTotal() { 517*598139dcSAndroid Build Coastguard Worker return SizesTotal; 518*598139dcSAndroid Build Coastguard Worker } 519*598139dcSAndroid Build Coastguard Worker 520*598139dcSAndroid Build Coastguard Worker std::string ReportInteresting() const EXCLUDES(lock_); 521*598139dcSAndroid Build Coastguard Worker std::string Format(uid_t uid, pid_t pid, unsigned int logMask) const EXCLUDES(lock_); 522*598139dcSAndroid Build Coastguard Worker 523*598139dcSAndroid Build Coastguard Worker const char* PidToName(pid_t pid) const EXCLUDES(lock_); 524*598139dcSAndroid Build Coastguard Worker uid_t PidToUid(pid_t pid) EXCLUDES(lock_); 525*598139dcSAndroid Build Coastguard Worker const char* UidToName(uid_t uid) const EXCLUDES(lock_); 526*598139dcSAndroid Build Coastguard Worker set_overhead(log_id_t id,size_t size)527*598139dcSAndroid Build Coastguard Worker void set_overhead(log_id_t id, size_t size) { 528*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_}; 529*598139dcSAndroid Build Coastguard Worker overhead_[id] = size; 530*598139dcSAndroid Build Coastguard Worker } 531*598139dcSAndroid Build Coastguard Worker 532*598139dcSAndroid Build Coastguard Worker private: 533*598139dcSAndroid Build Coastguard Worker template <typename TKey, typename TEntry> 534*598139dcSAndroid Build Coastguard Worker std::string FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid, pid_t pid, 535*598139dcSAndroid Build Coastguard Worker const std::string& name = std::string(""), 536*598139dcSAndroid Build Coastguard Worker log_id_t id = LOG_ID_MAX) const REQUIRES(lock_); 537*598139dcSAndroid Build Coastguard Worker void FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size, 538*598139dcSAndroid Build Coastguard Worker size_t nameLen) const REQUIRES(lock_); 539*598139dcSAndroid Build Coastguard Worker const char* UidToNameLocked(uid_t uid) const REQUIRES(lock_); 540*598139dcSAndroid Build Coastguard Worker 541*598139dcSAndroid Build Coastguard Worker mutable std::mutex lock_; 542*598139dcSAndroid Build Coastguard Worker bool track_total_size_; 543*598139dcSAndroid Build Coastguard Worker 544*598139dcSAndroid Build Coastguard Worker std::optional<size_t> overhead_[LOG_ID_MAX] GUARDED_BY(lock_); 545*598139dcSAndroid Build Coastguard Worker }; 546