Home | History | Annotate | Download | only in storaged
      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 <stdint.h>
     18 
     19 #include <vector>
     20 
     21 #include <android-base/parseint.h>
     22 #include <android-base/parsedouble.h>
     23 #include <binder/IBinder.h>
     24 #include <binder/IInterface.h>
     25 
     26 #include <binder/IPCThreadState.h>
     27 #include <binder/IServiceManager.h>
     28 #include <binder/PermissionCache.h>
     29 #include <private/android_filesystem_config.h>
     30 
     31 #include <storaged.h>
     32 #include <storaged_service.h>
     33 
     34 using namespace android::base;
     35 
     36 extern sp<storaged_t> storaged;
     37 
     38 std::vector<struct uid_info> BpStoraged::dump_uids(const char* /*option*/) {
     39     Parcel data, reply;
     40     data.writeInterfaceToken(IStoraged::getInterfaceDescriptor());
     41 
     42     remote()->transact(DUMPUIDS, data, &reply);
     43 
     44     uint32_t res_size = reply.readInt32();
     45     std::vector<struct uid_info> res(res_size);
     46     for (auto&& uid : res) {
     47         uid.uid = reply.readInt32();
     48         uid.name = reply.readCString();
     49         reply.read(&uid.io, sizeof(uid.io));
     50     }
     51     return res;
     52 }
     53 IMPLEMENT_META_INTERFACE(Storaged, "Storaged");
     54 
     55 status_t BnStoraged::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     56     switch(code) {
     57         case DUMPUIDS: {
     58                 if (!data.checkInterface(this))
     59                     return BAD_TYPE;
     60                 std::vector<struct uid_info> res = dump_uids(NULL);
     61                 reply->writeInt32(res.size());
     62                 for (auto uid : res) {
     63                     reply->writeInt32(uid.uid);
     64                     reply->writeCString(uid.name.c_str());
     65                     reply->write(&uid.io, sizeof(uid.io));
     66                 }
     67                 return NO_ERROR;
     68             }
     69             break;
     70         default:
     71             return BBinder::onTransact(code, data, reply, flags);
     72     }
     73 }
     74 
     75 std::vector<struct uid_info> Storaged::dump_uids(const char* /* option */) {
     76     std::vector<struct uid_info> uids_v;
     77     std::unordered_map<uint32_t, struct uid_info> uids_m = storaged->get_uids();
     78 
     79     for (const auto& it : uids_m) {
     80         uids_v.push_back(it.second);
     81     }
     82     return uids_v;
     83 }
     84 
     85 status_t Storaged::dump(int fd, const Vector<String16>& args) {
     86     IPCThreadState* self = IPCThreadState::self();
     87     const int pid = self->getCallingPid();
     88     const int uid = self->getCallingUid();
     89     if ((uid != AID_SHELL) &&
     90         !PermissionCache::checkPermission(
     91                 String16("android.permission.DUMP"), pid, uid)) {
     92         return PERMISSION_DENIED;
     93     }
     94 
     95     double hours = 0;
     96     int time_window = 0;
     97     uint64_t threshold = 0;
     98     bool force_report = false;
     99     for (size_t i = 0; i < args.size(); i++) {
    100         const auto& arg = args[i];
    101         if (arg == String16("--hours")) {
    102             if (++i >= args.size())
    103                 break;
    104             if(!ParseDouble(String8(args[i]).c_str(), &hours))
    105                 return BAD_VALUE;
    106             continue;
    107         }
    108         if (arg == String16("--time_window")) {
    109             if (++i >= args.size())
    110                 break;
    111             if(!ParseInt(String8(args[i]).c_str(), &time_window))
    112                 return BAD_VALUE;
    113             continue;
    114         }
    115         if (arg == String16("--threshold")) {
    116             if (++i >= args.size())
    117                 break;
    118             if(!ParseUint(String8(args[i]).c_str(), &threshold))
    119                 return BAD_VALUE;
    120             continue;
    121         }
    122         if (arg == String16("--force")) {
    123             force_report = true;
    124             continue;
    125         }
    126     }
    127 
    128     uint64_t last_ts = 0;
    129     const std::map<uint64_t, struct uid_records>& records =
    130                 storaged->get_uid_records(hours, threshold, force_report);
    131     for (const auto& it : records) {
    132         if (last_ts != it.second.start_ts) {
    133             dprintf(fd, "%llu", (unsigned long long)it.second.start_ts);
    134         }
    135         dprintf(fd, ",%llu\n", (unsigned long long)it.first);
    136         last_ts = it.first;
    137 
    138         for (const auto& record : it.second.entries) {
    139             dprintf(fd, "%s %ju %ju %ju %ju %ju %ju %ju %ju\n",
    140                 record.name.c_str(),
    141                 record.ios.bytes[READ][FOREGROUND][CHARGER_OFF],
    142                 record.ios.bytes[WRITE][FOREGROUND][CHARGER_OFF],
    143                 record.ios.bytes[READ][BACKGROUND][CHARGER_OFF],
    144                 record.ios.bytes[WRITE][BACKGROUND][CHARGER_OFF],
    145                 record.ios.bytes[READ][FOREGROUND][CHARGER_ON],
    146                 record.ios.bytes[WRITE][FOREGROUND][CHARGER_ON],
    147                 record.ios.bytes[READ][BACKGROUND][CHARGER_ON],
    148                 record.ios.bytes[WRITE][BACKGROUND][CHARGER_ON]);
    149         }
    150     }
    151 
    152     if (time_window) {
    153         storaged->update_uid_io_interval(time_window);
    154     }
    155 
    156     return NO_ERROR;
    157 }
    158 
    159 sp<IStoraged> get_storaged_service() {
    160     sp<IServiceManager> sm = defaultServiceManager();
    161     if (sm == NULL) return NULL;
    162 
    163     sp<IBinder> binder = sm->getService(String16("storaged"));
    164     if (binder == NULL) return NULL;
    165 
    166     sp<IStoraged> storaged = interface_cast<IStoraged>(binder);
    167 
    168     return storaged;
    169 }
    170