1 /*
2  * Copyright (c) 2022, 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_UIDCPUSTATSCOLLECTOR_H_
18 #define CPP_WATCHDOG_SERVER_SRC_UIDCPUSTATSCOLLECTOR_H_
19 
20 #include <android-base/result.h>
21 #include <android-base/stringprintf.h>
22 #include <utils/Mutex.h>
23 #include <utils/RefBase.h>
24 
25 #include <stdint.h>
26 
27 #include <string>
28 #include <unordered_map>
29 
30 namespace android {
31 namespace automotive {
32 namespace watchdog {
33 
34 inline constexpr char kShowUidCpuTimeFile[] = "/proc/uid_cputime/show_uid_stat";
35 
36 // Collector/Parser for `/proc/uid_cputime/show_uid_stat`.
37 class UidCpuStatsCollectorInterface : public RefBase {
38 public:
39     // Initializes the collector.
40     virtual void init() = 0;
41     // Collects the per-UID CPU stats.
42     virtual android::base::Result<void> collect() = 0;
43     // Returns the latest per-UID CPU stats.
44     virtual const std::unordered_map<uid_t, int64_t> latestStats() const = 0;
45     // Returns the delta of per-UID CPU stats since the last before collection.
46     virtual const std::unordered_map<uid_t, int64_t> deltaStats() const = 0;
47     // Returns true only when the per-UID CPU stats file is accessible.
48     virtual bool enabled() const = 0;
49     // Returns the path for the per-UID CPU stats file.
50     virtual const std::string filePath() const = 0;
51 };
52 
53 class UidCpuStatsCollector final : public UidCpuStatsCollectorInterface {
54 public:
mPath(path)55     explicit UidCpuStatsCollector(const std::string& path = kShowUidCpuTimeFile) : mPath(path) {}
56 
~UidCpuStatsCollector()57     ~UidCpuStatsCollector() {}
58 
init()59     void init() override {
60         Mutex::Autolock lock(mMutex);
61         // Note: Verify proc file access outside the constructor. Otherwise, the unittests of
62         // dependent classes would call the constructor before mocking and get killed due to
63         // sepolicy violation.
64         mEnabled = access(mPath.c_str(), R_OK) == 0;
65     }
66 
67     android::base::Result<void> collect() override;
68 
latestStats()69     const std::unordered_map<uid_t, int64_t> latestStats() const override {
70         Mutex::Autolock lock(mMutex);
71         return mLatestStats;
72     }
73 
deltaStats()74     const std::unordered_map<uid_t, int64_t> deltaStats() const override {
75         Mutex::Autolock lock(mMutex);
76         return mDeltaStats;
77     }
78 
enabled()79     bool enabled() const override {
80         Mutex::Autolock lock(mMutex);
81         return mEnabled;
82     }
83 
filePath()84     const std::string filePath() const override { return mPath; }
85 
86 private:
87     // Path to show_uid_stat file. Default path is |kShowUidCpuTimeFile|.
88     const std::string mPath;
89 
90     // Makes sure only one collection is running at any given time.
91     mutable Mutex mMutex;
92 
93     // True if |mPath| is accessible.
94     bool mEnabled GUARDED_BY(mMutex);
95 
96     // Latest dump from the file at |mPath|.
97     std::unordered_map<uid_t, int64_t> mLatestStats GUARDED_BY(mMutex);
98 
99     // Delta of per-UID CPU stats since last before collection.
100     std::unordered_map<uid_t, int64_t> mDeltaStats GUARDED_BY(mMutex);
101 };
102 
103 }  // namespace watchdog
104 }  // namespace automotive
105 }  // namespace android
106 
107 #endif  // CPP_WATCHDOG_SERVER_SRC_UIDCPUSTATSCOLLECTOR_H_
108