summaryrefslogtreecommitdiff
path: root/storaged/include/storaged.h
blob: 79b5d41ac4248587311332021da1a44529eb6ffb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _STORAGED_H_
#define _STORAGED_H_

#include <semaphore.h>
#include <stdint.h>
#include <time.h>

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

#include <utils/Mutex.h>

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

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

#define ARRAY_SIZE(x)   (sizeof(x) / sizeof((x)[0]))

#define IS_ALIGNED(x, align)   (!((x) & ((align) - 1)))
#define ROUND_UP(x, align)     (((x) + ((align) - 1)) & ~((align) - 1))

#define SECTOR_SIZE ( 512 )
#define SEC_TO_MSEC ( 1000 )
#define MSEC_TO_USEC ( 1000 )
#define USEC_TO_NSEC ( 1000 )
#define SEC_TO_USEC ( 1000000 )
#define HOUR_TO_SEC ( 3600 )
#define DAY_TO_SEC ( 3600 * 24 )
#define WEEK_TO_DAYS ( 7 )
#define YEAR_TO_WEEKS ( 52 )

#include "storaged_diskstats.h"
#include "storaged_info.h"
#include "storaged_uid_monitor.h"
#include "storaged.pb.h"
#include "uid_info.h"

using namespace std;
using namespace android;

// Periodic chores intervals in seconds
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT ( 300 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO ( 3600 )

// UID IO threshold in bytes
#define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL )

struct storaged_config {
    int periodic_chores_interval_unit;
    int periodic_chores_interval_disk_stats_publish;
    int periodic_chores_interval_uid_io;
    int periodic_chores_interval_flush_proto;
    int event_time_check_usec;  // check how much cputime spent in event loop
};

class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback,
                   public android::hardware::hidl_death_recipient {
  private:
    time_t mTimer;
    storaged_config mConfig;
    unique_ptr<disk_stats_monitor> mDsm;
    uid_monitor mUidm;
    time_t mStarttime;
    sp<android::hardware::health::V2_0::IHealth> health;
    unique_ptr<storage_info_t> storage_info;
    static const uint32_t current_version;
    Mutex proto_lock;
    unordered_map<userid_t, bool> proto_loaded;
    void load_proto(userid_t user_id);
    char* prepare_proto(userid_t user_id, StoragedProto* proto);
    void flush_proto(userid_t user_id, StoragedProto* proto);
    void flush_proto_data(userid_t user_id, const char* data, ssize_t size);
    string proto_path(userid_t user_id) {
        return string("/data/misc_ce/") + to_string(user_id) +
               "/storaged/storaged.proto";
    }
    void init_health_service();

  public:
    storaged_t(void);
    void init(void);
    void event(void);
    void event_checked(void);
    void pause(void) {
        sleep(mConfig.periodic_chores_interval_unit);
    }

    time_t get_starttime(void) {
        return mStarttime;
    }

    unordered_map<uint32_t, uid_info> get_uids(void) {
        return mUidm.get_uid_io_stats();
    }

    vector<int> get_perf_history(void) {
        return storage_info->get_perf_history();
    }

    uint32_t get_recent_perf(void) { return storage_info->get_recent_perf(); }

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

    void update_uid_io_interval(int interval) {
        if (interval >= DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT) {
            mConfig.periodic_chores_interval_uid_io = interval;
        }
    }

    void add_user_ce(userid_t user_id);
    void remove_user_ce(userid_t user_id);

    virtual ::android::hardware::Return<void> healthInfoChanged(
        const ::android::hardware::health::V2_0::HealthInfo& info);
    void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who);

    void report_storage_info();

    void flush_protos(unordered_map<int, StoragedProto>* protos);
};

// Eventlog tag
// The content must match the definition in EventLogTags.logtags
#define EVENTLOGTAG_DISKSTATS ( 2732 )
#define EVENTLOGTAG_EMMCINFO ( 2733 )
#define EVENTLOGTAG_UID_IO_ALERT ( 2734 )

#endif /* _STORAGED_H_ */