WindowManagerService類的成員函數performEnableScreen的實作如下所示:
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
......
public void performEnableScreen() {
synchronized(mWindowMap) {
if (mDisplayEnabled) {
return;
}
if (!mSystemBooted) {
......
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是否已經初始化過系統的螢幕了,隻有當它的值等于false,并且系統已經完成啟動,即WindowManagerService類的成員變量mSystemBooted等于true的情況下,WindowManagerService類的成員函數performEnableScreen才通知SurfaceFlinger服務停止顯示開機動畫。
注意,WindowManagerService類的成員函數performEnableScreen是通過一個類型為IBinder.FIRST_CALL_TRANSACTION的程序間通信請求來通知SurfaceFlinger服務停止顯示開機動畫的。
在SurfaceFlinger服務,類型為IBinder.FIRST_CALL_TRANSACTION的程序間通信請求被定義為停止顯示開機動畫的請求,如下所示:
class BnSurfaceComposer : public BnInterface<ISurfaceComposer>
{
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中,它是SurfaceFlinger服務所要繼承的Binder本地對象類,其中。當SurfaceFlinger服務接收到類型為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'\n", msg);
}
從前面的調用過程可以知道,參數msg和arg的值分别等于"stop"和“bootanim”,這表示要停止執行名稱為“bootanim”的服務,這是通過調用函數msg_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);
ERROR("no such service '%s'\n", name);
這個函數首先調用函數service_find_by_name來找到名稱等于name,即“bootanim”的服務,然後再調用函數service_stop來停止這個服務。
前面提到,名稱為“bootanim”的服務對應的應用程式即為/system/bin/bootanimation。是以,停止名稱為“bootanim”的服務即為停止執行應用程式/system/bin/bootanimation,而當應用程式/system/bin/bootanimation停止執行的時候,開機動畫就會停止顯示了。
至此,Android系統的三個開機畫面的顯示過程就分析完成了。通過這個三個開機畫面的顯示過程分析,我們學習到:
1. 在核心層,系統螢幕是使用一個稱為幀緩沖區的硬體裝置來描述的,而使用者空間的應用程式可以通過裝置檔案/dev/fb0或者/dev/graphics/fb0來操作這個硬體裝置。實際上,幀緩沖區本身并不是一個真正的硬體,它隻不過是對顯示卡的一個抽象表示,不過,我們通過訪幀緩沖區就可以間接地操作顯示卡記憶體以及顯示卡中的其它寄存器。
2. OpenGL是通過EGL接口來渲染螢幕,而EGL接口是通過ANativeWindow類來間接地渲染螢幕的。我們可以将ANativeWindow類了解成一個Android系統的本地視窗類,即相當于是Windows系統中的視窗句柄概念,它最終是通過檔案/dev/fb0或者/dev/graphics/fb0來渲染螢幕的。
3. init程序在啟動的過程中,會将另外一個ueventd程序也啟動起來。ueventd程序對應的可執行檔案與init程序對應的可執行檔案均為/init,不過ueventd程序主要負責處理核心發出的uevent事件,即負責管理系統中的裝置檔案。
4. 每當我們設定一個系統屬性的時候,init程序都會接收到一個系統屬性變化事件。當發生變化的系統屬性的名稱等于“ctl.start”或者“ctl.stop”,那麼實際上是向init程序發出一個啟動或者停止服務的指令。
前面第1點和第2點的知識是與Android系統的UI實作相關的,而後面第3點和第4點是兩個額外獲得的知識點。
本文的目的并不是單純為了介紹Android系統的開機畫面,而是希望能夠以Android系統的開機畫面來作為切入點來分析Android系統的UI實作。在後面的文章中,我們就會根據本文所涉及到的知識點,來展開分析Android系統的UI實作,敬請關注。
本文轉自 Luoshengyang 51CTO部落格,原文連結:http://blog.51cto.com/shyluo/967049,如需轉載請自行聯系原作者