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 WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
18 #define WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
19 
20 #include <android-base/result.h>
21 #include <stdint.h>
22 #include <utils/Mutex.h>
23 #include <utils/RefBase.h>
24 
25 #include <string>
26 #include <unordered_map>
27 
28 namespace android {
29 namespace automotive {
30 namespace watchdog {
31 
32 constexpr const char* kUidIoStatsPath = "/proc/uid_io/stats";
33 
34 enum UidState {
35     FOREGROUND = 0,
36     BACKGROUND,
37     UID_STATES,
38 };
39 
40 enum MetricType {
41     READ_BYTES = 0,
42     WRITE_BYTES,
43     FSYNC_COUNT,
44     METRIC_TYPES,
45 };
46 
47 struct IoStat {
48     uint64_t rchar = 0;       // characters read
49     uint64_t wchar = 0;       // characters written
50     uint64_t readBytes = 0;   // bytes read (from storage layer)
51     uint64_t writeBytes = 0;  // bytes written (to storage layer)
52     uint64_t fsync = 0;       // number of fsync syscalls
53 };
54 
55 struct UidIoStat {
56     uint32_t uid = 0;  // linux user id
57     IoStat io[UID_STATES] = {{}};
58 };
59 
60 class IoUsage {
61   public:
IoUsage()62     IoUsage() : metrics{{0}} {};
IoUsage(uint64_t fgRdBytes,uint64_t bgRdBytes,uint64_t fgWrBytes,uint64_t bgWrBytes,uint64_t fgFsync,uint64_t bgFsync)63     IoUsage(uint64_t fgRdBytes, uint64_t bgRdBytes, uint64_t fgWrBytes, uint64_t bgWrBytes,
64             uint64_t fgFsync, uint64_t bgFsync) {
65         metrics[READ_BYTES][FOREGROUND] = fgRdBytes;
66         metrics[READ_BYTES][BACKGROUND] = bgRdBytes;
67         metrics[WRITE_BYTES][FOREGROUND] = fgWrBytes;
68         metrics[WRITE_BYTES][BACKGROUND] = bgWrBytes;
69         metrics[FSYNC_COUNT][FOREGROUND] = fgFsync;
70         metrics[FSYNC_COUNT][BACKGROUND] = bgFsync;
71     }
72     bool operator==(const IoUsage& usage) const {
73         return memcmp(&metrics, &usage.metrics, sizeof(metrics)) == 0;
74     }
sumReadBytes()75     uint64_t sumReadBytes() const {
76         return metrics[READ_BYTES][FOREGROUND] + metrics[READ_BYTES][BACKGROUND];
77     }
sumWriteBytes()78     uint64_t sumWriteBytes() const {
79         return metrics[WRITE_BYTES][FOREGROUND] + metrics[WRITE_BYTES][BACKGROUND];
80     }
81     bool isZero() const;
82     std::string toString() const;
83     uint64_t metrics[METRIC_TYPES][UID_STATES];
84 };
85 
86 struct UidIoUsage {
87     uint32_t uid = 0;
88     IoUsage ios = {};
89 };
90 
91 class UidIoStats : public RefBase {
92 public:
93     explicit UidIoStats(const std::string& path = kUidIoStatsPath) :
94           kEnabled(!access(path.c_str(), R_OK)), kPath(path) {}
95 
~UidIoStats()96     virtual ~UidIoStats() {}
97 
98     // Collects the I/O usage since the last collection.
99     virtual android::base::Result<std::unordered_map<uint32_t, UidIoUsage>> collect();
100 
101     // Returns true when the uid_io stats file is accessible. Otherwise, returns false.
102     // Called by IoPerfCollection and tests.
enabled()103     virtual bool enabled() { return kEnabled; }
104 
filePath()105     virtual std::string filePath() { return kPath; }
106 
107 private:
108     // Reads the contents of |kPath|.
109     android::base::Result<std::unordered_map<uint32_t, UidIoStat>> getUidIoStatsLocked() const;
110 
111     // Makes sure only one collection is running at any given time.
112     Mutex mMutex;
113 
114     // Last dump from the file at |kPath|.
115     std::unordered_map<uint32_t, UidIoStat> mLastUidIoStats GUARDED_BY(mMutex);
116 
117     // True if kPath is accessible.
118     const bool kEnabled;
119 
120     // Path to uid_io stats file. Default path is |kUidIoStatsPath|.
121     const std::string kPath;
122 };
123 
124 }  // namespace watchdog
125 }  // namespace automotive
126 }  // namespace android
127 
128 #endif  //  WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
129