1 /*
2  * Copyright (C) 2012-2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _LOGD_LOG_BUFFER_H__
18 #define _LOGD_LOG_BUFFER_H__
19 
20 #include <sys/types.h>
21 
22 #include <list>
23 #include <string>
24 
25 #include <log/log.h>
26 #include <sysutils/SocketClient.h>
27 
28 #include <private/android_filesystem_config.h>
29 
30 #include "LogBufferElement.h"
31 #include "LogTimes.h"
32 #include "LogStatistics.h"
33 #include "LogWhiteBlackList.h"
34 
35 //
36 // We are either in 1970ish (MONOTONIC) or 2016+ish (REALTIME) so to
37 // differentiate without prejudice, we use 1972 to delineate, earlier
38 // is likely monotonic, later is real. Otherwise we start using a
39 // dividing line between monotonic and realtime if more than a minute
40 // difference between them.
41 //
42 namespace android {
43 
isMonotonic(const log_time & mono)44 static bool isMonotonic(const log_time &mono) {
45     static const uint32_t EPOCH_PLUS_2_YEARS = 2 * 24 * 60 * 60 * 1461 / 4;
46     static const uint32_t EPOCH_PLUS_MINUTE = 60;
47 
48     if (mono.tv_sec >= EPOCH_PLUS_2_YEARS) {
49         return false;
50     }
51 
52     log_time now(CLOCK_REALTIME);
53 
54     /* Timezone and ntp time setup? */
55     if (now.tv_sec >= EPOCH_PLUS_2_YEARS) {
56         return true;
57     }
58 
59     /* no way to differentiate realtime from monotonic time */
60     if (now.tv_sec < EPOCH_PLUS_MINUTE) {
61         return false;
62     }
63 
64     log_time cpu(CLOCK_MONOTONIC);
65     /* too close to call to differentiate monotonic times from realtime */
66     if ((cpu.tv_sec + EPOCH_PLUS_MINUTE) >= now.tv_sec) {
67         return false;
68     }
69 
70     /* dividing line half way between monotonic and realtime */
71     return mono.tv_sec < ((cpu.tv_sec + now.tv_sec) / 2);
72 }
73 
74 }
75 
76 typedef std::list<LogBufferElement *> LogBufferElementCollection;
77 
78 class LogBuffer {
79     LogBufferElementCollection mLogElements;
80     pthread_mutex_t mLogElementsLock;
81 
82     LogStatistics stats;
83 
84     PruneList mPrune;
85     // watermark for last per log id
86     LogBufferElementCollection::iterator mLast[LOG_ID_MAX];
87     bool mLastSet[LOG_ID_MAX];
88     // watermark of any worst/chatty uid processing
89     typedef std::unordered_map<uid_t,
90                                LogBufferElementCollection::iterator>
91                 LogBufferIteratorMap;
92     LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
93     // watermark of any worst/chatty pid of system processing
94     typedef std::unordered_map<pid_t,
95                                LogBufferElementCollection::iterator>
96                 LogBufferPidIteratorMap;
97     LogBufferPidIteratorMap mLastWorstPidOfSystem[LOG_ID_MAX];
98 
99     unsigned long mMaxSize[LOG_ID_MAX];
100 
101     bool monotonic;
102 
103 public:
104     LastLogTimes &mTimes;
105 
106     LogBuffer(LastLogTimes *times);
107     void init();
isMonotonic()108     bool isMonotonic() { return monotonic; }
109 
110     int log(log_id_t log_id, log_time realtime,
111             uid_t uid, pid_t pid, pid_t tid,
112             const char *msg, unsigned short len);
113     uint64_t flushTo(SocketClient *writer, const uint64_t start,
114                      bool privileged, bool security,
115                      int (*filter)(const LogBufferElement *element, void *arg) = NULL,
116                      void *arg = NULL);
117 
118     bool clear(log_id_t id, uid_t uid = AID_ROOT);
119     unsigned long getSize(log_id_t id);
120     int setSize(log_id_t id, unsigned long size);
121     unsigned long getSizeUsed(log_id_t id);
122     // *strp uses malloc, use free to release.
123     std::string formatStatistics(uid_t uid, pid_t pid, unsigned int logMask);
124 
enableStatistics()125     void enableStatistics() {
126         stats.enableStatistics();
127     }
128 
initPrune(const char * cp)129     int initPrune(const char *cp) { return mPrune.init(cp); }
formatPrune()130     std::string formatPrune() { return mPrune.format(); }
131 
132     // helper must be protected directly or implicitly by lock()/unlock()
pidToName(pid_t pid)133     const char *pidToName(pid_t pid) { return stats.pidToName(pid); }
pidToUid(pid_t pid)134     uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); }
uidToName(uid_t uid)135     const char *uidToName(uid_t uid) { return stats.uidToName(uid); }
lock()136     void lock() { pthread_mutex_lock(&mLogElementsLock); }
unlock()137     void unlock() { pthread_mutex_unlock(&mLogElementsLock); }
138 
139 private:
140 
141     static constexpr size_t minPrune = 4;
142     static constexpr size_t maxPrune = 256;
143 
144     void maybePrune(log_id_t id);
145     bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
146     LogBufferElementCollection::iterator erase(
147         LogBufferElementCollection::iterator it, bool coalesce = false);
148 };
149 
150 #endif // _LOGD_LOG_BUFFER_H__
151