blob: 5745782b2e6fa3ff3df233bb9f6a2f6cb06189d5 [file] [log] [blame]
Jin Qianbcd6e3b2016-12-28 15:43:51 -08001/*
2 * Copyright (C) 2016 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 "storaged"
18
19#include <stdint.h>
20#include <time.h>
21
22#include <string>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080023#include <unordered_map>
24
Jin Qian2d7bcce2017-07-28 18:45:59 -070025#include <android/content/pm/IPackageManagerNative.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080026#include <android-base/file.h>
27#include <android-base/logging.h>
28#include <android-base/macros.h>
Jin Qian9b1aeae2017-03-14 11:20:02 -070029#include <android-base/parseint.h>
Jin Qiane83a6102017-03-02 16:16:54 -080030#include <android-base/strings.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080031#include <android-base/stringprintf.h>
Jin Qian2d7bcce2017-07-28 18:45:59 -070032#include <binder/IServiceManager.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080033#include <log/log_event_list.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080034
35#include "storaged.h"
36#include "storaged_uid_monitor.h"
37
Jin Qianbcd6e3b2016-12-28 15:43:51 -080038using namespace android;
39using namespace android::base;
Jin Qian2d7bcce2017-07-28 18:45:59 -070040using namespace android::content::pm;
Jin Qianb049d182017-10-12 17:02:17 -070041using namespace android::os::storaged;
Jin Qianebf031b2017-08-14 16:41:24 -070042using namespace storaged_proto;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080043
Jin Qian65dea712017-08-29 16:48:20 -070044namespace {
45
46bool refresh_uid_names;
Jin Qian65dea712017-08-29 16:48:20 -070047const char* UID_IO_STATS_PATH = "/proc/uid_io/stats";
48
49} // namepsace
Jin Qianebf031b2017-08-14 16:41:24 -070050
Jin Qianb049d182017-10-12 17:02:17 -070051std::unordered_map<uint32_t, uid_info> uid_monitor::get_uid_io_stats()
Jin Qianbcd6e3b2016-12-28 15:43:51 -080052{
Jin Qian6df3bc62017-10-18 17:52:14 -070053 Mutex::Autolock _l(uidm_mutex);
Jin Qian5b962c62017-01-30 14:48:38 -080054 return get_uid_io_stats_locked();
55};
Jin Qianbcd6e3b2016-12-28 15:43:51 -080056
Yang Jin3906c892017-06-22 15:18:21 -070057/* return true on parse success and false on failure */
58bool uid_info::parse_uid_io_stats(std::string&& s)
59{
60 std::vector<std::string> fields = Split(s, " ");
61 if (fields.size() < 11 ||
62 !ParseUint(fields[0], &uid) ||
63 !ParseUint(fields[1], &io[FOREGROUND].rchar) ||
64 !ParseUint(fields[2], &io[FOREGROUND].wchar) ||
65 !ParseUint(fields[3], &io[FOREGROUND].read_bytes) ||
66 !ParseUint(fields[4], &io[FOREGROUND].write_bytes) ||
67 !ParseUint(fields[5], &io[BACKGROUND].rchar) ||
68 !ParseUint(fields[6], &io[BACKGROUND].wchar) ||
69 !ParseUint(fields[7], &io[BACKGROUND].read_bytes) ||
70 !ParseUint(fields[8], &io[BACKGROUND].write_bytes) ||
71 !ParseUint(fields[9], &io[FOREGROUND].fsync) ||
72 !ParseUint(fields[10], &io[BACKGROUND].fsync)) {
Jin Qian0e026872017-08-29 11:42:06 -070073 LOG_TO(SYSTEM, WARNING) << "Invalid uid I/O stats: \""
Yang Jin3906c892017-06-22 15:18:21 -070074 << s << "\"";
75 return false;
76 }
77 return true;
78}
79
80/* return true on parse success and false on failure */
81bool task_info::parse_task_io_stats(std::string&& s)
82{
83 std::vector<std::string> fields = Split(s, ",");
Jin Qian0e026872017-08-29 11:42:06 -070084 size_t size = fields.size();
85 if (size < 13 ||
86 !ParseInt(fields[size - 11], &pid) ||
87 !ParseUint(fields[size - 10], &io[FOREGROUND].rchar) ||
88 !ParseUint(fields[size - 9], &io[FOREGROUND].wchar) ||
89 !ParseUint(fields[size - 8], &io[FOREGROUND].read_bytes) ||
90 !ParseUint(fields[size - 7], &io[FOREGROUND].write_bytes) ||
91 !ParseUint(fields[size - 6], &io[BACKGROUND].rchar) ||
92 !ParseUint(fields[size - 5], &io[BACKGROUND].wchar) ||
93 !ParseUint(fields[size - 4], &io[BACKGROUND].read_bytes) ||
94 !ParseUint(fields[size - 3], &io[BACKGROUND].write_bytes) ||
95 !ParseUint(fields[size - 2], &io[FOREGROUND].fsync) ||
96 !ParseUint(fields[size - 1], &io[BACKGROUND].fsync)) {
97 LOG_TO(SYSTEM, WARNING) << "Invalid task I/O stats: \""
Yang Jin3906c892017-06-22 15:18:21 -070098 << s << "\"";
99 return false;
100 }
Jin Qian0e026872017-08-29 11:42:06 -0700101 comm = Join(std::vector<std::string>(
102 fields.begin() + 1, fields.end() - 11), ',');
Yang Jin3906c892017-06-22 15:18:21 -0700103 return true;
104}
105
106bool io_usage::is_zero() const
107{
108 for (int i = 0; i < IO_TYPES; i++) {
109 for (int j = 0; j < UID_STATS; j++) {
110 for (int k = 0; k < CHARGER_STATS; k++) {
111 if (bytes[i][j][k])
112 return false;
113 }
114 }
115 }
116 return true;
117}
118
Jin Qian65dea712017-08-29 16:48:20 -0700119namespace {
120
121void get_uid_names(const vector<int>& uids, const vector<std::string*>& uid_names)
Jin Qian2d7bcce2017-07-28 18:45:59 -0700122{
123 sp<IServiceManager> sm = defaultServiceManager();
124 if (sm == NULL) {
125 LOG_TO(SYSTEM, ERROR) << "defaultServiceManager failed";
126 return;
127 }
128
129 sp<IBinder> binder = sm->getService(String16("package_native"));
130 if (binder == NULL) {
131 LOG_TO(SYSTEM, ERROR) << "getService package_native failed";
132 return;
133 }
134
135 sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
136 std::vector<std::string> names;
137 binder::Status status = package_mgr->getNamesForUids(uids, &names);
138 if (!status.isOk()) {
139 LOG_TO(SYSTEM, ERROR) << "package_native::getNamesForUids failed: "
140 << status.exceptionMessage();
141 return;
142 }
143
144 for (uint32_t i = 0; i < uid_names.size(); i++) {
145 if (!names[i].empty()) {
146 *uid_names[i] = names[i];
147 }
148 }
149
150 refresh_uid_names = false;
151}
152
Jin Qian65dea712017-08-29 16:48:20 -0700153} // namespace
154
Jin Qianb049d182017-10-12 17:02:17 -0700155std::unordered_map<uint32_t, uid_info> uid_monitor::get_uid_io_stats_locked()
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800156{
Jin Qianb049d182017-10-12 17:02:17 -0700157 std::unordered_map<uint32_t, uid_info> uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800158 std::string buffer;
Jin Qian9b1aeae2017-03-14 11:20:02 -0700159 if (!ReadFileToString(UID_IO_STATS_PATH, &buffer)) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800160 PLOG_TO(SYSTEM, ERROR) << UID_IO_STATS_PATH << ": ReadFileToString failed";
Jin Qian5b962c62017-01-30 14:48:38 -0800161 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800162 }
163
Yang Jin3906c892017-06-22 15:18:21 -0700164 std::vector<std::string> io_stats = Split(std::move(buffer), "\n");
Jin Qianb049d182017-10-12 17:02:17 -0700165 uid_info u;
Jin Qian2d7bcce2017-07-28 18:45:59 -0700166 vector<int> uids;
167 vector<std::string*> uid_names;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800168
Jin Qiane83a6102017-03-02 16:16:54 -0800169 for (uint32_t i = 0; i < io_stats.size(); i++) {
170 if (io_stats[i].empty()) {
171 continue;
172 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800173
Yang Jin3906c892017-06-22 15:18:21 -0700174 if (io_stats[i].compare(0, 4, "task")) {
175 if (!u.parse_uid_io_stats(std::move(io_stats[i])))
176 continue;
Yang Jin3906c892017-06-22 15:18:21 -0700177 uid_io_stats[u.uid] = u;
Jin Qian2d7bcce2017-07-28 18:45:59 -0700178 uid_io_stats[u.uid].name = std::to_string(u.uid);
179 uids.push_back(u.uid);
180 uid_names.push_back(&uid_io_stats[u.uid].name);
181 if (last_uid_io_stats.find(u.uid) == last_uid_io_stats.end()) {
182 refresh_uid_names = true;
183 } else {
184 uid_io_stats[u.uid].name = last_uid_io_stats[u.uid].name;
185 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800186 } else {
Jin Qianb049d182017-10-12 17:02:17 -0700187 task_info t;
Yang Jin3906c892017-06-22 15:18:21 -0700188 if (!t.parse_task_io_stats(std::move(io_stats[i])))
189 continue;
190 uid_io_stats[u.uid].tasks[t.pid] = t;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800191 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800192 }
193
Jin Qian2d7bcce2017-07-28 18:45:59 -0700194 if (!uids.empty() && refresh_uid_names) {
195 get_uid_names(uids, uid_names);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800196 }
197
Jin Qian5b962c62017-01-30 14:48:38 -0800198 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800199}
200
Jin Qian65dea712017-08-29 16:48:20 -0700201namespace {
Jin Qiana2e5bd12017-01-24 16:23:13 -0800202
Jin Qian65dea712017-08-29 16:48:20 -0700203const int MAX_UID_RECORDS_SIZE = 1000 * 48; // 1000 uids in 48 hours
204
205inline size_t history_size(
Jin Qianebf031b2017-08-14 16:41:24 -0700206 const std::map<uint64_t, struct uid_records>& history)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800207{
Jin Qianebf031b2017-08-14 16:41:24 -0700208 size_t count = 0;
209 for (auto const& it : history) {
Jin Qian81577752017-02-21 12:09:39 -0800210 count += it.second.entries.size();
Jin Qian5b962c62017-01-30 14:48:38 -0800211 }
212 return count;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800213}
214
Jin Qian65dea712017-08-29 16:48:20 -0700215} // namespace
216
Jin Qian5b962c62017-01-30 14:48:38 -0800217void uid_monitor::add_records_locked(uint64_t curr_ts)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800218{
Jin Qian5b962c62017-01-30 14:48:38 -0800219 // remove records more than 5 days old
220 if (curr_ts > 5 * DAY_TO_SEC) {
Jin Qianebf031b2017-08-14 16:41:24 -0700221 auto it = io_history.lower_bound(curr_ts - 5 * DAY_TO_SEC);
222 io_history.erase(io_history.begin(), it);
Jin Qian9cdfdd32017-01-31 17:33:20 -0800223 }
224
Jin Qian81577752017-02-21 12:09:39 -0800225 struct uid_records new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800226 for (const auto& p : curr_io_stats) {
227 struct uid_record record = {};
228 record.name = p.first;
Yang Jin3906c892017-06-22 15:18:21 -0700229 if (!p.second.uid_ios.is_zero()) {
Jin Qian6df3bc62017-10-18 17:52:14 -0700230 record.ios.user_id = p.second.user_id;
Yang Jin3906c892017-06-22 15:18:21 -0700231 record.ios.uid_ios = p.second.uid_ios;
232 for (const auto& p_task : p.second.task_ios) {
233 if (!p_task.second.is_zero())
234 record.ios.task_ios[p_task.first] = p_task.second;
235 }
Jin Qian81577752017-02-21 12:09:39 -0800236 new_records.entries.push_back(record);
Jin Qian5b962c62017-01-30 14:48:38 -0800237 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800238 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800239
Jin Qian5b962c62017-01-30 14:48:38 -0800240 curr_io_stats.clear();
Jin Qian81577752017-02-21 12:09:39 -0800241 new_records.start_ts = start_ts;
242 start_ts = curr_ts;
Jin Qian9cdfdd32017-01-31 17:33:20 -0800243
Jin Qian81577752017-02-21 12:09:39 -0800244 if (new_records.entries.empty())
Jin Qian5b962c62017-01-30 14:48:38 -0800245 return;
246
247 // make some room for new records
Jin Qianebf031b2017-08-14 16:41:24 -0700248 ssize_t overflow = history_size(io_history) +
Jin Qian81577752017-02-21 12:09:39 -0800249 new_records.entries.size() - MAX_UID_RECORDS_SIZE;
Jin Qianebf031b2017-08-14 16:41:24 -0700250 while (overflow > 0 && io_history.size() > 0) {
251 auto del_it = io_history.begin();
Jin Qian81577752017-02-21 12:09:39 -0800252 overflow -= del_it->second.entries.size();
Jin Qianebf031b2017-08-14 16:41:24 -0700253 io_history.erase(io_history.begin());
Jin Qian5b962c62017-01-30 14:48:38 -0800254 }
255
Jin Qianebf031b2017-08-14 16:41:24 -0700256 io_history[curr_ts] = new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800257}
258
Jin Qian81577752017-02-21 12:09:39 -0800259std::map<uint64_t, struct uid_records> uid_monitor::dump(
Jin Qian94b64ef2017-11-09 15:07:18 -0800260 double hours, uint64_t threshold, bool force_report)
Jin Qian5b962c62017-01-30 14:48:38 -0800261{
Jin Qian1275b1b2017-02-06 14:02:50 -0800262 if (force_report) {
Jin Qian94b64ef2017-11-09 15:07:18 -0800263 report(nullptr);
Jin Qian1275b1b2017-02-06 14:02:50 -0800264 }
265
Jin Qian6df3bc62017-10-18 17:52:14 -0700266 Mutex::Autolock _l(uidm_mutex);
Jin Qian5b962c62017-01-30 14:48:38 -0800267
Jin Qian81577752017-02-21 12:09:39 -0800268 std::map<uint64_t, struct uid_records> dump_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800269 uint64_t first_ts = 0;
270
271 if (hours != 0) {
Jin Qiandd41d6b2017-02-10 17:23:16 -0800272 first_ts = time(NULL) - hours * HOUR_TO_SEC;
Jin Qian5b962c62017-01-30 14:48:38 -0800273 }
274
Jin Qianebf031b2017-08-14 16:41:24 -0700275 for (auto it = io_history.lower_bound(first_ts); it != io_history.end(); ++it) {
Jin Qian81577752017-02-21 12:09:39 -0800276 const std::vector<struct uid_record>& recs = it->second.entries;
277 struct uid_records filtered;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800278
279 for (const auto& rec : recs) {
Yang Jin3906c892017-06-22 15:18:21 -0700280 const io_usage& uid_usage = rec.ios.uid_ios;
281 if (uid_usage.bytes[READ][FOREGROUND][CHARGER_ON] +
282 uid_usage.bytes[READ][FOREGROUND][CHARGER_OFF] +
283 uid_usage.bytes[READ][BACKGROUND][CHARGER_ON] +
284 uid_usage.bytes[READ][BACKGROUND][CHARGER_OFF] +
285 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_ON] +
286 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_OFF] +
287 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_ON] +
288 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_OFF] > threshold) {
Jin Qian81577752017-02-21 12:09:39 -0800289 filtered.entries.push_back(rec);
Jin Qiane5ea17c2017-02-10 10:50:03 -0800290 }
291 }
Jin Qian81577752017-02-21 12:09:39 -0800292
293 if (filtered.entries.empty())
294 continue;
295
296 filtered.start_ts = it->second.start_ts;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800297 dump_records.insert(
Jin Qian81577752017-02-21 12:09:39 -0800298 std::pair<uint64_t, struct uid_records>(it->first, filtered));
Jin Qiane5ea17c2017-02-10 10:50:03 -0800299 }
Jin Qian5b962c62017-01-30 14:48:38 -0800300
301 return dump_records;
302}
303
304void uid_monitor::update_curr_io_stats_locked()
305{
Jin Qianb049d182017-10-12 17:02:17 -0700306 std::unordered_map<uint32_t, uid_info> uid_io_stats =
Jin Qian5b962c62017-01-30 14:48:38 -0800307 get_uid_io_stats_locked();
308 if (uid_io_stats.empty()) {
309 return;
310 }
311
312 for (const auto& it : uid_io_stats) {
Jin Qianb049d182017-10-12 17:02:17 -0700313 const uid_info& uid = it.second;
Jin Qian5b962c62017-01-30 14:48:38 -0800314 if (curr_io_stats.find(uid.name) == curr_io_stats.end()) {
Jin Qian6df3bc62017-10-18 17:52:14 -0700315 curr_io_stats[uid.name] = {};
Jin Qian5b962c62017-01-30 14:48:38 -0800316 }
317
318 struct uid_io_usage& usage = curr_io_stats[uid.name];
Jin Qian6df3bc62017-10-18 17:52:14 -0700319 usage.user_id = multiuser_get_user_id(uid.uid);
320
Jin Qianbaff6402017-02-16 18:34:31 -0800321 int64_t fg_rd_delta = uid.io[FOREGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800322 last_uid_io_stats[uid.uid].io[FOREGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800323 int64_t bg_rd_delta = uid.io[BACKGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800324 last_uid_io_stats[uid.uid].io[BACKGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800325 int64_t fg_wr_delta = uid.io[FOREGROUND].write_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800326 last_uid_io_stats[uid.uid].io[FOREGROUND].write_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800327 int64_t bg_wr_delta = uid.io[BACKGROUND].write_bytes -
328 last_uid_io_stats[uid.uid].io[BACKGROUND].write_bytes;
329
Yang Jin3906c892017-06-22 15:18:21 -0700330 usage.uid_ios.bytes[READ][FOREGROUND][charger_stat] +=
331 (fg_rd_delta < 0) ? 0 : fg_rd_delta;
332 usage.uid_ios.bytes[READ][BACKGROUND][charger_stat] +=
333 (bg_rd_delta < 0) ? 0 : bg_rd_delta;
334 usage.uid_ios.bytes[WRITE][FOREGROUND][charger_stat] +=
335 (fg_wr_delta < 0) ? 0 : fg_wr_delta;
336 usage.uid_ios.bytes[WRITE][BACKGROUND][charger_stat] +=
337 (bg_wr_delta < 0) ? 0 : bg_wr_delta;
338
339 for (const auto& task_it : uid.tasks) {
Jin Qianb049d182017-10-12 17:02:17 -0700340 const task_info& task = task_it.second;
Yang Jin3906c892017-06-22 15:18:21 -0700341 const pid_t pid = task_it.first;
342 const std::string& comm = task_it.second.comm;
343 int64_t task_fg_rd_delta = task.io[FOREGROUND].read_bytes -
344 last_uid_io_stats[uid.uid].tasks[pid].io[FOREGROUND].read_bytes;
345 int64_t task_bg_rd_delta = task.io[BACKGROUND].read_bytes -
346 last_uid_io_stats[uid.uid].tasks[pid].io[BACKGROUND].read_bytes;
347 int64_t task_fg_wr_delta = task.io[FOREGROUND].write_bytes -
348 last_uid_io_stats[uid.uid].tasks[pid].io[FOREGROUND].write_bytes;
349 int64_t task_bg_wr_delta = task.io[BACKGROUND].write_bytes -
350 last_uid_io_stats[uid.uid].tasks[pid].io[BACKGROUND].write_bytes;
351
Jin Qian6df3bc62017-10-18 17:52:14 -0700352 io_usage& task_usage = usage.task_ios[comm];
Yang Jin3906c892017-06-22 15:18:21 -0700353 task_usage.bytes[READ][FOREGROUND][charger_stat] +=
354 (task_fg_rd_delta < 0) ? 0 : task_fg_rd_delta;
355 task_usage.bytes[READ][BACKGROUND][charger_stat] +=
356 (task_bg_rd_delta < 0) ? 0 : task_bg_rd_delta;
357 task_usage.bytes[WRITE][FOREGROUND][charger_stat] +=
358 (task_fg_wr_delta < 0) ? 0 : task_fg_wr_delta;
359 task_usage.bytes[WRITE][BACKGROUND][charger_stat] +=
360 (task_bg_wr_delta < 0) ? 0 : task_bg_wr_delta;
361 }
Jin Qian5b962c62017-01-30 14:48:38 -0800362 }
363
364 last_uid_io_stats = uid_io_stats;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800365}
366
Jin Qian6df3bc62017-10-18 17:52:14 -0700367void uid_monitor::report(unordered_map<int, StoragedProto>* protos)
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800368{
Jin Qiana8533322017-10-13 18:15:34 -0700369 if (!enabled()) return;
370
Jin Qian6df3bc62017-10-18 17:52:14 -0700371 Mutex::Autolock _l(uidm_mutex);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800372
Jin Qian5b962c62017-01-30 14:48:38 -0800373 update_curr_io_stats_locked();
374 add_records_locked(time(NULL));
Jin Qianebf031b2017-08-14 16:41:24 -0700375
Jin Qian94b64ef2017-11-09 15:07:18 -0800376 if (protos) {
377 update_uid_io_proto(protos);
378 }
Jin Qianebf031b2017-08-14 16:41:24 -0700379}
380
Jin Qian65dea712017-08-29 16:48:20 -0700381namespace {
382
Jin Qian6df3bc62017-10-18 17:52:14 -0700383void set_io_usage_proto(IOUsage* usage_proto, const io_usage& usage)
Jin Qianebf031b2017-08-14 16:41:24 -0700384{
385 usage_proto->set_rd_fg_chg_on(usage.bytes[READ][FOREGROUND][CHARGER_ON]);
386 usage_proto->set_rd_fg_chg_off(usage.bytes[READ][FOREGROUND][CHARGER_OFF]);
387 usage_proto->set_rd_bg_chg_on(usage.bytes[READ][BACKGROUND][CHARGER_ON]);
388 usage_proto->set_rd_bg_chg_off(usage.bytes[READ][BACKGROUND][CHARGER_OFF]);
389 usage_proto->set_wr_fg_chg_on(usage.bytes[WRITE][FOREGROUND][CHARGER_ON]);
390 usage_proto->set_wr_fg_chg_off(usage.bytes[WRITE][FOREGROUND][CHARGER_OFF]);
391 usage_proto->set_wr_bg_chg_on(usage.bytes[WRITE][BACKGROUND][CHARGER_ON]);
392 usage_proto->set_wr_bg_chg_off(usage.bytes[WRITE][BACKGROUND][CHARGER_OFF]);
393}
394
Jin Qian6df3bc62017-10-18 17:52:14 -0700395void get_io_usage_proto(io_usage* usage, const IOUsage& io_proto)
Jin Qianebf031b2017-08-14 16:41:24 -0700396{
397 usage->bytes[READ][FOREGROUND][CHARGER_ON] = io_proto.rd_fg_chg_on();
398 usage->bytes[READ][FOREGROUND][CHARGER_OFF] = io_proto.rd_fg_chg_off();
399 usage->bytes[READ][BACKGROUND][CHARGER_ON] = io_proto.rd_bg_chg_on();
400 usage->bytes[READ][BACKGROUND][CHARGER_OFF] = io_proto.rd_bg_chg_off();
401 usage->bytes[WRITE][FOREGROUND][CHARGER_ON] = io_proto.wr_fg_chg_on();
402 usage->bytes[WRITE][FOREGROUND][CHARGER_OFF] = io_proto.wr_fg_chg_off();
403 usage->bytes[WRITE][BACKGROUND][CHARGER_ON] = io_proto.wr_bg_chg_on();
404 usage->bytes[WRITE][BACKGROUND][CHARGER_OFF] = io_proto.wr_bg_chg_off();
405}
406
Jin Qian65dea712017-08-29 16:48:20 -0700407} // namespace
408
Jin Qian6df3bc62017-10-18 17:52:14 -0700409void uid_monitor::update_uid_io_proto(unordered_map<int, StoragedProto>* protos)
Jin Qianebf031b2017-08-14 16:41:24 -0700410{
Jin Qianebf031b2017-08-14 16:41:24 -0700411 for (const auto& item : io_history) {
412 const uint64_t& end_ts = item.first;
413 const struct uid_records& recs = item.second;
Jin Qian6df3bc62017-10-18 17:52:14 -0700414 unordered_map<userid_t, UidIOItem*> user_items;
Jin Qianebf031b2017-08-14 16:41:24 -0700415
416 for (const auto& entry : recs.entries) {
Jin Qian6df3bc62017-10-18 17:52:14 -0700417 userid_t user_id = entry.ios.user_id;
418 UidIOItem* item_proto = user_items[user_id];
419 if (item_proto == nullptr) {
420 item_proto = (*protos)[user_id].mutable_uid_io_usage()
421 ->add_uid_io_items();
422 user_items[user_id] = item_proto;
423 }
424 item_proto->set_end_ts(end_ts);
425
426 UidIORecords* recs_proto = item_proto->mutable_records();
427 recs_proto->set_start_ts(recs.start_ts);
428
Jin Qianebf031b2017-08-14 16:41:24 -0700429 UidRecord* rec_proto = recs_proto->add_entries();
430 rec_proto->set_uid_name(entry.name);
Jin Qian6df3bc62017-10-18 17:52:14 -0700431 rec_proto->set_user_id(user_id);
Jin Qianebf031b2017-08-14 16:41:24 -0700432
433 IOUsage* uid_io_proto = rec_proto->mutable_uid_io();
Jin Qian6df3bc62017-10-18 17:52:14 -0700434 const io_usage& uio_ios = entry.ios.uid_ios;
Jin Qianebf031b2017-08-14 16:41:24 -0700435 set_io_usage_proto(uid_io_proto, uio_ios);
436
437 for (const auto& task_io : entry.ios.task_ios) {
438 const std::string& task_name = task_io.first;
Jin Qian6df3bc62017-10-18 17:52:14 -0700439 const io_usage& task_ios = task_io.second;
Jin Qianebf031b2017-08-14 16:41:24 -0700440
441 TaskIOUsage* task_io_proto = rec_proto->add_task_io();
442 task_io_proto->set_task_name(task_name);
443 set_io_usage_proto(task_io_proto->mutable_ios(), task_ios);
444 }
445 }
446 }
Jin Qianebf031b2017-08-14 16:41:24 -0700447}
448
Jin Qian94b64ef2017-11-09 15:07:18 -0800449void uid_monitor::clear_user_history(userid_t user_id)
450{
451 Mutex::Autolock _l(uidm_mutex);
452
453 for (auto& item : io_history) {
454 vector<uid_record>* entries = &item.second.entries;
455 entries->erase(
456 remove_if(entries->begin(), entries->end(),
457 [user_id](const uid_record& rec) {
458 return rec.ios.user_id == user_id;}),
459 entries->end());
460 }
461
462 for (auto it = io_history.begin(); it != io_history.end(); ) {
463 if (it->second.entries.empty()) {
464 it = io_history.erase(it);
465 } else {
466 it++;
467 }
468 }
469}
470
Jin Qiand691d6e2017-09-28 16:02:22 -0700471void uid_monitor::load_uid_io_proto(const UidIOUsage& uid_io_proto)
Jin Qianebf031b2017-08-14 16:41:24 -0700472{
Jin Qiana8533322017-10-13 18:15:34 -0700473 if (!enabled()) return;
474
Jin Qian94b64ef2017-11-09 15:07:18 -0800475 Mutex::Autolock _l(uidm_mutex);
476
Jin Qiand691d6e2017-09-28 16:02:22 -0700477 for (const auto& item_proto : uid_io_proto.uid_io_items()) {
Jin Qianebf031b2017-08-14 16:41:24 -0700478 const UidIORecords& records_proto = item_proto.records();
479 struct uid_records* recs = &io_history[item_proto.end_ts()];
480
481 recs->start_ts = records_proto.start_ts();
482 for (const auto& rec_proto : records_proto.entries()) {
483 struct uid_record record;
484 record.name = rec_proto.uid_name();
Jin Qian6df3bc62017-10-18 17:52:14 -0700485 record.ios.user_id = rec_proto.user_id();
Jin Qianebf031b2017-08-14 16:41:24 -0700486 get_io_usage_proto(&record.ios.uid_ios, rec_proto.uid_io());
487
488 for (const auto& task_io_proto : rec_proto.task_io()) {
489 get_io_usage_proto(
490 &record.ios.task_ios[task_io_proto.task_name()],
491 task_io_proto.ios());
492 }
493 recs->entries.push_back(record);
494 }
495 }
Jin Qian5b962c62017-01-30 14:48:38 -0800496}
497
498void uid_monitor::set_charger_state(charger_stat_t stat)
499{
Jin Qian6df3bc62017-10-18 17:52:14 -0700500 Mutex::Autolock _l(uidm_mutex);
Jin Qian5b962c62017-01-30 14:48:38 -0800501
502 if (charger_stat == stat) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800503 return;
504 }
505
Jin Qian5b962c62017-01-30 14:48:38 -0800506 update_curr_io_stats_locked();
507 charger_stat = stat;
508}
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800509
Jin Qiana8533322017-10-13 18:15:34 -0700510void uid_monitor::init(charger_stat_t stat)
Jin Qian5b962c62017-01-30 14:48:38 -0800511{
512 charger_stat = stat;
Jin Qianebf031b2017-08-14 16:41:24 -0700513
Jin Qian81577752017-02-21 12:09:39 -0800514 start_ts = time(NULL);
Jin Qian5b962c62017-01-30 14:48:38 -0800515 last_uid_io_stats = get_uid_io_stats();
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800516}
517
518uid_monitor::uid_monitor()
Jin Qian6df3bc62017-10-18 17:52:14 -0700519 : enable(!access(UID_IO_STATS_PATH, R_OK)) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800520}