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