WindowManagerService类的成员函数performEnableScreen的实现如下所示:
-
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) {
-
-
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 {
-
-
-
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);
-
} else {
-
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实现,敬请关注。