Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2e5bd13 authored by Jin Qian's avatar Jin Qian
Browse files

storaged: add dumpsys interface

Write alerts to an internal buffer and flush to dumpsys
when dump is called.

Test: adb shell dumpsys storaged
Bug: 33086174
Bug: 34198239
Change-Id: I39e5dfd9c4e9a5f3ec3d74356b28e9ddf77f6624
parent a867efae
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -283,7 +283,6 @@ public:
    void pause(void) {
        sleep(mConfig.periodic_chores_interval_unit);
    }

    void set_privileged_fds(int fd_emmc) {
        mEmmcInfo.set_emmc_fd(fd_emmc);
    }
@@ -295,6 +294,9 @@ public:
    std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
        return mUidm.get_uids();
    }
    std::vector<struct uid_event> get_uid_events(void) {
        return mUidm.dump_events();
    }
};

// Eventlog tag
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ class BnStoraged : public BnInterface<IStoraged> {

class Storaged : public BnStoraged {
    virtual std::vector<struct uid_info> dump_uids(const char* option);
    virtual status_t dump(int fd, const Vector<String16>& args);
};

sp<IStoraged> get_storaged_service();
+12 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <string>
#include <unordered_map>
#include <vector>

enum {
    UID_FOREGROUND = 0,
@@ -39,22 +40,33 @@ struct uid_info {
    uint32_t uid;                   // user id
    std::string name;               // package name
    struct uid_io_stats io[UID_STATS_SIZE];      // [0]:foreground [1]:background
};

struct uid_event {
    std::string name;
    uint64_t read_bytes;
    uint64_t write_bytes;
    uint64_t interval;
};

class uid_monitor {
private:
    std::unordered_map<uint32_t, struct uid_info> last_uids;
    std::vector<struct uid_event> events;
    sem_t events_lock;
    void set_last_uids(std::unordered_map<uint32_t, struct uid_info>&& uids, uint64_t ts);
    int interval;  // monitor interval in seconds
    int threshold; // monitor threshold in bytes
    uint64_t last_report_ts; // timestamp of last report in nsec
public:
    uid_monitor();
    ~uid_monitor();
    void set_periodic_chores_params(int intvl, int thold) { interval = intvl; threshold = thold; }
    int get_periodic_chores_interval() { return interval; }
    std::unordered_map<uint32_t, struct uid_info> get_uids();
    void report();
    void add_event(const struct uid_event& event);
    std::vector<struct uid_event> dump_events();
};

#endif /* _STORAGED_UID_MONITOR_H_ */
+25 −3
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include <private/android_filesystem_config.h>

#include <storaged.h>
#include <storaged_service.h>
@@ -44,14 +46,13 @@ std::vector<struct uid_info> BpStoraged::dump_uids(const char* /*option*/) {
    }
    return res;
}

IMPLEMENT_META_INTERFACE(Storaged, "Storaged");

status_t BnStoraged::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    data.checkInterface(this);

    switch(code) {
        case DUMPUIDS: {
                if (!data.checkInterface(this))
                    return BAD_TYPE;
                std::vector<struct uid_info> res = dump_uids(NULL);
                reply->writeInt32(res.size());
                for (auto uid : res) {
@@ -77,6 +78,27 @@ std::vector<struct uid_info> Storaged::dump_uids(const char* /* option */) {
    return uids_v;
}

status_t Storaged::dump(int fd, const Vector<String16>& /* args */) {
    IPCThreadState* self = IPCThreadState::self();
    const int pid = self->getCallingPid();
    const int uid = self->getCallingUid();
    if ((uid != AID_SHELL) &&
        !PermissionCache::checkPermission(
                String16("android.permission.DUMP"), pid, uid)) {
        return PERMISSION_DENIED;
    }

    const std::vector<struct uid_event>& events = storaged.get_uid_events();
    for (const auto& event : events) {
        dprintf(fd, "%s %llu %llu %llu\n", event.name.c_str(),
            (unsigned long long)event.read_bytes,
            (unsigned long long)event.write_bytes,
            (unsigned long long)event.interval);
    }
    return NO_ERROR;
}


sp<IStoraged> get_storaged_service() {
    sp<IServiceManager> sm = defaultServiceManager();
    if (sm == NULL) return NULL;
+36 −0
Original line number Diff line number Diff line
@@ -101,6 +101,28 @@ std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uids()
    return uids;
}

static const int MAX_UID_EVENTS = 1000;

void uid_monitor::add_event(const struct uid_event& event)
{
    std::unique_ptr<lock_t> lock(new lock_t(&events_lock));

    if (events.size() > MAX_UID_EVENTS) {
        LOG_TO(SYSTEM, ERROR) << "event buffer full";
        return;
    }
    events.push_back(event);
}

std::vector<struct uid_event> uid_monitor::dump_events()
{
    std::unique_ptr<lock_t> lock(new lock_t(&events_lock));
    std::vector<struct uid_event> dump_events = events;

    events.clear();
    return dump_events;
}

void uid_monitor::report()
{
    struct timespec ts;
@@ -129,6 +151,13 @@ void uid_monitor::report()
            last_uids[uid.uid].io[UID_BACKGROUND].write_bytes;

        if (bg_read_delta + bg_write_delta >= adjusted_threshold) {
            struct uid_event event;
            event.name = uid.name;
            event.read_bytes = bg_read_delta;
            event.write_bytes = bg_write_delta;
            event.interval = uint64_t(ts_delta / NS_PER_SEC);
            add_event(event);

            android_log_event_list(EVENTLOGTAG_UID_IO_ALERT)
                << uid.name << bg_read_delta << bg_write_delta
                << uint64_t(ts_delta / NS_PER_SEC) << LOG_ID_EVENTS;
@@ -147,4 +176,11 @@ uid_monitor::uid_monitor()
        return;
    }
    last_report_ts = ts.tv_sec * NS_PER_SEC + ts.tv_nsec;

    sem_init(&events_lock, 0, 1);
}

uid_monitor::~uid_monitor()
{
    sem_destroy(&events_lock);
}