1 /*
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 #include <inttypes.h>
18 #include <stdint.h>
19
20 #include <vector>
21
22 #include <android-base/parseint.h>
23 #include <android-base/parsedouble.h>
24 #include <binder/IBinder.h>
25 #include <binder/IInterface.h>
26
27 #include <binder/IPCThreadState.h>
28 #include <binder/IServiceManager.h>
29 #include <binder/PermissionCache.h>
30 #include <private/android_filesystem_config.h>
31
32 #include <storaged.h>
33 #include <storaged_utils.h>
34 #include <storaged_service.h>
35
36 using namespace std;
37 using namespace android::base;
38
39 extern sp<storaged_t> storaged_sp;
40
start()41 status_t StoragedService::start() {
42 return BinderService<StoragedService>::publish();
43 }
44
dumpUidRecords(int fd,const vector<uid_record> & entries)45 void StoragedService::dumpUidRecords(int fd, const vector<uid_record>& entries) {
46 map<string, io_usage> merged_entries = merge_io_usage(entries);
47 for (const auto& rec : merged_entries) {
48 dprintf(fd, "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
49 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
50 rec.first.c_str(),
51 rec.second.bytes[READ][FOREGROUND][CHARGER_OFF],
52 rec.second.bytes[WRITE][FOREGROUND][CHARGER_OFF],
53 rec.second.bytes[READ][BACKGROUND][CHARGER_OFF],
54 rec.second.bytes[WRITE][BACKGROUND][CHARGER_OFF],
55 rec.second.bytes[READ][FOREGROUND][CHARGER_ON],
56 rec.second.bytes[WRITE][FOREGROUND][CHARGER_ON],
57 rec.second.bytes[READ][BACKGROUND][CHARGER_ON],
58 rec.second.bytes[WRITE][BACKGROUND][CHARGER_ON]);
59 }
60 }
61
dumpUidRecordsDebug(int fd,const vector<uid_record> & entries)62 void StoragedService::dumpUidRecordsDebug(int fd, const vector<uid_record>& entries) {
63 for (const auto& record : entries) {
64 const io_usage& uid_usage = record.ios.uid_ios;
65 dprintf(fd, "%s_%d %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
66 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
67 record.name.c_str(), record.ios.user_id,
68 uid_usage.bytes[READ][FOREGROUND][CHARGER_OFF],
69 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_OFF],
70 uid_usage.bytes[READ][BACKGROUND][CHARGER_OFF],
71 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_OFF],
72 uid_usage.bytes[READ][FOREGROUND][CHARGER_ON],
73 uid_usage.bytes[WRITE][FOREGROUND][CHARGER_ON],
74 uid_usage.bytes[READ][BACKGROUND][CHARGER_ON],
75 uid_usage.bytes[WRITE][BACKGROUND][CHARGER_ON]);
76
77 for (const auto& task_it : record.ios.task_ios) {
78 const io_usage& task_usage = task_it.second;
79 const string& comm = task_it.first;
80 dprintf(fd, "-> %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
81 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
82 comm.c_str(),
83 task_usage.bytes[READ][FOREGROUND][CHARGER_OFF],
84 task_usage.bytes[WRITE][FOREGROUND][CHARGER_OFF],
85 task_usage.bytes[READ][BACKGROUND][CHARGER_OFF],
86 task_usage.bytes[WRITE][BACKGROUND][CHARGER_OFF],
87 task_usage.bytes[READ][FOREGROUND][CHARGER_ON],
88 task_usage.bytes[WRITE][FOREGROUND][CHARGER_ON],
89 task_usage.bytes[READ][BACKGROUND][CHARGER_ON],
90 task_usage.bytes[WRITE][BACKGROUND][CHARGER_ON]);
91 }
92 }
93 }
94
dump(int fd,const Vector<String16> & args)95 status_t StoragedService::dump(int fd, const Vector<String16>& args) {
96 IPCThreadState* self = IPCThreadState::self();
97 const int pid = self->getCallingPid();
98 const int uid = self->getCallingUid();
99 if ((uid != AID_SHELL) &&
100 !PermissionCache::checkPermission(
101 String16("android.permission.DUMP"), pid, uid)) {
102 return PERMISSION_DENIED;
103 }
104
105 double hours = 0;
106 int time_window = 0;
107 uint64_t threshold = 0;
108 bool force_report = false;
109 bool debug = false;
110 for (size_t i = 0; i < args.size(); i++) {
111 const auto& arg = args[i];
112 if (arg == String16("--hours")) {
113 if (++i >= args.size())
114 break;
115 if(!ParseDouble(String8(args[i]).c_str(), &hours))
116 return BAD_VALUE;
117 continue;
118 }
119 if (arg == String16("--time_window")) {
120 if (++i >= args.size())
121 break;
122 if(!ParseInt(String8(args[i]).c_str(), &time_window))
123 return BAD_VALUE;
124 continue;
125 }
126 if (arg == String16("--threshold")) {
127 if (++i >= args.size())
128 break;
129 if(!ParseUint(String8(args[i]).c_str(), &threshold))
130 return BAD_VALUE;
131 continue;
132 }
133 if (arg == String16("--force")) {
134 force_report = true;
135 continue;
136 }
137 if (arg == String16("--debug")) {
138 debug = true;
139 continue;
140 }
141 }
142
143 uint64_t last_ts = 0;
144 map<uint64_t, struct uid_records> records =
145 storaged_sp->get_uid_records(hours, threshold, force_report);
146 for (const auto& it : records) {
147 if (last_ts != it.second.start_ts) {
148 dprintf(fd, "%" PRIu64, it.second.start_ts);
149 }
150 dprintf(fd, ",%" PRIu64 "\n", it.first);
151 last_ts = it.first;
152
153 if (!debug) {
154 dumpUidRecords(fd, it.second.entries);
155 } else {
156 dumpUidRecordsDebug(fd, it.second.entries);
157 }
158 }
159
160 if (time_window) {
161 storaged_sp->update_uid_io_interval(time_window);
162 }
163
164 return OK;
165 }
166
onUserStarted(int32_t userId)167 binder::Status StoragedService::onUserStarted(int32_t userId) {
168 storaged_sp->add_user_ce(userId);
169 return binder::Status::ok();
170 }
171
onUserStopped(int32_t userId)172 binder::Status StoragedService::onUserStopped(int32_t userId) {
173 storaged_sp->remove_user_ce(userId);
174 return binder::Status::ok();
175 }
176
getRecentPerf(int32_t * _aidl_return)177 binder::Status StoragedService::getRecentPerf(int32_t* _aidl_return) {
178 uint32_t recent_perf = storaged_sp->get_recent_perf();
179 if (recent_perf > INT32_MAX) {
180 *_aidl_return = INT32_MAX;
181 } else {
182 *_aidl_return = static_cast<int32_t>(recent_perf);
183 }
184 return binder::Status::ok();
185 }
186
start()187 status_t StoragedPrivateService::start() {
188 return BinderService<StoragedPrivateService>::publish();
189 }
190
dumpUids(vector<::android::os::storaged::UidInfo> * _aidl_return)191 binder::Status StoragedPrivateService::dumpUids(
192 vector<::android::os::storaged::UidInfo>* _aidl_return) {
193 unordered_map<uint32_t, uid_info> uids_m = storaged_sp->get_uids();
194
195 for (const auto& it : uids_m) {
196 UidInfo uinfo;
197 uinfo.uid = it.second.uid;
198 uinfo.name = it.second.name;
199 uinfo.tasks = it.second.tasks;
200 memcpy(&uinfo.io, &it.second.io, sizeof(uinfo.io));
201 _aidl_return->push_back(uinfo);
202 }
203 return binder::Status::ok();
204 }
205
dumpPerfHistory(vector<int32_t> * _aidl_return)206 binder::Status StoragedPrivateService::dumpPerfHistory(
207 vector<int32_t>* _aidl_return) {
208 *_aidl_return = storaged_sp->get_perf_history();
209 return binder::Status::ok();
210 }
211
get_storaged_pri_service()212 sp<IStoragedPrivate> get_storaged_pri_service() {
213 sp<IServiceManager> sm = defaultServiceManager();
214 if (sm == NULL) return NULL;
215
216 sp<IBinder> binder = sm->getService(String16("storaged_pri"));
217 if (binder == NULL) return NULL;
218
219 return interface_cast<IStoragedPrivate>(binder);
220 }
221