• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020, 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 CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_
18 #define CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_
19 
20 #include <android-base/result.h>
21 #include <android-base/stringprintf.h>
22 #include <gtest/gtest_prod.h>
23 #include <utils/Mutex.h>
24 #include <utils/RefBase.h>
25 
26 #include <inttypes.h>
27 #include <stdint.h>
28 #include <unistd.h>
29 
30 #include <string>
31 #include <unordered_map>
32 #include <vector>
33 
34 namespace android {
35 namespace automotive {
36 namespace watchdog {
37 
38 using ::android::base::StringPrintf;
39 
40 #define PID_FOR_INIT 1
41 
42 constexpr const char kProcDirPath[] = "/proc";
43 constexpr const char kStatFileFormat[] = "/%" PRIu32 "/stat";
44 constexpr const char kTaskDirFormat[] = "/%" PRIu32 "/task";
45 constexpr const char kStatusFileFormat[] = "/%" PRIu32 "/status";
46 
47 // Per-pid/tid stats.
48 // The int64_t type is used due to AIDL limitations representing long field values.
49 struct PidStat {
50     std::string comm = "";
51     std::string state = "";
52     int64_t startTimeMillis = 0;
53     int64_t cpuTimeMillis = 0;
54     uint64_t majorFaults = 0;
55 };
56 
57 // Per-process stats.
58 struct ProcessStats {
59     std::string comm = "";
60     int64_t startTimeMillis = 0;  // Useful when identifying PID reuse
61     int64_t cpuTimeMillis = 0;
62     uint64_t totalMajorFaults = 0;
63     int totalTasksCount = 0;
64     int ioBlockedTasksCount = 0;
65     std::string toString() const;
66 };
67 
68 // Per-UID stats.
69 struct UidProcStats {
70     int64_t cpuTimeMillis = 0;
71     uint64_t totalMajorFaults = 0;
72     int totalTasksCount = 0;
73     int ioBlockedTasksCount = 0;
74     std::unordered_map<pid_t, ProcessStats> processStatsByPid = {};
75     std::string toString() const;
76 };
77 
78 // Collector/parser for `/proc/[pid]/stat`, `/proc/[pid]/task/[tid]/stat` and /proc/[pid]/status`
79 // files.
80 class UidProcStatsCollectorInterface : public RefBase {
81 public:
82     // Initializes the collector.
83     virtual void init() = 0;
84     // Collects the per-uid stats from /proc directory.
85     virtual android::base::Result<void> collect() = 0;
86     // Returns the latest per-uid process stats.
87     virtual const std::unordered_map<uid_t, UidProcStats> latestStats() const = 0;
88     // Returns the delta of per-uid process stats since the last before collection.
89     virtual const std::unordered_map<uid_t, UidProcStats> deltaStats() const = 0;
90     // Returns true only when the /proc files for the init process are accessible.
91     virtual bool enabled() const = 0;
92     // Returns the /proc files common ancestor directory path.
93     virtual const std::string dirPath() const = 0;
94 };
95 
96 class UidProcStatsCollector final : public UidProcStatsCollectorInterface {
97 public:
98     explicit UidProcStatsCollector(const std::string& path = kProcDirPath) :
sysconf(_SC_CLK_TCK)99           mMillisPerClockTick(1000 / sysconf(_SC_CLK_TCK)),
100           mPath(path),
101           mLatestStats({}),
102           mDeltaStats({}) {}
103 
~UidProcStatsCollector()104     ~UidProcStatsCollector() {}
105 
106     void init() override;
107 
108     android::base::Result<void> collect() override;
109 
latestStats()110     const std::unordered_map<uid_t, UidProcStats> latestStats() const {
111         Mutex::Autolock lock(mMutex);
112         return mLatestStats;
113     }
114 
deltaStats()115     const std::unordered_map<uid_t, UidProcStats> deltaStats() const {
116         Mutex::Autolock lock(mMutex);
117         return mDeltaStats;
118     }
119 
enabled()120     bool enabled() const {
121         Mutex::Autolock lock(mMutex);
122         return mEnabled;
123     }
124 
dirPath()125     const std::string dirPath() const { return mPath; }
126 
127     static android::base::Result<PidStat> readStatFileForPid(pid_t pid);
128 
129     static android::base::Result<std::tuple<uid_t, pid_t>> readPidStatusFileForPid(pid_t pid);
130 
131 private:
132     android::base::Result<std::unordered_map<uid_t, UidProcStats>> readUidProcStatsLocked() const;
133 
134     // Reads the contents of the below files:
135     // 1. Pid stat file at |mPath| + |kStatFileFormat|
136     // 2. Aggregated per-process status at |mPath| + |kStatusFileFormat|
137     // 3. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat|
138     android::base::Result<std::tuple<uid_t, ProcessStats>> readProcessStatsLocked(pid_t pid) const;
139 
140     // Number of milliseconds per clock cycle.
141     int32_t mMillisPerClockTick;
142 
143     // Proc directory path. Default value is |kProcDirPath|.
144     // Updated by tests to point to a different location when needed.
145     std::string mPath;
146 
147     // Makes sure only one collection is running at any given time.
148     mutable Mutex mMutex;
149 
150     // True if the below files are accessible:
151     // 1. Pid stat file at |mPath| + |kTaskStatFileFormat|
152     // 2. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat|
153     // 3. Pid status file at |mPath| + |kStatusFileFormat|
154     // Otherwise, set to false.
155     bool mEnabled GUARDED_BY(mMutex);
156 
157     // Latest dump of per-UID stats.
158     std::unordered_map<uid_t, UidProcStats> mLatestStats GUARDED_BY(mMutex);
159 
160     // Latest delta of per-uid stats.
161     std::unordered_map<uid_t, UidProcStats> mDeltaStats GUARDED_BY(mMutex);
162 
163     FRIEND_TEST(IoPerfCollectionTest, TestValidProcPidContents);
164     FRIEND_TEST(UidProcStatsCollectorTest, TestValidStatFiles);
165     FRIEND_TEST(UidProcStatsCollectorTest, TestHandlesProcessTerminationBetweenScanningAndParsing);
166     FRIEND_TEST(UidProcStatsCollectorTest, TestHandlesPidTidReuse);
167 };
168 
169 }  // namespace watchdog
170 }  // namespace automotive
171 }  // namespace android
172 
173 #endif  //  CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_
174