2011年12月21日
Android 4.0でZygoteを起動せずに最小構成で動かす
Androidのinit.rcでは複数のserviceをまとめて扱うclassを定義することができます。この機能は以前からあったのですが、使われていませんでした。
Android 4.0ではinit.rcを少し修正することで、ZygoteなどAndroidのframeworkのserviceが起動する前の、最小限の構成までで止めることができます。
最小構成で動かす
通常状態でのプロセスは以下のものが動いています。
$ ps USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 332 196 ffffffff 00000000 S /init ... (kernel threadは省略) ... root 41 1 328 180 ffffffff 00000000 S /sbin/ueventd system 42 1 832 260 ffffffff 00000000 S /system/bin/servicemanager root 43 1 4020 740 ffffffff 00000000 S /system/bin/vold root 44 1 6312 912 ffffffff 00000000 S /system/bin/netd root 45 1 696 272 ffffffff 00000000 S /system/bin/debuggerd radio 46 1 4472 752 ffffffff 00000000 S /system/bin/rild system 47 1 49244 7984 ffffffff 00000000 S /system/bin/surfaceflinger root 48 1 103276 35308 ffffffff 00000000 S zygote drm 49 1 12232 3812 ffffffff 00000000 S /system/bin/drmserver media 50 1 28096 6416 ffffffff 00000000 S /system/bin/mediaserver bluetooth 51 1 1332 596 ffffffff 00000000 S /system/bin/dbus-daemon root 52 1 844 328 ffffffff 00000000 S /system/bin/installd keystore 53 1 1736 544 ffffffff 00000000 S /system/bin/keystore shell 55 1 760 324 c00597f8 4000d264 S /system/bin/sh root 56 1 3436 172 ffffffff 00000000 S /sbin/adbd system 94 48 184232 45844 ffffffff 00000000 S system_server system 158 48 122116 45440 ffffffff 00000000 S com.android.systemui app_5 173 48 113080 31436 ffffffff 00000000 S com.android.inputmethod.latin radio 197 48 127064 36036 ffffffff 00000000 S com.android.phone app_16 209 48 136500 54892 ffffffff 00000000 S com.android.launcher app_2 244 48 139312 51560 ffffffff 00000000 S android.process.acore app_29 262 48 111744 27172 ffffffff 00000000 S com.android.smspush app_2 303 48 119600 32820 ffffffff 00000000 S com.android.contacts app_0 338 48 113256 29828 ffffffff 00000000 S com.android.providers.calendar app_1 353 48 117804 28816 ffffffff 00000000 S com.android.exchange app_3 367 48 122856 33936 ffffffff 00000000 S com.android.email app_7 380 48 115424 30420 ffffffff 00000000 S android.process.media app_4 403 48 115096 30972 ffffffff 00000000 S com.android.mms app_20 444 48 111804 27272 ffffffff 00000000 S com.android.voicedialer app_33 457 48 114552 29304 ffffffff 00000000 S com.android.deskclock system 473 48 123924 39356 ffffffff 00000000 S com.android.settings app_26 486 48 116264 29592 ffffffff 00000000 S com.android.calendar shell 505 55 960 340 00000000 40010438 R ps $
init.rcを一行コメントアウトし、core classのserviceだけ動かしてmain classのものを動かさないことにします。
--- init.rc 2011-12-15 20:42:46.000000000 +0900 +++ init.rc.min 2011-12-15 20:42:39.000000000 +0900 @@ -264,7 +264,7 @@ setprop system_init.startsurfaceflinger 0 class_start core - class_start main +# class_start main on nonencrypted class_start late_start
これで再起動すると以下のようになります。
$ ps USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 332 196 c00d1884 000086e8 S /init ... (kernel threadは省略) ... root 41 1 328 180 c00d1884 000086e8 S /sbin/ueventd system 42 1 832 260 c02431bc 40010670 S /system/bin/servicemanager root 43 1 4020 728 ffffffff 40015c74 S /system/bin/vold root 45 1 760 324 c00597f8 4000d264 S /system/bin/sh root 46 1 3432 164 ffffffff 0000825c S /sbin/adbd root 60 45 960 340 00000000 40010438 R ps $
シリアルコンソールでshellが使えるほか、adbdが起動しているのでadb経由で通信できます。
host$ adb logcat ...
もうひとつ別のターミナルから
host$ adb shell #
この状態で有線LANは使用可能なので、サーバー的に使用するならばこれでも十分です。
例えば、rubyをインストールして簡単にHTTPサーバを動かすことができます。
ここからZygoteを起動する
以下のコマンドでmainクラスのサービスを起動することができます。
# setprop vold.decrypt trigger_restart_framework
または、デバッグや動作の理解のために以下のようにひとつづつserviceを手動で起動していくこともできます。
# start netd # start debuggerd # start ril-deamon # start surfaceflinger # start zygote # start drm # start media # start dbus # start installd
surfaceflingerをstartさせたときにブートアニメーションが起動されます。
(参考:Androidのブートアニメーション)
Android4.0でなぜcoreとmainのクラスに分かれたのか
Android2.3まではclassの定義はされていなかったので全てのserviceはdefaultクラスに属していました。
core classにvold(Volume Daemon)が含まれていることと、その後にmain classをstartさせるproperty名がvold.decryptであることから、このクラス分けはストレージの暗号化が関係しているようです。おそらく製品では、core classを起動した後に、ストレージの暗号化を行うならばそのためのセットアップを行い、その後にmain classのserviceを起動させるようにしているのではないでしょうか。
Android2.3で同様のことをするには
複数のserviceをまとめて扱うclassを定義することはAndroid2.3でも可能です。そのため、Android4.0のinit.rcと見比べて、同様の変更をすればよいと思います。
関連するページ
Androidでinitの代わりに/system/bin/shを動かしてみた
AndroidのNDKツールを使ってrubyをビルドして動かす