blob: 1c98477d54d40dbb0653c679567351b076beedd1 [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>
Jin Qianebf031b2017-08-14 16:41:24 -070020#include <stdio.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080021#include <time.h>
Jin Qianebf031b2017-08-14 16:41:24 -070022#include <zlib.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080023
Jin Qianebf031b2017-08-14 16:41:24 -070024#include <fstream>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080025#include <string>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080026#include <unordered_map>
27
Jin Qian2d7bcce2017-07-28 18:45:59 -070028#include <android/content/pm/IPackageManagerNative.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080029#include <android-base/file.h>
30#include <android-base/logging.h>
31#include <android-base/macros.h>
Jin Qian9b1aeae2017-03-14 11:20:02 -070032#include <android-base/parseint.h>
Jin Qiane83a6102017-03-02 16:16:54 -080033#include <android-base/strings.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080034#include <android-base/stringprintf.h>
Jin Qian2d7bcce2017-07-28 18:45:59 -070035#include <binder/IServiceManager.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080036#include <log/log_event_list.h>
Jin Qianbcd6e3b2016-12-28 15:43:51 -080037
38#include "storaged.h"
39#include "storaged_uid_monitor.h"
Jin Qianebf031b2017-08-14 16:41:24 -070040#include "system/core/storaged/storaged.pb.h"
Jin Qianbcd6e3b2016-12-28 15:43:51 -080041
Jin Qianbcd6e3b2016-12-28 15:43:51 -080042using namespace android;
43using namespace android::base;
Jin Qian2d7bcce2017-07-28 18:45:59 -070044using namespace android::content::pm;
Jin Qianebf031b2017-08-14 16:41:24 -070045using namespace google::protobuf::io;
46using namespace storaged_proto;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080047
Jin Qian2d7bcce2017-07-28 18:45:59 -070048static bool refresh_uid_names;
Jin Qianebf031b2017-08-14 16:41:24 -070049static const uint32_t crc_init = 0x5108A4ED; /* STORAGED */
50
51const std::string uid_monitor::io_history_proto_file =
52 "/data/misc/storaged/io_history.proto";
Jin Qianbcd6e3b2016-12-28 15:43:51 -080053
Jin Qian5b962c62017-01-30 14:48:38 -080054std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats()
Jin Qianbcd6e3b2016-12-28 15:43:51 -080055{
Jin Qian5b962c62017-01-30 14:48:38 -080056 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
57 return get_uid_io_stats_locked();
58};
Jin Qianbcd6e3b2016-12-28 15:43:51 -080059
Yang Jin3906c892017-06-22 15:18:21 -070060/* return true on parse success and false on failure */
61bool uid_info::parse_uid_io_stats(std::string&& s)
62{
63 std::vector<std::string> fields = Split(s, " ");
64 if (fields.size() < 11 ||
65 !ParseUint(fields[0], &uid) ||
66 !ParseUint(fields[1], &io[FOREGROUND].rchar) ||
67 !ParseUint(fields[2], &io[FOREGROUND].wchar) ||
68 !ParseUint(fields[3], &io[FOREGROUND].read_bytes) ||
69 !ParseUint(fields[4], &io[FOREGROUND].write_bytes) ||
70 !ParseUint(fields[5], &io[BACKGROUND].rchar) ||
71 !ParseUint(fields[6], &io[BACKGROUND].wchar) ||
72 !ParseUint(fields[7], &io[BACKGROUND].read_bytes) ||
73 !ParseUint(fields[8], &io[BACKGROUND].write_bytes) ||
74 !ParseUint(fields[9], &io[FOREGROUND].fsync) ||
75 !ParseUint(fields[10], &io[BACKGROUND].fsync)) {
76 LOG_TO(SYSTEM, WARNING) << "Invalid I/O stats: \""
77 << s << "\"";
78 return false;
79 }
80 return true;
81}
82
83/* return true on parse success and false on failure */
84bool task_info::parse_task_io_stats(std::string&& s)
85{
86 std::vector<std::string> fields = Split(s, ",");
87 if (fields.size() < 13 ||
88 !ParseInt(fields[2], &pid) ||
89 !ParseUint(fields[3], &io[FOREGROUND].rchar) ||
90 !ParseUint(fields[4], &io[FOREGROUND].wchar) ||
91 !ParseUint(fields[5], &io[FOREGROUND].read_bytes) ||
92 !ParseUint(fields[6], &io[FOREGROUND].write_bytes) ||
93 !ParseUint(fields[7], &io[BACKGROUND].rchar) ||
94 !ParseUint(fields[8], &io[BACKGROUND].wchar) ||
95 !ParseUint(fields[9], &io[BACKGROUND].read_bytes) ||
96 !ParseUint(fields[10], &io[BACKGROUND].write_bytes) ||
97 !ParseUint(fields[11], &io[FOREGROUND].fsync) ||
98 !ParseUint(fields[12], &io[BACKGROUND].fsync)) {
99 LOG_TO(SYSTEM, WARNING) << "Invalid I/O stats: \""
100 << s << "\"";
101 return false;
102 }
103 comm = fields[1];
104 return true;
105}
106
107bool io_usage::is_zero() const
108{
109 for (int i = 0; i < IO_TYPES; i++) {
110 for (int j = 0; j < UID_STATS; j++) {
111 for (int k = 0; k < CHARGER_STATS; k++) {
112 if (bytes[i][j][k])
113 return false;
114 }
115 }
116 }
117 return true;
118}
119
Jin Qian2d7bcce2017-07-28 18:45:59 -0700120static void get_uid_names(const vector<int>& uids, const vector<std::string*>& uid_names)
121{
122 sp<IServiceManager> sm = defaultServiceManager();
123 if (sm == NULL) {
124 LOG_TO(SYSTEM, ERROR) << "defaultServiceManager failed";
125 return;
126 }
127
128 sp<IBinder> binder = sm->getService(String16("package_native"));
129 if (binder == NULL) {
130 LOG_TO(SYSTEM, ERROR) << "getService package_native failed";
131 return;
132 }
133
134 sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
135 std::vector<std::string> names;
136 binder::Status status = package_mgr->getNamesForUids(uids, &names);
137 if (!status.isOk()) {
138 LOG_TO(SYSTEM, ERROR) << "package_native::getNamesForUids failed: "
139 << status.exceptionMessage();
140 return;
141 }
142
143 for (uint32_t i = 0; i < uid_names.size(); i++) {
144 if (!names[i].empty()) {
145 *uid_names[i] = names[i];
146 }
147 }
148
149 refresh_uid_names = false;
150}
151
Jin Qian5b962c62017-01-30 14:48:38 -0800152std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats_locked()
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800153{
Jin Qian5b962c62017-01-30 14:48:38 -0800154 std::unordered_map<uint32_t, struct uid_info> uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800155 std::string buffer;
Jin Qian9b1aeae2017-03-14 11:20:02 -0700156 if (!ReadFileToString(UID_IO_STATS_PATH, &buffer)) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800157 PLOG_TO(SYSTEM, ERROR) << UID_IO_STATS_PATH << ": ReadFileToString failed";
Jin Qian5b962c62017-01-30 14:48:38 -0800158 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800159 }
160
Yang Jin3906c892017-06-22 15:18:21 -0700161 std::vector<std::string> io_stats = Split(std::move(buffer), "\n");
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800162 struct uid_info u;
Jin Qian2d7bcce2017-07-28 18:45:59 -0700163 vector<int> uids;
164 vector<std::string*> uid_names;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800165
Jin Qiane83a6102017-03-02 16:16:54 -0800166 for (uint32_t i = 0; i < io_stats.size(); i++) {
167 if (io_stats[i].empty()) {
168 continue;
169 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800170
Yang Jin3906c892017-06-22 15:18:21 -0700171 if (io_stats[i].compare(0, 4, "task")) {
172 if (!u.parse_uid_io_stats(std::move(io_stats[i])))
173 continue;
Yang Jin3906c892017-06-22 15:18:21 -0700174 uid_io_stats[u.uid] = u;
Jin Qian2d7bcce2017-07-28 18:45:59 -0700175 uid_io_stats[u.uid].name = std::to_string(u.uid);
176 uids.push_back(u.uid);
177 uid_names.push_back(&uid_io_stats[u.uid].name);
178 if (last_uid_io_stats.find(u.uid) == last_uid_io_stats.end()) {
179 refresh_uid_names = true;
180 } else {
181 uid_io_stats[u.uid].name = last_uid_io_stats[u.uid].name;
182 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800183 } else {
Yang Jin3906c892017-06-22 15:18:21 -0700184 struct task_info t;
185 if (!t.parse_task_io_stats(std::move(io_stats[i])))
186 continue;
187 uid_io_stats[u.uid].tasks[t.pid] = t;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800188 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800189 }
190
Jin Qian2d7bcce2017-07-28 18:45:59 -0700191 if (!uids.empty() && refresh_uid_names) {
192 get_uid_names(uids, uid_names);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800193 }
194
Jin Qian5b962c62017-01-30 14:48:38 -0800195 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800196}
197
Jin Qian5b962c62017-01-30 14:48:38 -0800198static const int MAX_UID_RECORDS_SIZE = 1000 * 48; // 1000 uids in 48 hours
Jin Qiana2e5bd12017-01-24 16:23:13 -0800199
Jin Qianebf031b2017-08-14 16:41:24 -0700200static inline size_t history_size(
201 const std::map<uint64_t, struct uid_records>& history)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800202{
Jin Qianebf031b2017-08-14 16:41:24 -0700203 size_t count = 0;
204 for (auto const& it : history) {
Jin Qian81577752017-02-21 12:09:39 -0800205 count += it.second.entries.size();
Jin Qian5b962c62017-01-30 14:48:38 -0800206 }
207 return count;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800208}
209
Jin Qian5b962c62017-01-30 14:48:38 -0800210void uid_monitor::add_records_locked(uint64_t curr_ts)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800211{
Jin Qian5b962c62017-01-30 14:48:38 -0800212 // remove records more than 5 days old
213 if (curr_ts > 5 * DAY_TO_SEC) {
Jin Qianebf031b2017-08-14 16:41:24 -0700214 auto it = io_history.lower_bound(curr_ts - 5 * DAY_TO_SEC);
215 io_history.erase(io_history.begin(), it);
Jin Qian9cdfdd32017-01-31 17:33:20 -0800216 }
217
Jin Qian81577752017-02-21 12:09:39 -0800218 struct uid_records new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800219 for (const auto& p : curr_io_stats) {
220 struct uid_record record = {};
221 record.name = p.first;
Yang Jin3906c892017-06-22 15:18:21 -0700222 if (!p.second.uid_ios.is_zero()) {
223 record.ios.uid_ios = p.second.uid_ios;
224 for (const auto& p_task : p.second.task_ios) {
225 if (!p_task.second.is_zero())
226 record.ios.task_ios[p_task.first] = p_task.second;
227 }
Jin Qian81577752017-02-21 12:09:39 -0800228 new_records.entries.push_back(record);
Jin Qian5b962c62017-01-30 14:48:38 -0800229 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800230 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800231
Jin Qian5b962c62017-01-30 14:48:38 -0800232 curr_io_stats.clear();
Jin Qian81577752017-02-21 12:09:39 -0800233 new_records.start_ts = start_ts;
234 start_ts = curr_ts;
Jin Qian9cdfdd32017-01-31 17:33:20 -0800235
Jin Qian81577752017-02-21 12:09:39 -0800236 if (new_records.entries.empty())
Jin Qian5b962c62017-01-30 14:48:38 -0800237 return;
238
239 // make some room for new records
Jin Qianebf031b2017-08-14 16:41:24 -0700240 ssize_t overflow = history_size(io_history) +
Jin Qian81577752017-02-21 12:09:39 -0800241 new_records.entries.size() - MAX_UID_RECORDS_SIZE;
Jin Qianebf031b2017-08-14 16:41:24 -0700242 while (overflow > 0 && io_history.size() > 0) {
243 auto del_it = io_history.begin();
Jin Qian81577752017-02-21 12:09:39 -0800244 overflow -= del_it->second.entries.size();
Jin Qianebf031b2017-08-14 16:41:24 -0700245 io_history.erase(io_history.begin());
Jin Qian5b962c62017-01-30 14:48:38 -0800246 }
247
Jin Qianebf031b2017-08-14 16:41:24 -0700248 io_history[curr_ts] = new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800249}
250
Jin Qian81577752017-02-21 12:09:39 -0800251std::map<uint64_t, struct uid_records> uid_monitor::dump(
Jin Qiandd41d6b2017-02-10 17:23:16 -0800252 double hours, uint64_t threshold, bool force_report)
Jin Qian5b962c62017-01-30 14:48:38 -0800253{
Jin Qian1275b1b2017-02-06 14:02:50 -0800254 if (force_report) {
255 report();
256 }
257
Jin Qian5b962c62017-01-30 14:48:38 -0800258 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
259
Jin Qian81577752017-02-21 12:09:39 -0800260 std::map<uint64_t, struct uid_records> dump_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800261 uint64_t first_ts = 0;
262
263 if (hours != 0) {
Jin Qiandd41d6b2017-02-10 17:23:16 -0800264 first_ts = time(NULL) - hours * HOUR_TO_SEC;
Jin Qian5b962c62017-01-30 14:48:38 -0800265 }
266
Jin Qianebf031b2017-08-14 16:41:24 -0700267 for (auto it = io_history.lower_bound(first_ts); it != io_history.end(); ++it) {
Jin Qian81577752017-02-21 12:09:39 -0800268 const std::vector<struct uid_record>& recs = it->second.entries;
269 struct uid_records filtered;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800270
271 for (const auto& rec : recs) {
Yang Jin3906c892017-06-22 15:18:21 -0700272 const io_usage& uid_usage = rec.ios.uid_ios;
273 if (uid_usage.bytes[READ][FOREGROUND][CHARGER_ON] +
274 uid_usage.bytes[READ][FOREGROUND][CHARGER_OFF] +
275 uid_usage.bytes[READ][BACKGROUND][CHARGER_ON] +
276 uid_usage.bytes[READ][BACKGROUND][CHARGER_OFF] +
277 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_ON] +
278 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_OFF] +
279 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_ON] +
280 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_OFF] > threshold) {
Jin Qian81577752017-02-21 12:09:39 -0800281 filtered.entries.push_back(rec);
Jin Qiane5ea17c2017-02-10 10:50:03 -0800282 }
283 }
Jin Qian81577752017-02-21 12:09:39 -0800284
285 if (filtered.entries.empty())
286 continue;
287
288 filtered.start_ts = it->second.start_ts;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800289 dump_records.insert(
Jin Qian81577752017-02-21 12:09:39 -0800290 std::pair<uint64_t, struct uid_records>(it->first, filtered));
Jin Qiane5ea17c2017-02-10 10:50:03 -0800291 }
Jin Qian5b962c62017-01-30 14:48:38 -0800292
293 return dump_records;
294}
295
296void uid_monitor::update_curr_io_stats_locked()
297{
298 std::unordered_map<uint32_t, struct uid_info> uid_io_stats =
299 get_uid_io_stats_locked();
300 if (uid_io_stats.empty()) {
301 return;
302 }
303
304 for (const auto& it : uid_io_stats) {
305 const struct uid_info& uid = it.second;
306
307 if (curr_io_stats.find(uid.name) == curr_io_stats.end()) {
308 curr_io_stats[uid.name] = {};
309 }
310
311 struct uid_io_usage& usage = curr_io_stats[uid.name];
Jin Qianbaff6402017-02-16 18:34:31 -0800312 int64_t fg_rd_delta = uid.io[FOREGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800313 last_uid_io_stats[uid.uid].io[FOREGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800314 int64_t bg_rd_delta = uid.io[BACKGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800315 last_uid_io_stats[uid.uid].io[BACKGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800316 int64_t fg_wr_delta = uid.io[FOREGROUND].write_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800317 last_uid_io_stats[uid.uid].io[FOREGROUND].write_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800318 int64_t bg_wr_delta = uid.io[BACKGROUND].write_bytes -
319 last_uid_io_stats[uid.uid].io[BACKGROUND].write_bytes;
320
Yang Jin3906c892017-06-22 15:18:21 -0700321 usage.uid_ios.bytes[READ][FOREGROUND][charger_stat] +=
322 (fg_rd_delta < 0) ? 0 : fg_rd_delta;
323 usage.uid_ios.bytes[READ][BACKGROUND][charger_stat] +=
324 (bg_rd_delta < 0) ? 0 : bg_rd_delta;
325 usage.uid_ios.bytes[WRITE][FOREGROUND][charger_stat] +=
326 (fg_wr_delta < 0) ? 0 : fg_wr_delta;
327 usage.uid_ios.bytes[WRITE][BACKGROUND][charger_stat] +=
328 (bg_wr_delta < 0) ? 0 : bg_wr_delta;
329
330 for (const auto& task_it : uid.tasks) {
331 const struct task_info& task = task_it.second;
332 const pid_t pid = task_it.first;
333 const std::string& comm = task_it.second.comm;
334 int64_t task_fg_rd_delta = task.io[FOREGROUND].read_bytes -
335 last_uid_io_stats[uid.uid].tasks[pid].io[FOREGROUND].read_bytes;
336 int64_t task_bg_rd_delta = task.io[BACKGROUND].read_bytes -
337 last_uid_io_stats[uid.uid].tasks[pid].io[BACKGROUND].read_bytes;
338 int64_t task_fg_wr_delta = task.io[FOREGROUND].write_bytes -
339 last_uid_io_stats[uid.uid].tasks[pid].io[FOREGROUND].write_bytes;
340 int64_t task_bg_wr_delta = task.io[BACKGROUND].write_bytes -
341 last_uid_io_stats[uid.uid].tasks[pid].io[BACKGROUND].write_bytes;
342
343 struct io_usage& task_usage = usage.task_ios[comm];
344 task_usage.bytes[READ][FOREGROUND][charger_stat] +=
345 (task_fg_rd_delta < 0) ? 0 : task_fg_rd_delta;
346 task_usage.bytes[READ][BACKGROUND][charger_stat] +=
347 (task_bg_rd_delta < 0) ? 0 : task_bg_rd_delta;
348 task_usage.bytes[WRITE][FOREGROUND][charger_stat] +=
349 (task_fg_wr_delta < 0) ? 0 : task_fg_wr_delta;
350 task_usage.bytes[WRITE][BACKGROUND][charger_stat] +=
351 (task_bg_wr_delta < 0) ? 0 : task_bg_wr_delta;
352 }
Jin Qian5b962c62017-01-30 14:48:38 -0800353 }
354
355 last_uid_io_stats = uid_io_stats;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800356}
357
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800358void uid_monitor::report()
359{
Jin Qian5b962c62017-01-30 14:48:38 -0800360 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800361
Jin Qian5b962c62017-01-30 14:48:38 -0800362 update_curr_io_stats_locked();
363 add_records_locked(time(NULL));
Jin Qianebf031b2017-08-14 16:41:24 -0700364
365 flush_io_history_to_proto();
366}
367
368static void set_io_usage_proto(IOUsage* usage_proto, const struct io_usage& usage)
369{
370 usage_proto->set_rd_fg_chg_on(usage.bytes[READ][FOREGROUND][CHARGER_ON]);
371 usage_proto->set_rd_fg_chg_off(usage.bytes[READ][FOREGROUND][CHARGER_OFF]);
372 usage_proto->set_rd_bg_chg_on(usage.bytes[READ][BACKGROUND][CHARGER_ON]);
373 usage_proto->set_rd_bg_chg_off(usage.bytes[READ][BACKGROUND][CHARGER_OFF]);
374 usage_proto->set_wr_fg_chg_on(usage.bytes[WRITE][FOREGROUND][CHARGER_ON]);
375 usage_proto->set_wr_fg_chg_off(usage.bytes[WRITE][FOREGROUND][CHARGER_OFF]);
376 usage_proto->set_wr_bg_chg_on(usage.bytes[WRITE][BACKGROUND][CHARGER_ON]);
377 usage_proto->set_wr_bg_chg_off(usage.bytes[WRITE][BACKGROUND][CHARGER_OFF]);
378}
379
380static void get_io_usage_proto(struct io_usage* usage, const IOUsage& io_proto)
381{
382 usage->bytes[READ][FOREGROUND][CHARGER_ON] = io_proto.rd_fg_chg_on();
383 usage->bytes[READ][FOREGROUND][CHARGER_OFF] = io_proto.rd_fg_chg_off();
384 usage->bytes[READ][BACKGROUND][CHARGER_ON] = io_proto.rd_bg_chg_on();
385 usage->bytes[READ][BACKGROUND][CHARGER_OFF] = io_proto.rd_bg_chg_off();
386 usage->bytes[WRITE][FOREGROUND][CHARGER_ON] = io_proto.wr_fg_chg_on();
387 usage->bytes[WRITE][FOREGROUND][CHARGER_OFF] = io_proto.wr_fg_chg_off();
388 usage->bytes[WRITE][BACKGROUND][CHARGER_ON] = io_proto.wr_bg_chg_on();
389 usage->bytes[WRITE][BACKGROUND][CHARGER_OFF] = io_proto.wr_bg_chg_off();
390}
391
392void uid_monitor::flush_io_history_to_proto()
393{
394 UidIOHistoryProto out_proto;
395
396 for (const auto& item : io_history) {
397 const uint64_t& end_ts = item.first;
398 const struct uid_records& recs = item.second;
399
400 UidIOItem* item_proto = out_proto.add_items();
401 item_proto->set_end_ts(end_ts);
402
403 UidIORecords* recs_proto = item_proto->mutable_records();
404 recs_proto->set_start_ts(recs.start_ts);
405
406 for (const auto& entry : recs.entries) {
407 UidRecord* rec_proto = recs_proto->add_entries();
408 rec_proto->set_uid_name(entry.name);
409
410 IOUsage* uid_io_proto = rec_proto->mutable_uid_io();
411 const struct io_usage& uio_ios = entry.ios.uid_ios;
412 set_io_usage_proto(uid_io_proto, uio_ios);
413
414 for (const auto& task_io : entry.ios.task_ios) {
415 const std::string& task_name = task_io.first;
416 const struct io_usage& task_ios = task_io.second;
417
418 TaskIOUsage* task_io_proto = rec_proto->add_task_io();
419 task_io_proto->set_task_name(task_name);
420 set_io_usage_proto(task_io_proto->mutable_ios(), task_ios);
421 }
422 }
423 }
424
425 out_proto.set_crc(crc_init);
426 std::string out_proto_str = out_proto.SerializeAsString();
427 out_proto.set_crc(crc32(crc_init,
428 reinterpret_cast<const Bytef*>(out_proto_str.c_str()),
429 out_proto_str.size()));
430
431 std::string tmp_file = io_history_proto_file + "_tmp";
432 std::ofstream out(tmp_file,
433 std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
434 out << out_proto.SerializeAsString();
435 out.close();
436
437 /* Atomically replace existing proto file to reduce chance of data loss. */
438 rename(tmp_file.c_str(), io_history_proto_file.c_str());
439}
440
441void uid_monitor::load_io_history_from_proto()
442{
443 std::ifstream in(io_history_proto_file,
444 std::ofstream::in | std::ofstream::binary);
445
446 if (!in.good()) {
447 PLOG_TO(SYSTEM, INFO) << "Open " << io_history_proto_file << " failed";
448 return;
449 }
450
451 stringstream ss;
452 ss << in.rdbuf();
453 UidIOHistoryProto in_proto;
454 in_proto.ParseFromString(ss.str());
455
456 uint32_t crc = in_proto.crc();
457 in_proto.set_crc(crc_init);
458 std::string io_proto_str = in_proto.SerializeAsString();
459 uint32_t computed_crc = crc32(crc_init,
460 reinterpret_cast<const Bytef*>(io_proto_str.c_str()),
461 io_proto_str.size());
462
463 if (crc != computed_crc) {
464 LOG_TO(SYSTEM, WARNING) << "CRC mismatch in " << io_history_proto_file;
465 return;
466 }
467
468 for (const auto& item_proto : in_proto.items()) {
469 const UidIORecords& records_proto = item_proto.records();
470 struct uid_records* recs = &io_history[item_proto.end_ts()];
471
472 recs->start_ts = records_proto.start_ts();
473 for (const auto& rec_proto : records_proto.entries()) {
474 struct uid_record record;
475 record.name = rec_proto.uid_name();
476 get_io_usage_proto(&record.ios.uid_ios, rec_proto.uid_io());
477
478 for (const auto& task_io_proto : rec_proto.task_io()) {
479 get_io_usage_proto(
480 &record.ios.task_ios[task_io_proto.task_name()],
481 task_io_proto.ios());
482 }
483 recs->entries.push_back(record);
484 }
485 }
Jin Qian5b962c62017-01-30 14:48:38 -0800486}
487
488void uid_monitor::set_charger_state(charger_stat_t stat)
489{
490 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
491
492 if (charger_stat == stat) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800493 return;
494 }
495
Jin Qian5b962c62017-01-30 14:48:38 -0800496 update_curr_io_stats_locked();
497 charger_stat = stat;
498}
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800499
Jin Qian5b962c62017-01-30 14:48:38 -0800500void uid_monitor::init(charger_stat_t stat)
501{
502 charger_stat = stat;
Jin Qianebf031b2017-08-14 16:41:24 -0700503
504 load_io_history_from_proto();
505
Jin Qian81577752017-02-21 12:09:39 -0800506 start_ts = time(NULL);
Jin Qian5b962c62017-01-30 14:48:38 -0800507 last_uid_io_stats = get_uid_io_stats();
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800508}
509
510uid_monitor::uid_monitor()
511{
Jin Qian5b962c62017-01-30 14:48:38 -0800512 sem_init(&um_lock, 0, 1);
Jin Qiana2e5bd12017-01-24 16:23:13 -0800513}
514
515uid_monitor::~uid_monitor()
516{
Jin Qian5b962c62017-01-30 14:48:38 -0800517 sem_destroy(&um_lock);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800518}