2011年12月12日
Android2.3でSurfaceflingerを独立したプロセスで動かす
Android2.3まではSurfaceflingerはSystemServerの中のスレッドとして動作していましたが、Android4.0では独立したプロセスになっていました。
システムの各種の資源を節約するには、SystemServerの中で動かす方がよいと思いますが、Surfaceflingerにデバッガをあてて調べるには独立したプロセスになっているほうが好都合です。
init.rcの変更
実は以前からSurfaceflingerは独立したプロセスで動かすことが可能になっていました。Android 2.3でも/system/bin/surfaceflinger という実行コマンドはビルドされてインストールされています。
そのため、以下のようにinit.rcを変更するだけで、Surfaceflingerを独立したプロセスで動かすことができました。
$ diff -u init.rc.org init.rc
--- init.rc.org 2011-12-12 09:55:31.000000000 +0900
+++ init.rc 2011-12-12 10:02:00.000000000 +0900
@@ -273,6 +273,9 @@
setprop net.tcp.buffersize.edge 4093,26280,35040,4096,16384,35040
setprop net.tcp.buffersize.gprs 4092,8760,11680,4096,8760,11680
+# Set this property so surfaceflinger is not started by system_init
+ setprop system_init.startsurfaceflinger 0
+
class_start default
## Daemon processes to be run by init.
@@ -324,6 +327,11 @@
user root
group radio cache inet misc audio sdcard_rw
+service surfaceflinger /system/bin/surfaceflinger
+ user system
+ group graphics
+ onrestart restart zygote
+
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
ただし、これだけだとタイミングによってはデバイスファイルのopenに失敗して一度Surfaceflingerは終了し、その後initによって再起動されることがあるようです。(GPU用のカーネルモジュールをロードして、そのデバイスファイルが準備できる前に、Surfaceflingerがそれをopenしようとしてしまう時があるらしい。)
参考:SystemServerでsurfaceflingerを起動するところ
SystemServerでsurfaceflingerを起動するときにsystem_init.startsurfaceflingerのプロパティを見ています。
frameworks/base/cmds/system_server/library/system_init.cpp
extern "C" status_t system_init()
{
LOGI("Entered system_init()");
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
LOGI("ServiceManager: %p\n", sm.get());
sp grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
// Start the sensor service
SensorService::instantiate();
...
以前書いたAndroidのSystemServerの起動シーケンス(メモ)も参照してください。
おまけ: surfaceflingerでのシステムコール呼び出しをstraceで調べる
#service surfaceflinger /system/bin/surfaceflinger
service surfaceflinger /system/xbin/strace -ff -o /data/local/tmp/strace.log /system/bin/surfaceflinger
user system
group graphics
onrestart restart zygote
あらかじめ /data/local/tmp のディレクトリを作って書き込み可能にしておきます。
おまけ2:Android4.0でSurfaceflingerをSystemServerの中のスレッドとして動かす
逆に以下のようにinit.rcをコメントアウトすれば、Android4.0でSurfaceflingerをSystemServerの中のスレッドとして動かすことができます。
$ sudo diff -u init.rc.org init.rc
--- init.rc.org 2011-12-12 10:16:40.000000000 +0900
+++ init.rc 2011-12-12 10:16:59.000000000 +0900
@@ -261,7 +261,7 @@
setprop net.tcp.buffersize.gprs 4092,8760,11680,4096,8760,11680
# Set this property so surfaceflinger is not started by system_init
- setprop system_init.startsurfaceflinger 0
+# setprop system_init.startsurfaceflinger 0
class_start core
class_start main
@@ -400,11 +400,11 @@
user root
group radio cache inet misc audio sdcard_rw log
-service surfaceflinger /system/bin/surfaceflinger
- class main
- user system
- group graphics
- onrestart restart zygote
+#service surfaceflinger /system/bin/surfaceflinger
+# class main
+# user system
+# group graphics
+# onrestart restart zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main