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     if (mUidProcStatsCollector->enabled()) {
50         if (const auto& result = mUidIoStatsCollector->collect(); !result.ok()) {
51             return Error() << "Failed to collect per-uid I/O stats: " << result.error();
52         }
53     }
54     if (mUidProcStatsCollector->enabled()) {
55         if (const auto& result = mUidProcStatsCollector->collect(); !result.ok()) {
56             return Error() << "Failed to collect per-uid process stats: " << result.error();
57         }
58     }
59     mLatestStats =
60             process(mUidIoStatsCollector->latestStats(), mUidProcStatsCollector->latestStats());
61     mDeltaStats = process(mUidIoStatsCollector->deltaStats(), mUidProcStatsCollector->deltaStats());
62     return {};
63 }
64 
process(const std::unordered_map<uid_t,UidIoStats> & uidIoStatsByUid,const std::unordered_map<uid_t,UidProcStats> & uidProcStatsByUid) const65 std::vector<UidStats> UidStatsCollector::process(
66         const std::unordered_map<uid_t, UidIoStats>& uidIoStatsByUid,
67         const std::unordered_map<uid_t, UidProcStats>& uidProcStatsByUid) const {
68     if (uidIoStatsByUid.empty() && uidProcStatsByUid.empty()) {
69         return std::vector<UidStats>();
70     }
71     std::unordered_set<uid_t> uidSet;
72     for (const auto& [uid, _] : uidIoStatsByUid) {
73         uidSet.insert(uid);
74     }
75     for (const auto& [uid, _] : uidProcStatsByUid) {
76         uidSet.insert(uid);
77     }
78     std::vector<uid_t> uids;
79     for (const auto& uid : uidSet) {
80         uids.push_back(uid);
81     }
82     const auto packageInfoByUid = mPackageInfoResolver->getPackageInfosForUids(uids);
83     std::vector<UidStats> uidStats;
84     for (const auto& uid : uids) {
85         UidStats curUidStats;
86         if (const auto it = packageInfoByUid.find(uid); it != packageInfoByUid.end()) {
87             curUidStats.packageInfo = it->second;
88         } else {
89             curUidStats.packageInfo.packageIdentifier.uid = uid;
90         }
91         if (const auto it = uidIoStatsByUid.find(uid); it != uidIoStatsByUid.end()) {
92             curUidStats.ioStats = it->second;
93         }
94         if (const auto it = uidProcStatsByUid.find(uid); it != uidProcStatsByUid.end()) {
95             curUidStats.procStats = it->second;
96         }
97         uidStats.emplace_back(std::move(curUidStats));
98     }
99     return uidStats;
100 }
101 
102 }  // namespace watchdog
103 }  // namespace automotive
104 }  // namespace android
105