inotify で Android 上のファイル I/O を監視する
Android の Linux カーネルには inotify が含まれており、Android SDK には inotify を利用した FileObserver クラスが用意されています。
Android では一般のアプリケーションプロセスからアクセスできるファイル・ディレクトリが制限されるため、FileObserver を使い Android アプリの形でツールを用意しても今回の目的にはあまり役に立たないでしょう。こういう時には CUI のコマンドラインツールの方が何かと融通がききます。Android エミュレータ環境への adb shell 接続で得られる root 権限のコンソール上でツールを動かすことにしました。
Android の notify コマンドを使う
Android には inotify API を使ってファイル I/O をモニタするコマンドラインツール「notify」が含まれています。 [platform/system/core/toolbox/notify.c]
# notify Usage: notify [-m eventmask] [-c count] [-p] [-v verbosity] path [path ...]この notify コマンドを使って "/data/local/tmp" ディレクトリを監視しつつ別プロセスから以下のコマンドを実行した時の出力例を示します。
# pwd /data/local/tmp # echo aaa > test.txt # mv test.txt aaa.txt
# notify -c 10 /data/local/tmp /data/local/tmp: 00000100 00000000 "test.txt" ; 0x00000100:IN_CREATE /data/local/tmp: 00000020 00000000 "test.txt" ; 0x00000020:IN_OPEN /data/local/tmp: 00000002 00000000 "test.txt" ; 0x00000002:IN_MODIFY /data/local/tmp: 00000008 00000000 "test.txt" ; 0x00000008:IN_CLOSE_WRITE /data/local/tmp: 00000040 00000033 "test.txt" ; 0x00000040:IN_MOVED_FROM /data/local/tmp: 00000080 00000033 "aaa.txt" ; 0x00000080:IN_MOVED_TO※ I/O イベントの定義は [platform/bionic/libc/kernel/common/linux/inotify.h]
inotifywait コマンドを使う
Android の notify コマンドはコンパクトで手軽なツールですが、出力の読みにくさに加え、ディレクトリ配下を再帰的に監視できない点が不便です。改造したりツールを自作するのも面白そうではありますが、Linux 界隈には inotify-tools というパッケージがあることを知り、そこに含まれる inotifywait コマンドを利用することにしました。
すでに誰かが Android 上で動作する inotifywait をビルドし配布しているのではないかとネット上を探したところ見当たらなかったため手元でビルドを行いました。inotifywait 本体と NDK でのビルド用に手を加えたプロジェクト一式を以下に公開します。
md5sum [55BF0FD8365A4139D679CE0D6A3A07B3]
プロジェクト一式(※) - github
(※) 以下の著作物が含まれます。利用に際しては各ソフトウェアのライセンス規約を遵守して下さい。・ inotify-tools
著作権者:Rohan McGovern, Radu Voicilas
ライセンス:GPL version 2
サイト:https://github.com/rvoicilas/inotify-tools/wiki/
・ GNU glibc POSIX 正規表現関数群 (glibc-2.11.3 より)
著作権者:Free Software Foundation, Inc.
ライセンス:LGPL version 2.1 or later
サイト:http://www.gnu.org/software/libc/
inotifywait に /data /cache /system の各ディレクトリを再帰的に監視させた状態で、自作のアプリ「HelloApp」を起動した際の出力例を以下に示します。
# ./inotifywait -r -m /data /cache /system Setting up watches. Beware: since -r was given, this may take a while! Watches established. /system/framework/ ACCESS framework-res.apk /system/framework/ ACCESS framework-res.apk /data/app/ OPEN com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ OPEN com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/dalvik-cache/ OPEN data@app@com.example.helloapp-1.apk@classes.dex /data/dalvik-cache/ ACCESS data@app@com.example.helloapp-1.apk@classes.dex /data/dalvik-cache/ ACCESS data@app@com.example.helloapp-1.apk@classes.dex /data/app/ OPEN com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /data/app/ ACCESS com.example.helloapp-1.apk /system/framework/ ACCESS framework-res.apk /data/app/ ACCESS com.example.helloapp-1.apk /system/fonts/ OPEN DroidSans-Bold.ttf /system/lib/hw/ OPEN gralloc.default.so /system/lib/hw/ ACCESS gralloc.default.so /system/lib/hw/ ACCESS gralloc.default.so /system/framework/ ACCESS framework-res.apk /system/framework/ ACCESS framework-res.apk /data/app/ CLOSE_NOWRITE,CLOSE com.example.helloapp-1.apk :
(tanabe)