LoginSignup
2
1

More than 3 years have passed since last update.

[Android] dumpsys storagedの見方

Last updated at Posted at 2019-08-31

dumpsysとは

Androidのsystem serviceの状態を出力するコマンド。
オプション無しだと全サービスの情報を出力してくれる。
dumpsys -lで対応するserviceの一覧を取得し、dumpsys SERVICEで特定のserviceの情報だけ出力することも可能。

dumpsys自体はserviceに対してdump要求を投げるだけで、実際の情報出力はservice側でおこなう。
この作りのおかげで柔軟にdumpsysを拡張できる。
逆に言えばdumpsysに対応するserviceはシステムごとに異なる。

以前"cpuinfo"を取り上げたので、今回はストレージデバイス使用量の情報を取得する"storaged"の中身を見る。

ソースコードおよび動作確認の環境は以下のとおり。
- Android: android-8.1.0_r1.0, Oreo, API 27
- Linux kernel: android-4.4-o-release

dumpsys storaged

dumpsys storagedは、UIDごとのストレージデバイス使用量統計を出力する。
定期的(デフォルト一時間ごと)に/proc/uid_io/statsを収集し、
充電中かどうかに応じて分類したうえで変化量を出力する。

shellからの実行であれば、root権限は不要。
(直接serviceを使う場合は、"android.permission.DUMP"が必要。)

まずは出力例。
起動直後など十分にデータが収集されていない場合は何も出力されないかもしれない。
その場合は、後述の--forceオプションを指定するとよい。

$ adb shell dumpsys storaged
1567214981,1567215005                                 <------- タイムスタンプ(開始,終了)
shared:android.uid.shell 1105920 0 0 0 0 0 0 0        <------- UIDごとのディスク使用量
1047 405504 0 0 0 0 0 0 0
0 98934784 8777728 0 0 0 0 0 0
1041 471040 0 0 0 0 0 0 0
shared:android.uid.phone 1929216 0 0 0 0 0 0 0
1046 118784 0 0 0 0 0 0 0
1013 847872 0 0 0 0 0 0 0
1036 4096 0 0 0 0 0 0 0
1040 1069056 0 0 0 0 0 0 0
shared:android.uid.system 634400768 2273280 0 0 0 0 0 0
,1567215093                                           <------- タイムスタンプ(,終了)
com.google.android.sdksetup 163840 0 0 0 0 0 0 0
shared:android.media 0 0 1449984 10014720 0 0 0 0
0 6856192 12464128 0 0 0 0 0 0
shared:com.google.android.apps.maps 0 0 31870976 323584 0 0 0 0
com.google.android.apps.nexuslauncher 8339456 6082560 3010560 4096 0 0 0 0
com.android.contacts 0 0 2224128 0 0 0 0 0

いつからいつまでの使用量なのかを示すタイムスタンプの後に、
各UIDごとのストレージデバイス使用量が出力される。

タイムスタンプ行

1567214981,1567215005                                 <------- タイムスタンプ(開始,終了)
,1567215093                                           <------- タイムスタンプ(,終了)

終了時刻しか書いていない場合、開始時刻は一つ前の終了時刻となる。

タイムスタンプの内容はUNIXタイム。つまり単位は秒。
dateコマンドを使えば、従来の時間に変更可能。

$ date -d @1567214981       
Sat Aug 31 01:29:41 GMT 2019

ストレージデバイス使用量行

shared:android.uid.shell 1105920 0 0 0 0 0 0 0
1047 405504 0 0 0 0 0 0 0

各項目の意味は以下の通り。

  1. UID or UIDに対応する名前
  2. 非充電 かつ FOREGROUND の読み出し [Byte]
  3. 非充電 かつ FOREGROUND の書き込み [Byte]
  4. 非充電 かつ BACKGROUND の読み出し [Byte]
  5. 非充電 かつ BACKGROUND の書き込み [Byte]
  6. 充電中 かつ FOREGROUND の読み出し [Byte]
  7. 充電中 かつ FOREGROUND の書き込み [Byte]
  8. 充電中 かつ BACKGROUND の読み出し [Byte]
  9. 充電中 かつ BACKGROUND の書き込み [Byte]

オプション

  • --hours <HOURS>
    • HOURSはdouble型
    • 直近のHOURS時間以降の統計情報のみ出力する。
  • --time_window <TIME_WINDOW>
    • TIME_WINDOWはint型
    • /proc/uid_io/statsを収集する時間間隔を設定する(単位は秒)
    • ただし、DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)以上でなければならない。
    • 初期値は、ro.storaged.uid_io.interval
    • ro.storaged.uid_io.intervalが設定されていない場合はDEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )。つまり1時間。
  • --threshold <THRESHOLD>
    • THRESHOLDはuint型
    • IOの総量がTHRESHOLD byte以上のUIDのみ出力するようにする。
  • --force
    • 強制的に現時点までのストレージデバイス使用量を出力する。

ドキュメントもヘルプも見つからなかった。。。

実装

storaged自体がストレージデバイス使用量を収集するためのサービスということもあり、
実装はだいぶシンプルで読みやすい。
system/core/storaged/storaged_service.cppのStoraged::dump()dumpsys storagedに対応する。
前述のオプションなども、ここを見ればわかる。

