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