Androidシステムの起動画面表示過程分析(13)
25110 ワード
WindowManagerServiceクラスのメンバー関数performEnableScreenの実装は、次のようになります.
WindowManagerServiceクラスの別のメンバー変数mDisplayEnabledは、WindowManagerServiceクラスのメンバー変数mSystemBootedがtrueに等しい場合にのみ、WindowManagerServiceクラスがシステムの画面を初期化したかどうかを記述するために使用されます.WindowManagerServiceクラスのメンバー関数performEnableScreenは、SurfaceFlingerサービスに電源オンアニメーションの表示を停止するよう通知します.
WindowManagerServiceクラスのメンバー関数performEnableScreenは、IBinderというタイプのFIRST_CALL_TRANSACTIONのプロセス間通信要求は、SurfaceFlingerサービスに起動アニメーションの表示を停止することを通知する.
Surface FlingerサービスではIBinder.FIRST_CALL_TRANSACTIONのプロセス間通信要求は、以下に示すように、起動アニメーションの表示を停止する要求として定義される.
class BnSurfaceComposer : public BnInterface
{
public:
enum {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
......
};
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
BnSurfaceComposerクラスは、ファイルframeworks/base/include/surfaceflinger/ISurfaceComposerに定義する.hでは、Surface Flingerサービスが継承するBinderローカルオブジェクトクラスである.Surface Flingerサービス受信タイプがIBinder::FIRST_CALL_TRANSACTION、すなわちタイプBOOT_FINISHEDのプロセス間通信要求は、その要求をメンバー関数bootFinishedに渡して処理します.
SurfaceFlingerサービスのメンバー関数bootFinishedはファイルframeworks/base/services/surfaceflinger/surfaceFlinger.cppでは、以下のようになります.
void SurfaceFlinger::bootFinished()
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mBootFinished = true;
property_set("ctl.stop", "bootanim");
}
この関数は主にシステム属性「ctl.stop」の値を「bootanim」に設定します.前述したように、initプロセスは、システム属性が変化するたびに起動され、その中で実行される関数handle_を呼び出す.property_set_fdは、このシステム属性変化イベントを処理する.このシーンでは、変更されたシステム属性の名前が「ctl.」であるため、最初の、すなわち変更されたシステム属性は制御タイプの属性であるため、次の関数handle_property_set_fdはまた別の関数handleを呼び出します.control_Messageは、システム属性変化イベントを処理します.
関数handle_control_Messageはファイルsystem/core/init/initで実現する.cでは、以下に示す.
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,"start")) {
msg_start(arg);
} else if (!strcmp(msg,"stop")) {
msg_stop(arg);
} else {
ERROR("unknown control msg '%s'", msg);
}
}
前の呼び出しプロセスから分かるように、パラメータmsgとargの値はそれぞれ「stop」と「bootanim」に等しく、これは関数msg_を呼び出すことによって「bootanim」という名前のサービスを停止することを意味する.stopで実現しました.
関数msg_stopもファイルsystem/core/init/initで実現する.cでは、以下に示す.
static void msg_stop(const char *name)
{
struct service *svc = service_find_by_name(name);
if (svc) {
service_stop(svc);
} else {
ERROR("no such service '%s'", name);
}
}
この関数はまず関数サービスを呼び出します.find_by_nameは、name、すなわちbootanimに等しい名前のサービスを見つけ、関数service_を呼び出します.stopはこのサービスを停止します.
前述したように、「bootanim」という名前のサービスに対応するアプリケーションは、/system/bin/bootanimationです.したがって、「bootanim」という名前のサービスを停止することは、アプリケーション/system/bin/bootanimationの実行を停止することであり、アプリケーション/system/bin/bootanimationが実行を停止すると、起動アニメーションの表示が停止します.
これでAndroidシステムの3つの起動画面の表示過程の分析が完了した.この3つの起動画面の表示過程の分析を通じて、私たちは以下のことを学びました.
1. カーネル層では、システム画面はフレームバッファと呼ばれるハードウェアデバイスを用いて記述され、ユーザ空間のアプリケーションは、デバイスファイル/dev/fb 0または/dev/graphics/fb 0を介してこのハードウェアデバイスを動作させることができる.実際には、フレームバッファ自体は本物のハードウェアではなく、グラフィックスカードの抽象的な表現にすぎませんが、フレームバッファにアクセスすることで、グラフィックスカードのメモリやグラフィックスカードの他のレジスタを間接的に操作することができます.
2. OpenGLはEGLインタフェースによってスクリーンをレンダリングし、EGLインタフェースはANativeWindowクラスによってスクリーンを間接的にレンダリングします.ANativeWindowクラスは、最終的にはファイル/dev/fb 0または/dev/graphics/fb 0によってスクリーンをレンダリングするWindowsシステムのウィンドウハンドル概念に相当するAndroidシステムのローカルウィンドウクラスと理解できます.
3. Initプロセスは、起動中に別のueventdプロセスも起動します.ueventdプロセスに対応する実行可能ファイルとinitプロセスに対応する実行可能ファイルはいずれも/initであるが、ueventdプロセスは主にカーネルから発行されたueventイベント、すなわちシステム内のデバイスファイルの管理を担当する.
4. システム属性を設定するたびに、initプロセスはシステム属性変化イベントを受信します.変更されたシステム属性の名前が「ctl.start」または「ctl.stop」に等しい場合、実際にはinitプロセスにサービスを開始または停止するコマンドが発行されます.
前の1点目と2点目の知識はAndroidシステムのUI実装に関連しており、後の3点目と4点目は2つの追加の知識点である.
本稿の目的は,単にAndroidシステムの起動画面を紹介することではなく,Androidシステムの起動画面を切り口としてAndroidシステムのUI実現を分析することである.後述する記事では、本明細書に関連する知識点に基づいて、Androidシステムを分析するUI実装を展開しますので、ご注目ください.
-
public class WindowManagerService extends IWindowManager.Stub
-
implements Watchdog.Monitor {
-
......
-
-
public void performEnableScreen() {
-
synchronized(mWindowMap) {
-
if (mDisplayEnabled) {
-
return;
-
}
-
if (!mSystemBooted) {
-
return;
-
}
-
-
......
-
-
mDisplayEnabled = true;
-
......
-
-
try {
-
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
-
if (surfaceFlinger != null) {
-
//Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
-
Parcel data = Parcel.obtain();
-
data.writeInterfaceToken("android.ui.ISurfaceComposer");
-
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
-
data, null, 0);
-
data.recycle();
-
}
-
} catch (RemoteException ex) {
-
Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
-
}
-
}
-
-
......
-
}
-
-
......
-
}
WindowManagerServiceクラスの別のメンバー変数mDisplayEnabledは、WindowManagerServiceクラスのメンバー変数mSystemBootedがtrueに等しい場合にのみ、WindowManagerServiceクラスがシステムの画面を初期化したかどうかを記述するために使用されます.WindowManagerServiceクラスのメンバー関数performEnableScreenは、SurfaceFlingerサービスに電源オンアニメーションの表示を停止するよう通知します.
WindowManagerServiceクラスのメンバー関数performEnableScreenは、IBinderというタイプのFIRST_CALL_TRANSACTIONのプロセス間通信要求は、SurfaceFlingerサービスに起動アニメーションの表示を停止することを通知する.
Surface FlingerサービスではIBinder.FIRST_CALL_TRANSACTIONのプロセス間通信要求は、以下に示すように、起動アニメーションの表示を停止する要求として定義される.
class BnSurfaceComposer : public BnInterface
{
public:
enum {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
......
};
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
BnSurfaceComposerクラスは、ファイルframeworks/base/include/surfaceflinger/ISurfaceComposerに定義する.hでは、Surface Flingerサービスが継承するBinderローカルオブジェクトクラスである.Surface Flingerサービス受信タイプがIBinder::FIRST_CALL_TRANSACTION、すなわちタイプBOOT_FINISHEDのプロセス間通信要求は、その要求をメンバー関数bootFinishedに渡して処理します.
SurfaceFlingerサービスのメンバー関数bootFinishedはファイルframeworks/base/services/surfaceflinger/surfaceFlinger.cppでは、以下のようになります.
void SurfaceFlinger::bootFinished()
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mBootFinished = true;
property_set("ctl.stop", "bootanim");
}
この関数は主にシステム属性「ctl.stop」の値を「bootanim」に設定します.前述したように、initプロセスは、システム属性が変化するたびに起動され、その中で実行される関数handle_を呼び出す.property_set_fdは、このシステム属性変化イベントを処理する.このシーンでは、変更されたシステム属性の名前が「ctl.」であるため、最初の、すなわち変更されたシステム属性は制御タイプの属性であるため、次の関数handle_property_set_fdはまた別の関数handleを呼び出します.control_Messageは、システム属性変化イベントを処理します.
関数handle_control_Messageはファイルsystem/core/init/initで実現する.cでは、以下に示す.
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,"start")) {
msg_start(arg);
} else if (!strcmp(msg,"stop")) {
msg_stop(arg);
} else {
ERROR("unknown control msg '%s'", msg);
}
}
前の呼び出しプロセスから分かるように、パラメータmsgとargの値はそれぞれ「stop」と「bootanim」に等しく、これは関数msg_を呼び出すことによって「bootanim」という名前のサービスを停止することを意味する.stopで実現しました.
関数msg_stopもファイルsystem/core/init/initで実現する.cでは、以下に示す.
static void msg_stop(const char *name)
{
struct service *svc = service_find_by_name(name);
if (svc) {
service_stop(svc);
} else {
ERROR("no such service '%s'", name);
}
}
この関数はまず関数サービスを呼び出します.find_by_nameは、name、すなわちbootanimに等しい名前のサービスを見つけ、関数service_を呼び出します.stopはこのサービスを停止します.
前述したように、「bootanim」という名前のサービスに対応するアプリケーションは、/system/bin/bootanimationです.したがって、「bootanim」という名前のサービスを停止することは、アプリケーション/system/bin/bootanimationの実行を停止することであり、アプリケーション/system/bin/bootanimationが実行を停止すると、起動アニメーションの表示が停止します.
これでAndroidシステムの3つの起動画面の表示過程の分析が完了した.この3つの起動画面の表示過程の分析を通じて、私たちは以下のことを学びました.
1. カーネル層では、システム画面はフレームバッファと呼ばれるハードウェアデバイスを用いて記述され、ユーザ空間のアプリケーションは、デバイスファイル/dev/fb 0または/dev/graphics/fb 0を介してこのハードウェアデバイスを動作させることができる.実際には、フレームバッファ自体は本物のハードウェアではなく、グラフィックスカードの抽象的な表現にすぎませんが、フレームバッファにアクセスすることで、グラフィックスカードのメモリやグラフィックスカードの他のレジスタを間接的に操作することができます.
2. OpenGLはEGLインタフェースによってスクリーンをレンダリングし、EGLインタフェースはANativeWindowクラスによってスクリーンを間接的にレンダリングします.ANativeWindowクラスは、最終的にはファイル/dev/fb 0または/dev/graphics/fb 0によってスクリーンをレンダリングするWindowsシステムのウィンドウハンドル概念に相当するAndroidシステムのローカルウィンドウクラスと理解できます.
3. Initプロセスは、起動中に別のueventdプロセスも起動します.ueventdプロセスに対応する実行可能ファイルとinitプロセスに対応する実行可能ファイルはいずれも/initであるが、ueventdプロセスは主にカーネルから発行されたueventイベント、すなわちシステム内のデバイスファイルの管理を担当する.
4. システム属性を設定するたびに、initプロセスはシステム属性変化イベントを受信します.変更されたシステム属性の名前が「ctl.start」または「ctl.stop」に等しい場合、実際にはinitプロセスにサービスを開始または停止するコマンドが発行されます.
前の1点目と2点目の知識はAndroidシステムのUI実装に関連しており、後の3点目と4点目は2つの追加の知識点である.
本稿の目的は,単にAndroidシステムの起動画面を紹介することではなく,Androidシステムの起動画面を切り口としてAndroidシステムのUI実現を分析することである.後述する記事では、本明細書に関連する知識点に基づいて、Androidシステムを分析するUI実装を展開しますので、ご注目ください.