system/core/storaged/storaged_service.cpp
status_t Storaged::dump(int fd, const Vector<String16>& args) {

...

    const std::map<uint64_t, struct uid_records>& records =
                storaged->get_uid_records(hours, threshold, force_report);
    for (const auto& it : records) {
        if (last_ts != it.second.start_ts) {
            dprintf(fd, "%llu", (unsigned long long)it.second.start_ts);
        }
        dprintf(fd, ",%llu\n", (unsigned long long)it.first);
        last_ts = it.first;

        for (const auto& record : it.second.entries) {
            dprintf(fd, "%s %ju %ju %ju %ju %ju %ju %ju %ju\n",
                record.name.c_str(),
                record.ios.bytes[READ][FOREGROUND][CHARGER_OFF],
                record.ios.bytes[WRITE][FOREGROUND][CHARGER_OFF],
                record.ios.bytes[READ][BACKGROUND][CHARGER_OFF],
                record.ios.bytes[WRITE][BACKGROUND][CHARGER_OFF],
                record.ios.bytes[READ][FOREGROUND][CHARGER_ON],
                record.ios.bytes[WRITE][FOREGROUND][CHARGER_ON],
                record.ios.bytes[READ][BACKGROUND][CHARGER_ON],
                record.ios.bytes[WRITE][BACKGROUND][CHARGER_ON]);
        }
    }

...

    return NO_ERROR;
}

/proc/uid_io/stats

dumpsys storagedの基となるprocfs
Androidで独自に追加されている。
出力はぱっと見dumpsys storagedと似ているが、中身は全然違うので要注意。
さらに、公式ページの説明も間違っている(2019/8/31時点)ので注意。
参照にはroot権限が必要。

$ cat /proc/uid_io/stats                                                                                                                                                                         
0 69488496 57508693 176613888 71938048 0 0 0 0 37 0
10074 0 0 0 0 478411 2454202 8970240 3514368 0 259
1021 523337 3579 2101248 0 0 0 0 0 0 0
10019 13994 828 163840 0 10502 1521 0 0 0 0
...
  1. UID
  2. FOREGROUND かつ read system call [Byte]
  3. FOREGROUND かつ write system call [Byte]
  4. FOREGROUND かつ storage deviceからの読み出し [Byte]
  5. FOREGROUND かつ storage deviceへの書き込み [Byte]
  6. BACKGROUND かつ read system call [Byte]
  7. BACKGROUND かつ write system call [Byte]
  8. BACKGROUND かつ storage deviceからの読み出し [Byte]
  9. BACKGROUND かつ storage deviceへの書き込み [Byte]
  10. FOREGROUND かつ fsync system call [回数]
  11. BACKGROUND かつ fsync system call [回数]

実装は以下。

drivers/misc/uid_sys_stats.c
static int uid_io_show(struct seq_file *m, void *v)
{
        struct uid_entry *uid_entry;
        unsigned long bkt;

        rt_mutex_lock(&uid_lock);

        update_io_stats_all_locked();

        hash_for_each(hash_table, bkt, uid_entry, hash) {
                seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
                                uid_entry->uid,
                                uid_entry->io[UID_STATE_FOREGROUND].rchar,
                                uid_entry->io[UID_STATE_FOREGROUND].wchar,
                                uid_entry->io[UID_STATE_FOREGROUND].read_bytes,
                                uid_entry->io[UID_STATE_FOREGROUND].write_bytes,
                                uid_entry->io[UID_STATE_BACKGROUND].rchar,
                                uid_entry->io[UID_STATE_BACKGROUND].wchar,
                                uid_entry->io[UID_STATE_BACKGROUND].read_bytes,
                                uid_entry->io[UID_STATE_BACKGROUND].write_bytes,
                                uid_entry->io[UID_STATE_FOREGROUND].fsync,
                                uid_entry->io[UID_STATE_BACKGROUND].fsync);

                show_io_uid_tasks(m, uid_entry);
        }

        rt_mutex_unlock(&uid_lock);
        return 0;
}

おまけ:UIDごとの累積使用量が知りたいときはstoraged -u

/pro/uid_io/statsだとUIDで出力されるので、わかりづらい。
dumpsys storagedはUIDがpackage名なのでわかりやすいが、累積使用量を知るためには処理が必要。

という場合はstoraged -uを使えばいい。
デーモンプロセスを実行するのは抵抗があるかも知れないが、
UIDをpackage名に変換して、/proc/uid_io/stats相当の情報を出力してくれる。
ヘッダをつけてくれるのも地味にありがたい。

# storaged -u
name/uid fg_rchar fg_wchar fg_rbytes fg_wbytes bg_rchar bg_wchar bg_rbytes bg_wbytes fg_fsync bg_fsync
shared:com.google.uid.shared 333142 4077 159744 16384 119379524 25551230 139603968 67715072 0 2766
com.google.android.googlequicksearchbox 1552289 1046016 1654784 237568 2588581 6417348 65368064 6144000 3 223
shared:com.google.android.apps.maps 0 0 0 0 917109 59377 62382080 90112 0 15
com.android.chrome 1944 213 0 0 1645705 1542720 38596608 18350080 0 61
com.google.android.inputmethod.latin 1944 213 0 0 1740052 1965819 43499520 524288 0 12
com.google.android.dialer 1944 203 0 0 17437687 30775961 13991936 25989120 0 47
com.google.android.apps.photos 0 0 0 0 2109896 849853 31760384 880640 0 4

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1