设计网站官网国外,seo快速排名案例,佛山网站设计哪家便宜,wordpress仿58同城3. 第三个开机画面的显示过程第三个开机画面是由应用程序bootanimation来负责显示的。应用程序bootanimation在启动脚本init.rc中被配置成了一个服务#xff0c;如下所示#xff1a;service bootanim /system/bin/bootanimation user graphics group graphics disabled o… 3. 第三个开机画面的显示过程 第三个开机画面是由应用程序bootanimation来负责显示的。应用程序bootanimation在启动脚本init.rc中被配置成了一个服务如下所示 service bootanim /system/bin/bootanimation user graphics group graphics disabled oneshot 应用程序bootanimation的用户和用户组名称分别被设置为graphics。注意 用来启动应用程序bootanimation的服务是disable的即init进程在启动的时候不会主动将应用程序bootanimation启动起来。当SurfaceFlinger服务启动的时候它会通过修改系统属性ctl.start的值来通知init进程启动应用程序bootanimation以便可以显示第三个开机画面而当System进程将系统中的关键服务都启动起来之后ActivityManagerService服务就会通知SurfaceFlinger服务来修改系统属性ctl.stop的值以便可以通知init进程停止执行应用程序bootanimation即停止显示第三个开机画面。接下来我们就分别分析第三个开机画面的显示过程和停止过程。 从前面Android系统进程Zygote启动过程的源代码分析一文可以知道Zygote进程在启动的过程中会将System进程启动起来而从前面Android应用程序安装过程源代码分析一文又可以知道System进程在启动的过程Step 3中会调用SurfaceFlinger类的静态成员函数instantiate来启动SurfaceFlinger服务。Sytem进程在启动SurfaceFlinger服务的过程中首先会创建一个SurfaceFlinger实例然后再将这个实例注册到Service Manager中去。在注册的过程前面创建的SurfaceFlinger实例会被一个sp指针引用。从前面Android系统的智能指针轻量级指针、强指针和弱指针的实现原理分析一文可以知道当一个对象第一次被智能指针引用的时候这个对象的成员函数onFirstRef就会被调用。由于SurfaceFlinger重写了父类RefBase的成员函数onFirstRef因此在注册SurfaceFlinger服务的过程中将会调用SurfaceFlinger类的成员函数onFirstRef。在调用的过程就会创建一个线程来启动第三个开机画面。 SurfaceFlinger类实现在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp 中它的成员函数onFirstRef的实现如下所示 void SurfaceFlinger::onFirstRef() { run(SurfaceFlinger, PRIORITY_URGENT_DISPLAY); // Wait for the main thread to be done with its initialization mReadyToRunBarrier.wait(); } SurfaceFlinger类继承了Thread类当它的成员函数run被调用的时候系统就会创建一个新的线程。这个线程在第一次运行之前会调用SurfaceFlinger类的成员函数readyToRun来通知SurfaceFlinger它准备就绪了。当这个线程准备就绪之后它就会循环执行SurfaceFlinger类的成员函数threadLoop直到这个成员函数的返回值等于false为止。 注意SurfaceFlinger类的成员函数onFirstRef是在System进程的主线程中调用的它需要等待前面创建的线程准备就绪之后再继续往前执行这个通过调用SurfaceFlinger类的成员变量mReadytoRunBarrier所描述的一个Barrier对象的成员函数wait来实现的。每一个Barrier对象内问都封装了一个条件变量Condition Variable而条件变量是用来同步线程的。 接下来我们继续分析SurfaceFlinger类的成员函数readyToRun的实现如下所示 status_t SurfaceFlinger::readyToRun() { LOGI( SurfaceFlingers main thread ready to run. Initializing graphics H/W...); ...... mReadyToRunBarrier.open(); /* * Were now ready to accept clients... */ // start boot animation property_set(ctl.start, bootanim); return NO_ERROR; } 前面创建的线程用作SurfaceFlinger的主线程。这个线程在启动的时候会对设备主屏幕以及OpenGL库进行初始化。初始化完成之后接着就会调用SurfaceFlinger类的成员变量mReadyToRunBarrier所描述的一个Barrier对象的成员函数open来唤醒System进程的主线程以便它可以继续往前执行。最后SurfaceFlinger类的成员函数readyToRun的成员函数会调用函数property_set来将系统属性“ctl.start”的值设置为“bootanim”表示要将应用程序bootanimation启动起来以便可以显示第三个开机画面。 前面在介绍第二个开机画面的时候提到当系统属性发生改变时init进程就会接收到一个系统属性变化通知这个通知最终是由在init进程中的函数handle_property_set_fd来处理的。 函数handle_property_set_fd实现在文件system/core/init/property_service.c中如下所示 void handle_property_set_fd() { prop_msg msg; int s; int r; int res; struct ucred cr; struct sockaddr_un addr; socklen_t addr_size sizeof(addr); socklen_t cr_size sizeof(cr); if ((s accept(property_set_fd, (struct sockaddr *) addr, addr_size)) 0) { return; } /* Check socket options here */ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, cr, cr_size) 0) { close(s); ERROR(Unable to recieve socket options\n); return; } r recv(s, msg, sizeof(msg), 0); close(s); if(r ! sizeof(prop_msg)) { ERROR(sys_prop: mis-match msg size recieved: %d expected: %d\n, r, sizeof(prop_msg)); return; } switch(msg.cmd) { case PROP_MSG_SETPROP: msg.name[PROP_NAME_MAX-1] 0; msg.value[PROP_VALUE_MAX-1] 0; if(memcmp(msg.name,ctl.,4) 0) { if (check_control_perms(msg.value, cr.uid, cr.gid)) { handle_control_message((char*) msg.name 4, (char*) msg.value); } else { ERROR(sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n, msg.name 4, msg.value, cr.uid, cr.pid); } } else { if (check_perms(msg.name, cr.uid, cr.gid)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR(sys_prop: permission denied uid:%d name:%s\n, cr.uid, msg.name); } } break; default: break; } } init进程是通过一个socket来接收系统属性变化事件的。每一个系统属性变化事件的内容都是通过一个prop_msg对象来描述的。在prop_msg对象对成员变量name用来描述发生变化的系统属性的名称而成员变量value用来描述发生变化的系统属性的值。系统属性分为两种类型一种是普通类型的系统属性另一种是控制类型的系统属性属性名称以“ctl.”开头。控制类型的系统属性在发生变化时会触发init进程执行一个命令而普通类型的系统属性就不具有这个特性。注意改变系统属性是需要权限因此函数handle_property_set_fd在处理一个系统属性变化事件之前首先会检查修改系统属性的进程是否具有相应的权限这是通过调用函数check_control_perms或者check_perms来实现的。 从前面的调用过程可以知道当前发生变化的系统属性的名称为“ctl.start”它的值被设置为“bootanim”。由于这是一个控制类型的系统属性因此在通过了权限检查之后另外一个函数handle_control_message就会被调用以便可以执行一个名称为“bootanim”的命令。 本文转自 Luoshengyang 51CTO博客原文链接http://blog.51cto.com/shyluo/967040如需转载请自行联系原作者