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