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 #ifndef _STORAGED_UID_MONITOR_H_
18 #define _STORAGED_UID_MONITOR_H_
19 
20 #include <stdint.h>
21 
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include <cutils/multiuser.h>
27 #include <utils/Mutex.h>
28 
29 #include "storaged.pb.h"
30 #include "uid_info.h"
31 
32 #define FRIEND_TEST(test_case_name, test_name) \
33 friend class test_case_name##_##test_name##_Test
34 
35 using namespace std;
36 using namespace storaged_proto;
37 using namespace android;
38 using namespace android::os::storaged;
39 
40 class uid_info : public UidInfo {
41 public:
42     bool parse_uid_io_stats(string&& s);
43 };
44 
45 class io_usage {
46 public:
io_usage()47     io_usage() : bytes{{{0}}} {};
48     uint64_t bytes[IO_TYPES][UID_STATS][CHARGER_STATS];
49     bool is_zero() const;
50     io_usage& operator+= (const io_usage& stats) {
51         for (int i = 0; i < IO_TYPES; i++) {
52             for (int j = 0; j < UID_STATS; j++) {
53                 for (int k = 0; k < CHARGER_STATS; k++) {
54                     bytes[i][j][k] += stats.bytes[i][j][k];
55                 }
56             }
57         }
58         return *this;
59     }
60 };
61 
62 struct uid_io_usage {
63     userid_t user_id;
64     io_usage uid_ios;
65     // mapped from task comm to task io usage
66     map<string, io_usage> task_ios;
67 };
68 
69 struct uid_record {
70     string name;
71     uid_io_usage ios;
72 };
73 
74 struct uid_records {
75     uint64_t start_ts;
76     vector<uid_record> entries;
77 };
78 
79 class uid_monitor {
80 private:
81     FRIEND_TEST(storaged_test, uid_monitor);
82     FRIEND_TEST(storaged_test, load_uid_io_proto);
83 
84     // last dump from /proc/uid_io/stats, uid -> uid_info
85     unordered_map<uint32_t, uid_info> last_uid_io_stats_;
86     // current io usage for next report, app name -> uid_io_usage
87     unordered_map<string, uid_io_usage> curr_io_stats_;
88     // io usage records, end timestamp -> {start timestamp, vector of records}
89     map<uint64_t, uid_records> io_history_;
90     // charger ON/OFF
91     charger_stat_t charger_stat_;
92     // protects curr_io_stats, last_uid_io_stats, records and charger_stat
93     Mutex uidm_mutex_;
94     // start time for IO records
95     uint64_t start_ts_;
96     // true if UID_IO_STATS_PATH is accessible
97     const bool enabled_;
98 
99     // reads from /proc/uid_io/stats
100     unordered_map<uint32_t, uid_info> get_uid_io_stats_locked();
101     // flushes curr_io_stats to records
102     void add_records_locked(uint64_t curr_ts);
103     // updates curr_io_stats and set last_uid_io_stats
104     void update_curr_io_stats_locked();
105     // writes io_history to protobuf
106     void update_uid_io_proto(unordered_map<int, StoragedProto>* protos);
107 
108     // Ensure that io_history_ can append |n| items without exceeding
109     // MAX_UID_RECORDS_SIZE in size.
110     void maybe_shrink_history_for_items(size_t nitems);
111 
112 public:
113     uid_monitor();
114     // called by storaged main thread
115     void init(charger_stat_t stat);
116     // called by storaged -u
117     unordered_map<uint32_t, uid_info> get_uid_io_stats();
118     // called by dumpsys
119     map<uint64_t, uid_records> dump(
120         double hours, uint64_t threshold, bool force_report);
121     // called by battery properties listener
122     void set_charger_state(charger_stat_t stat);
123     // called by storaged periodic_chore or dump with force_report
enabled()124     bool enabled() { return enabled_; };
125     void report(unordered_map<int, StoragedProto>* protos);
126     // restores io_history from protobuf
127     void load_uid_io_proto(userid_t user_id, const UidIOUsage& proto);
128     void clear_user_history(userid_t user_id);
129 
io_history()130     map<uint64_t, uid_records>& io_history() { return io_history_; }
131 
132     static constexpr int MAX_UID_RECORDS_SIZE = 1000 * 48; // 1000 uids in 48 hours
133 };
134 
135 #endif /* _STORAGED_UID_MONITOR_H_ */
136