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