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

Commit 6df3bc63 authored by Jin Qian's avatar Jin Qian
Browse files

storaged: split proto file into multiple CE areas

Use user_id (from app uid) to determine file location.
/data/misc_ce/<user_id>/storaged/storaged.proto

Vold notifies storaged when a user's CE area becomes available.
Then storaged restores data from the proto in that area and
combines them into IO history.

Vold also notifies storaged when the CE area is being deleted.
Storaged clears internal history about this user and deletes the
proto file.

IO perf is stored in user_0 area since it's not user related.

Test: dumpsys storaged before/after multiple users' unlock
Bug: 63740245
Change-Id: I39f923f6b09e9f2a29e9286ce02b3b3bcbfb9f94
parent 446ab4a3
Loading
Loading
Loading
Loading
+15 −22
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <vector>

#include <batteryservice/IBatteryPropertiesListener.h>
#include <utils/Mutex.h>

#include <android/hardware/health/2.0/IHealth.h>

@@ -83,17 +84,18 @@ class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback,
    sp<android::hardware::health::V2_0::IHealth> health;
    unique_ptr<storage_info_t> storage_info;
    static const uint32_t crc_init;
    static const string proto_file;
    storaged_proto::StoragedProto proto;
    enum stat {
        NOT_AVAILABLE,
        AVAILABLE,
        LOADED,
    };
    stat proto_stat;
    unordered_map<int, storaged_proto::StoragedProto> protos;
    Mutex proto_mutex;
    void load_proto_locked(userid_t user_id);
    void prepare_proto(StoragedProto* proto, userid_t user_id);
    void flush_proto_locked(userid_t user_id);
    void flush_proto_user_system_locked(StoragedProto* proto);
    string proto_path(userid_t user_id) {
        return string("/data/misc_ce/") + to_string(user_id) +
               "/storaged/storaged.proto";
    }
public:
    storaged_t(void);
    ~storaged_t() {}
    void event(void);
    void event_checked(void);
    void pause(void) {
@@ -114,8 +116,7 @@ public:

    map<uint64_t, struct uid_records> get_uid_records(
            double hours, uint64_t threshold, bool force_report) {
        return mUidm.dump(hours, threshold, force_report,
                          proto.mutable_uid_io_usage());
        return mUidm.dump(hours, threshold, force_report, &protos);
    }

    void update_uid_io_interval(int interval) {
@@ -124,15 +125,8 @@ public:
        }
    }

    void set_proto_stat_available(bool available) {
        if (available) {
            if (proto_stat != LOADED) {
                proto_stat = AVAILABLE;
            }
        } else {
            proto_stat = NOT_AVAILABLE;
        }
    };
    void add_user_ce(userid_t user_id);
    void remove_user_ce(userid_t user_id);

    void init_health_service();
    virtual ::android::hardware::Return<void> healthInfoChanged(
@@ -141,8 +135,7 @@ public:

    void report_storage_info();

    void load_proto();
    void flush_proto();
    void flush_protos();
};

// Eventlog tag
+5 −3
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@

#include <chrono>

#include <utils/Mutex.h>

#include "storaged.h"
#include "storaged.pb.h"

@@ -28,6 +30,7 @@
friend class test_case_name##_##test_name##_Test

using namespace std;
using namespace android;
using namespace chrono;
using namespace storaged_proto;

