1 /*
2 * Copyright (c) 2021, 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 #define LOG_TAG "carwatchdogd"
18
19 #include "UidStatsCollector.h"
20
21 #include <algorithm>
22 #include <unordered_map>
23 #include <unordered_set>
24
25 namespace android {
26 namespace automotive {
27 namespace watchdog {
28
29 using ::android::sp;
30 using ::android::base::Error;
31 using ::android::base::Result;
32
hasPackageInfo() const33 bool UidStats::hasPackageInfo() const {
34 return !packageInfo.packageIdentifier.name.empty();
35 }
36
uid() const37 uid_t UidStats::uid() const {
38 return static_cast<uid_t>(packageInfo.packageIdentifier.uid);
39 }
40
genericPackageName() const41 std::string UidStats::genericPackageName() const {
42 if (hasPackageInfo()) {
43 return packageInfo.packageIdentifier.name;
44 }
45 return std::to_string(packageInfo.packageIdentifier.uid);
46 }
47
collect()48 Result<void> UidStatsCollector::collect() {
49 Mutex::Autolock lock(mMutex);
50 if (mUidIoStatsCollector->enabled()) {
51 if (const auto& result = mUidIoStatsCollector->collect(); !result.ok()) {
52 return Error() << "Failed to collect per-uid I/O stats: " << result.error();
53 }
54 }
55 if (mUidProcStatsCollector->enabled()) {
56 if (const auto& result = mUidProcStatsCollector->collect(); !result.ok()) {
57 return Error() << "Failed to collect per-uid process stats: " << result.error();
58 }
59 }
60 if (mUidCpuStatsCollector->enabled()) {
61 if (const auto& result = mUidCpuStatsCollector->collect(); !result.ok()) {
62 return Error() << "Failed to collect per-uid CPU stats: " << result.error();
63 }
64 }
65
66 mLatestStats =
67 process(mUidIoStatsCollector->latestStats(), mUidProcStatsCollector->latestStats(),
68 mUidCpuStatsCollector->latestStats());
69 mDeltaStats = process(mUidIoStatsCollector->deltaStats(), mUidProcStatsCollector->deltaStats(),
70 mUidCpuStatsCollector->deltaStats());
71 return {};
72 }
73
process(const std::unordered_map<uid_t,UidIoStats> & uidIoStatsByUid,const std::unordered_map<uid_t,UidProcStats> & uidProcStatsByUid,const std::unordered_map<uid_t,int64_t> & cpuTimeMillisByUid) const74 std::vector<UidStats> UidStatsCollector::process(
75 const std::unordered_map<uid_t, UidIoStats>& uidIoStatsByUid,
76 const std::unordered_map<uid_t, UidProcStats>& uidProcStatsByUid,
77 const std::unordered_map<uid_t, int64_t>& cpuTimeMillisByUid) const {
78 if (uidIoStatsByUid.empty() && uidProcStatsByUid.empty() && cpuTimeMillisByUid.empty()) {
79 return std::vector<UidStats>();
80 }
81 std::unordered_set<uid_t> uidSet;
82 for (const auto& [uid, _] : uidIoStatsByUid) {
83 uidSet.insert(uid);
84 }
85 for (const auto& [uid, _] : uidProcStatsByUid) {
86 uidSet.insert(uid);
87 }
88 for (const auto& [uid, _] : cpuTimeMillisByUid) {
89 uidSet.insert(uid);
90 }
91 std::vector<uid_t> uids;
92 for (const auto& uid : uidSet) {
93 uids.push_back(uid);
94 }
95 const auto packageInfoByUid = mPackageInfoResolver->getPackageInfosForUids(uids);
96 std::vector<UidStats> uidStats;
97 for (const auto& uid : uids) {
98 UidStats curUidStats;
99 if (const auto it = packageInfoByUid.find(uid); it != packageInfoByUid.end()) {
100 curUidStats.packageInfo = it->second;
101 } else {
102 curUidStats.packageInfo.packageIdentifier.uid = uid;
103 }
104 if (const auto it = uidIoStatsByUid.find(uid); it != uidIoStatsByUid.end()) {
105 curUidStats.ioStats = it->second;
106 }
107 if (const auto it = cpuTimeMillisByUid.find(uid); it != cpuTimeMillisByUid.end()) {
108 curUidStats.cpuTimeMillis = it->second;
109 }
110 if (const auto it = uidProcStatsByUid.find(uid); it != uidProcStatsByUid.end()) {
111 curUidStats.procStats = it->second;
112 if (curUidStats.cpuTimeMillis == 0) {
113 curUidStats.cpuTimeMillis = curUidStats.procStats.cpuTimeMillis;
114 }
115 }
116 uidStats.emplace_back(std::move(curUidStats));
117 }
118 return uidStats;
119 }
120
121 } // namespace watchdog
122 } // namespace automotive
123 } // namespace android
124