blob: dd8bdd6e8b68cd517e53080561e0da306719375a [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 Qian9c542682017-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 Qian9c542682017-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 Qian9c542682017-07-28 18:45:59 -070040using namespace android::content::pm;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080041
Jin Qian9c542682017-07-28 18:45:59 -070042static bool refresh_uid_names;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080043
Jin Qian5b962c62017-01-30 14:48:38 -080044std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats()
Jin Qianbcd6e3b2016-12-28 15:43:51 -080045{
Jin Qian5b962c62017-01-30 14:48:38 -080046 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
47 return get_uid_io_stats_locked();
48};
Jin Qianbcd6e3b2016-12-28 15:43:51 -080049
Jin Qian9c542682017-07-28 18:45:59 -070050static void get_uid_names(const vector<int>& uids, const vector<std::string*>& uid_names)
51{
52 sp<IServiceManager> sm = defaultServiceManager();
53 if (sm == NULL) {
54 LOG_TO(SYSTEM, ERROR) << "defaultServiceManager failed";
55 return;
56 }
57
58 sp<IBinder> binder = sm->getService(String16("package_native"));
59 if (binder == NULL) {
60 LOG_TO(SYSTEM, ERROR) << "getService package_native failed";
61 return;
62 }
63
64 sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
65 std::vector<std::string> names;
66 binder::Status status = package_mgr->getNamesForUids(uids, &names);
67 if (!status.isOk()) {
68 LOG_TO(SYSTEM, ERROR) << "package_native::getNamesForUids failed: "
69 << status.exceptionMessage();
70 return;
71 }
72
73 for (uint32_t i = 0; i < uid_names.size(); i++) {
74 if (!names[i].empty()) {
75 *uid_names[i] = names[i];
76 }
77 }
78
79 refresh_uid_names = false;
80}
81
Jin Qian5b962c62017-01-30 14:48:38 -080082std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats_locked()
Jin Qianbcd6e3b2016-12-28 15:43:51 -080083{
Jin Qian5b962c62017-01-30 14:48:38 -080084 std::unordered_map<uint32_t, struct uid_info> uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080085 std::string buffer;
Jin Qian9b1aeae2017-03-14 11:20:02 -070086 if (!ReadFileToString(UID_IO_STATS_PATH, &buffer)) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -080087 PLOG_TO(SYSTEM, ERROR) << UID_IO_STATS_PATH << ": ReadFileToString failed";
Jin Qian5b962c62017-01-30 14:48:38 -080088 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080089 }
90
Jin Qian9b1aeae2017-03-14 11:20:02 -070091 std::vector<std::string> io_stats = Split(buffer, "\n");
Jin Qianbcd6e3b2016-12-28 15:43:51 -080092 struct uid_info u;
Jin Qian9c542682017-07-28 18:45:59 -070093 vector<int> uids;
94 vector<std::string*> uid_names;
Jin Qianbcd6e3b2016-12-28 15:43:51 -080095
Jin Qiane83a6102017-03-02 16:16:54 -080096 for (uint32_t i = 0; i < io_stats.size(); i++) {
97 if (io_stats[i].empty()) {
98 continue;
99 }
Jin Qian9b1aeae2017-03-14 11:20:02 -0700100 std::vector<std::string> fields = Split(io_stats[i], " ");
101 if (fields.size() < 11 ||
102 !ParseUint(fields[0], &u.uid) ||
103 !ParseUint(fields[1], &u.io[FOREGROUND].rchar) ||
104 !ParseUint(fields[2], &u.io[FOREGROUND].wchar) ||
105 !ParseUint(fields[3], &u.io[FOREGROUND].read_bytes) ||
106 !ParseUint(fields[4], &u.io[FOREGROUND].write_bytes) ||
107 !ParseUint(fields[5], &u.io[BACKGROUND].rchar) ||
108 !ParseUint(fields[6], &u.io[BACKGROUND].wchar) ||
109 !ParseUint(fields[7], &u.io[BACKGROUND].read_bytes) ||
110 !ParseUint(fields[8], &u.io[BACKGROUND].write_bytes) ||
111 !ParseUint(fields[9], &u.io[FOREGROUND].fsync) ||
112 !ParseUint(fields[10], &u.io[BACKGROUND].fsync)) {
113 LOG_TO(SYSTEM, WARNING) << "Invalid I/O stats: \""
Jin Qiane83a6102017-03-02 16:16:54 -0800114 << io_stats[i] << "\"";
115 continue;
116 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800117
Jin Qian5b962c62017-01-30 14:48:38 -0800118 uid_io_stats[u.uid] = u;
Jin Qian9c542682017-07-28 18:45:59 -0700119 uid_io_stats[u.uid].name = std::to_string(u.uid);
120 uids.push_back(u.uid);
121 uid_names.push_back(&uid_io_stats[u.uid].name);
122 if (last_uid_io_stats.find(u.uid) == last_uid_io_stats.end()) {
123 refresh_uid_names = true;
124 } else {
125 uid_io_stats[u.uid].name = last_uid_io_stats[u.uid].name;
126 }
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800127 }
128
Jin Qian9c542682017-07-28 18:45:59 -0700129 if (!uids.empty() && refresh_uid_names) {
130 get_uid_names(uids, uid_names);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800131 }
132
Jin Qian5b962c62017-01-30 14:48:38 -0800133 return uid_io_stats;
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800134}
135
Jin Qian5b962c62017-01-30 14:48:38 -0800136static const int MAX_UID_RECORDS_SIZE = 1000 * 48; // 1000 uids in 48 hours
Jin Qiana2e5bd12017-01-24 16:23:13 -0800137
Jin Qian5b962c62017-01-30 14:48:38 -0800138static inline int records_size(
Jin Qian81577752017-02-21 12:09:39 -0800139 const std::map<uint64_t, struct uid_records>& curr_records)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800140{
Jin Qian5b962c62017-01-30 14:48:38 -0800141 int count = 0;
Jin Qian81577752017-02-21 12:09:39 -0800142 for (auto const& it : curr_records) {
143 count += it.second.entries.size();
Jin Qian5b962c62017-01-30 14:48:38 -0800144 }
145 return count;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800146}
147
Jin Qian5b962c62017-01-30 14:48:38 -0800148static struct uid_io_usage zero_io_usage;
149
150void uid_monitor::add_records_locked(uint64_t curr_ts)
Jin Qiana2e5bd12017-01-24 16:23:13 -0800151{
Jin Qian5b962c62017-01-30 14:48:38 -0800152 // remove records more than 5 days old
153 if (curr_ts > 5 * DAY_TO_SEC) {
154 auto it = records.lower_bound(curr_ts - 5 * DAY_TO_SEC);
155 records.erase(records.begin(), it);
Jin Qian9cdfdd32017-01-31 17:33:20 -0800156 }
157
Jin Qian81577752017-02-21 12:09:39 -0800158 struct uid_records new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800159 for (const auto& p : curr_io_stats) {
160 struct uid_record record = {};
161 record.name = p.first;
162 record.ios = p.second;
163 if (memcmp(&record.ios, &zero_io_usage, sizeof(struct uid_io_usage))) {
Jin Qian81577752017-02-21 12:09:39 -0800164 new_records.entries.push_back(record);
Jin Qian5b962c62017-01-30 14:48:38 -0800165 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800166 }
Jin Qian9cdfdd32017-01-31 17:33:20 -0800167
Jin Qian5b962c62017-01-30 14:48:38 -0800168 curr_io_stats.clear();
Jin Qian81577752017-02-21 12:09:39 -0800169 new_records.start_ts = start_ts;
170 start_ts = curr_ts;
Jin Qian9cdfdd32017-01-31 17:33:20 -0800171
Jin Qian81577752017-02-21 12:09:39 -0800172 if (new_records.entries.empty())
Jin Qian5b962c62017-01-30 14:48:38 -0800173 return;
174
175 // make some room for new records
176 int overflow = records_size(records) +
Jin Qian81577752017-02-21 12:09:39 -0800177 new_records.entries.size() - MAX_UID_RECORDS_SIZE;
Jin Qian5b962c62017-01-30 14:48:38 -0800178 while (overflow > 0 && records.size() > 0) {
Jin Qian81577752017-02-21 12:09:39 -0800179 auto del_it = records.begin();
180 overflow -= del_it->second.entries.size();
Jin Qian5b962c62017-01-30 14:48:38 -0800181 records.erase(records.begin());
182 }
183
Jin Qian81577752017-02-21 12:09:39 -0800184 records[curr_ts] = new_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800185}
186
Jin Qian81577752017-02-21 12:09:39 -0800187std::map<uint64_t, struct uid_records> uid_monitor::dump(
Jin Qiandd41d6b2017-02-10 17:23:16 -0800188 double hours, uint64_t threshold, bool force_report)
Jin Qian5b962c62017-01-30 14:48:38 -0800189{
Jin Qian1275b1b2017-02-06 14:02:50 -0800190 if (force_report) {
191 report();
192 }
193
Jin Qian5b962c62017-01-30 14:48:38 -0800194 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
195
Jin Qian81577752017-02-21 12:09:39 -0800196 std::map<uint64_t, struct uid_records> dump_records;
Jin Qian5b962c62017-01-30 14:48:38 -0800197 uint64_t first_ts = 0;
198
199 if (hours != 0) {
Jin Qiandd41d6b2017-02-10 17:23:16 -0800200 first_ts = time(NULL) - hours * HOUR_TO_SEC;
Jin Qian5b962c62017-01-30 14:48:38 -0800201 }
202
Jin Qiane5ea17c2017-02-10 10:50:03 -0800203 for (auto it = records.lower_bound(first_ts); it != records.end(); ++it) {
Jin Qian81577752017-02-21 12:09:39 -0800204 const std::vector<struct uid_record>& recs = it->second.entries;
205 struct uid_records filtered;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800206
207 for (const auto& rec : recs) {
208 if (rec.ios.bytes[READ][FOREGROUND][CHARGER_ON] +
209 rec.ios.bytes[READ][FOREGROUND][CHARGER_OFF] +
210 rec.ios.bytes[READ][BACKGROUND][CHARGER_ON] +
211 rec.ios.bytes[READ][BACKGROUND][CHARGER_OFF] +
212 rec.ios.bytes[WRITE][FOREGROUND][CHARGER_ON] +
213 rec.ios.bytes[WRITE][FOREGROUND][CHARGER_OFF] +
214 rec.ios.bytes[WRITE][BACKGROUND][CHARGER_ON] +
215 rec.ios.bytes[WRITE][BACKGROUND][CHARGER_OFF] > threshold) {
Jin Qian81577752017-02-21 12:09:39 -0800216 filtered.entries.push_back(rec);
Jin Qiane5ea17c2017-02-10 10:50:03 -0800217 }
218 }
Jin Qian81577752017-02-21 12:09:39 -0800219
220 if (filtered.entries.empty())
221 continue;
222
223 filtered.start_ts = it->second.start_ts;
Jin Qiane5ea17c2017-02-10 10:50:03 -0800224 dump_records.insert(
Jin Qian81577752017-02-21 12:09:39 -0800225 std::pair<uint64_t, struct uid_records>(it->first, filtered));
Jin Qiane5ea17c2017-02-10 10:50:03 -0800226 }
Jin Qian5b962c62017-01-30 14:48:38 -0800227
228 return dump_records;
229}
230
231void uid_monitor::update_curr_io_stats_locked()
232{
233 std::unordered_map<uint32_t, struct uid_info> uid_io_stats =
234 get_uid_io_stats_locked();
235 if (uid_io_stats.empty()) {
236 return;
237 }
238
239 for (const auto& it : uid_io_stats) {
240 const struct uid_info& uid = it.second;
241
242 if (curr_io_stats.find(uid.name) == curr_io_stats.end()) {
243 curr_io_stats[uid.name] = {};
244 }
245
246 struct uid_io_usage& usage = curr_io_stats[uid.name];
Jin Qianbaff6402017-02-16 18:34:31 -0800247 int64_t fg_rd_delta = uid.io[FOREGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800248 last_uid_io_stats[uid.uid].io[FOREGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800249 int64_t bg_rd_delta = uid.io[BACKGROUND].read_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800250 last_uid_io_stats[uid.uid].io[BACKGROUND].read_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800251 int64_t fg_wr_delta = uid.io[FOREGROUND].write_bytes -
Jin Qian5b962c62017-01-30 14:48:38 -0800252 last_uid_io_stats[uid.uid].io[FOREGROUND].write_bytes;
Jin Qianbaff6402017-02-16 18:34:31 -0800253 int64_t bg_wr_delta = uid.io[BACKGROUND].write_bytes -
254 last_uid_io_stats[uid.uid].io[BACKGROUND].write_bytes;
255
256 usage.bytes[READ][FOREGROUND][charger_stat] +=
Jin Qianccae2b52017-08-02 17:37:40 -0700257 (fg_rd_delta < 0) ? 0 : fg_rd_delta;
Jin Qianbaff6402017-02-16 18:34:31 -0800258 usage.bytes[READ][BACKGROUND][charger_stat] +=
Jin Qianccae2b52017-08-02 17:37:40 -0700259 (bg_rd_delta < 0) ? 0 : bg_rd_delta;
Jin Qianbaff6402017-02-16 18:34:31 -0800260 usage.bytes[WRITE][FOREGROUND][charger_stat] +=
Jin Qianccae2b52017-08-02 17:37:40 -0700261 (fg_wr_delta < 0) ? 0 : fg_wr_delta;
Jin Qian5b962c62017-01-30 14:48:38 -0800262 usage.bytes[WRITE][BACKGROUND][charger_stat] +=
Jin Qianccae2b52017-08-02 17:37:40 -0700263 (bg_wr_delta < 0) ? 0 : bg_wr_delta;
Jin Qian5b962c62017-01-30 14:48:38 -0800264 }
265
266 last_uid_io_stats = uid_io_stats;
Jin Qiana2e5bd12017-01-24 16:23:13 -0800267}
268
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800269void uid_monitor::report()
270{
Jin Qian5b962c62017-01-30 14:48:38 -0800271 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800272
Jin Qian5b962c62017-01-30 14:48:38 -0800273 update_curr_io_stats_locked();
274 add_records_locked(time(NULL));
275}
276
277void uid_monitor::set_charger_state(charger_stat_t stat)
278{
279 std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
280
281 if (charger_stat == stat) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800282 return;
283 }
284
Jin Qian5b962c62017-01-30 14:48:38 -0800285 update_curr_io_stats_locked();
286 charger_stat = stat;
287}
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800288
Jin Qian5b962c62017-01-30 14:48:38 -0800289void uid_monitor::init(charger_stat_t stat)
290{
291 charger_stat = stat;
Jin Qian81577752017-02-21 12:09:39 -0800292 start_ts = time(NULL);
Jin Qian5b962c62017-01-30 14:48:38 -0800293 last_uid_io_stats = get_uid_io_stats();
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800294}
295
296uid_monitor::uid_monitor()
297{
Jin Qian5b962c62017-01-30 14:48:38 -0800298 sem_init(&um_lock, 0, 1);
Jin Qiana2e5bd12017-01-24 16:23:13 -0800299}
300
301uid_monitor::~uid_monitor()
302{
Jin Qian5b962c62017-01-30 14:48:38 -0800303 sem_destroy(&um_lock);
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800304}