@@ -51,13 +54,12 @@ protected:
    uint32_t nr_days;
    vector<uint32_t> weekly_perf;
    uint32_t nr_weeks;
    sem_t si_lock;
    Mutex si_mutex;

    storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0),
        userdata_total_kb(0), userdata_free_kb(0), nr_samples(0),
        daily_perf(WEEK_TO_DAYS, 0), nr_days(0),
        weekly_perf(YEAR_TO_WEEKS, 0), nr_weeks(0) {
            sem_init(&si_lock, 0, 1);
            day_start_tp = system_clock::now();
            day_start_tp -= chrono::seconds(duration_cast<chrono::seconds>(
                day_start_tp.time_since_epoch()).count() % DAY_TO_SEC);
@@ -66,7 +68,7 @@ protected:
    storage_info_t* s_info;
public:
    static storage_info_t* get_storage_info();
    virtual ~storage_info_t() { sem_destroy(&si_lock); }
    virtual ~storage_info_t() {};
    virtual void report() {};
    void load_perf_history_proto(const IOPerfHistory& perf_history);
    void refresh(IOPerfHistory* perf_history);
+3 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ using namespace android::os;
using namespace android::os::storaged;

class StoragedService : public BinderService<StoragedService>, public BnStoraged {
private:
    void dumpUidRecordsDebug(int fd, const vector<struct uid_record>& entries);
    void dumpUidRecords(int fd, const vector<struct uid_record>& entries);
public:
    static status_t start();
    static char const* getServiceName() { return "storaged"; }
+38 −29
Original line number Diff line number Diff line
@@ -23,92 +23,101 @@
#include <unordered_map>
#include <vector>

#include <cutils/multiuser.h>
#include <utils/Mutex.h>

#include "storaged.pb.h"
#include "uid_info.h"

#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test

using namespace std;
using namespace storaged_proto;
using namespace android;
using namespace android::os::storaged;

class uid_info : public UidInfo {
public:
    bool parse_uid_io_stats(std::string&& s);
    bool parse_uid_io_stats(string&& s);
};

struct io_usage {
class io_usage {
public:
    io_usage() : bytes{{{0}}} {};
    uint64_t bytes[IO_TYPES][UID_STATS][CHARGER_STATS];
    bool is_zero() const;
    io_usage& operator+= (const io_usage& stats) {
        for (int i = 0; i < IO_TYPES; i++) {
            for (int j = 0; j < UID_STATS; j++) {
                for (int k = 0; k < CHARGER_STATS; k++) {
                    bytes[i][j][k] += stats.bytes[i][j][k];
                }
            }
        }
        return *this;
    }
};

struct uid_io_usage {
    struct io_usage uid_ios;
    userid_t user_id;
    io_usage uid_ios;
    // mapped from task comm to task io usage
    std::map<std::string, struct io_usage> task_ios;
    map<string, io_usage> task_ios;
};

struct uid_record {
    std::string name;
    string name;
    struct uid_io_usage ios;
};

struct uid_records {
    uint64_t start_ts;
    std::vector<struct uid_record> entries;
};

class lock_t {
    sem_t* mSem;
public:
    lock_t(sem_t* sem) {
        mSem = sem;
        sem_wait(mSem);
    }
    ~lock_t() {
        sem_post(mSem);
    }
    vector<struct uid_record> entries;
};

class uid_monitor {
private:
    FRIEND_TEST(storaged_test, uid_monitor);
    // last dump from /proc/uid_io/stats, uid -> uid_info
    std::unordered_map<uint32_t, uid_info> last_uid_io_stats;
    unordered_map<uint32_t, uid_info> last_uid_io_stats;
    // current io usage for next report, app name -> uid_io_usage
    std::unordered_map<std::string, struct uid_io_usage> curr_io_stats;
    unordered_map<string, struct uid_io_usage> curr_io_stats;
    // io usage records, end timestamp -> {start timestamp, vector of records}
    std::map<uint64_t, struct uid_records> io_history;
    map<uint64_t, struct uid_records> io_history;
    // charger ON/OFF
    charger_stat_t charger_stat;
    // protects curr_io_stats, last_uid_io_stats, records and charger_stat
    sem_t um_lock;
    Mutex uidm_mutex;
    // start time for IO records
    uint64_t start_ts;
    // true if UID_IO_STATS_PATH is accessible
    const bool enable;

    // reads from /proc/uid_io/stats
    std::unordered_map<uint32_t, uid_info> get_uid_io_stats_locked();
    unordered_map<uint32_t, uid_info> get_uid_io_stats_locked();
    // flushes curr_io_stats to records
    void add_records_locked(uint64_t curr_ts);
    // updates curr_io_stats and set last_uid_io_stats
    void update_curr_io_stats_locked();
    // writes io_history to protobuf
    void update_uid_io_proto(UidIOUsage* proto);
    void update_uid_io_proto(unordered_map<int, StoragedProto>* protos);

public:
    uid_monitor();
    ~uid_monitor();
    // called by storaged main thread
    void init(charger_stat_t stat);
    // called by storaged -u
    std::unordered_map<uint32_t, uid_info> get_uid_io_stats();
    unordered_map<uint32_t, uid_info> get_uid_io_stats();
    // called by dumpsys
    std::map<uint64_t, struct uid_records> dump(
    map<uint64_t, struct uid_records> dump(
        double hours, uint64_t threshold, bool force_report,
        UidIOUsage* uid_io_proto);
        unordered_map<int, StoragedProto>* protos);
    // called by battery properties listener
    void set_charger_state(charger_stat_t stat);
    // called by storaged periodic_chore or dump with force_report
    bool enabled() { return enable; };
    void report(UidIOUsage* proto);
    void report(unordered_map<int, StoragedProto>* protos);
    // restores io_history from protobuf
    void load_uid_io_proto(const UidIOUsage& proto);
};
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ void get_inc_disk_stats(const struct disk_stats* prev, const struct disk_stats*
void add_disk_stats(struct disk_stats* src, struct disk_stats* dst);

// UID I/O
map<string, io_usage> merge_io_usage(const vector<uid_record>& entries);
void sort_running_uids_info(std::vector<UidInfo> &uids);

// Logging
Loading