1bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian/*
2bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * Copyright (C) 2016 The Android Open Source Project
3bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian *
4bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * Licensed under the Apache License, Version 2.0 (the "License");
5bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * you may not use this file except in compliance with the License.
6bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * You may obtain a copy of the License at
7bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian *
8bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian *      http://www.apache.org/licenses/LICENSE-2.0
9bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian *
10bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * Unless required by applicable law or agreed to in writing, software
11bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * distributed under the License is distributed on an "AS IS" BASIS,
12bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * See the License for the specific language governing permissions and
14bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian * limitations under the License.
15bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian */
16bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
17bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#ifndef _STORAGED_UID_MONITOR_H_
18bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#define _STORAGED_UID_MONITOR_H_
19bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
20bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#include <stdint.h>
21bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
22bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#include <string>
23bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#include <unordered_map>
24a2e5bd1347fe2e70d6eb0b54b5b077cdf14cabcfJin Qian#include <vector>
25bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
265b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qianenum uid_stat_t {
275b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    FOREGROUND = 0,
285b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    BACKGROUND = 1,
295b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    UID_STATS = 2
305b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian};
315b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian
325b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qianenum charger_stat_t {
335b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    CHARGER_OFF = 0,
345b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    CHARGER_ON = 1,
355b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    CHARGER_STATS = 2
365b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian};
375b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian
385b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qianenum io_type_t {
395b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    READ = 0,
405b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    WRITE = 1,
415b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    IO_TYPES = 2
42bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian};
43bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
44bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qianstruct uid_io_stats {
45bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uint64_t rchar;                 // characters read
46bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uint64_t wchar;                 // characters written
47bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uint64_t read_bytes;            // bytes read (from storage layer)
48bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uint64_t write_bytes;           // bytes written (to storage layer)
49e83a6107c7b5c4e5bc4cca56012025de301212e7Jin Qian    uint64_t fsync;                 // number of fsync syscalls
50bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian};
51bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
52bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qianstruct uid_info {
53bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uint32_t uid;                   // user id
54bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    std::string name;               // package name
555b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    struct uid_io_stats io[UID_STATS];    // [0]:foreground [1]:background
56a2e5bd1347fe2e70d6eb0b54b5b077cdf14cabcfJin Qian};
57bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
585b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qianstruct uid_io_usage {
595b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    uint64_t bytes[IO_TYPES][UID_STATS][CHARGER_STATS];
605b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian};
615b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian
625b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qianstruct uid_record {
63a2e5bd1347fe2e70d6eb0b54b5b077cdf14cabcfJin Qian    std::string name;
645b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    struct uid_io_usage ios;
65bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian};
66bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
678157775d791c124fcd84cdbeb7a751226bcb285bJin Qianstruct uid_records {
688157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    uint64_t start_ts;
698157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    std::vector<struct uid_record> entries;
708157775d791c124fcd84cdbeb7a751226bcb285bJin Qian};
718157775d791c124fcd84cdbeb7a751226bcb285bJin Qian
72bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qianclass uid_monitor {
73bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qianprivate:
745b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // last dump from /proc/uid_io/stats, uid -> uid_info
755b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    std::unordered_map<uint32_t, struct uid_info> last_uid_io_stats;
765b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // current io usage for next report, app name -> uid_io_usage
775b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    std::unordered_map<std::string, struct uid_io_usage> curr_io_stats;
788157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    // io usage records, end timestamp -> {start timestamp, vector of records}
798157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    std::map<uint64_t, struct uid_records> records;
805b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // charger ON/OFF
815b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    charger_stat_t charger_stat;
825b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // protects curr_io_stats, last_uid_io_stats, records and charger_stat
835b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    sem_t um_lock;
848157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    // start time for IO records
858157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    uint64_t start_ts;
865b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian
875b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // reads from /proc/uid_io/stats
885b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats_locked();
895b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // flushes curr_io_stats to records
905b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    void add_records_locked(uint64_t curr_ts);
915b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // updates curr_io_stats and set last_uid_io_stats
925b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    void update_curr_io_stats_locked();
935b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian
94bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qianpublic:
95bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    uid_monitor();
96a2e5bd1347fe2e70d6eb0b54b5b077cdf14cabcfJin Qian    ~uid_monitor();
975b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // called by storaged main thread
985b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    void init(charger_stat_t stat);
995b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // called by storaged -u
1005b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats();
1015b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // called by dumpsys
1028157775d791c124fcd84cdbeb7a751226bcb285bJin Qian    std::map<uint64_t, struct uid_records> dump(
103dd41d6b17115f5592f184b17351383c1b06d6336Jin Qian        double hours, uint64_t threshold, bool force_report);
1045b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    // called by battery properties listener
1055b962c6dbd305946ece05ffbd81d29c2ea211673Jin Qian    void set_charger_state(charger_stat_t stat);
1061275b1b6aaf417243ff3be17a400a21e26c42f39Jin Qian    // called by storaged periodic_chore or dump with force_report
107bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian    void report();
108bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian};
109bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian
110bcd6e3b9d92b2eea3b054372c9adf00a1e6235bcJin Qian#endif /* _STORAGED_UID_MONITOR_H_ */
111