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