打印
[资料分享]

安卓底层开发学习经验第十九期

[复制链接]
991|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
这一期我们来学习Android bootanim的一个启动过程
首先我们来看一下Android bootanim的一个启动过程:首先我们会在init.rc中定义一个bootanim的服务,这个服务在最开始是被disable掉的,是因为我们Android的显示需要依赖于Android系统的surface管理服务,所以我们必须等待整个显示的硬件初始化完成,软件初始化完成,然后才能真正的试用Android的显示机制去做显示,而这个机制就是依赖于我们surface的服务。当显示这个服务初始化完成之后,第一件事就是调用start命令,将bootanim这个服务启动,然后bootanim得到我们的surfaceflinge服务,然后去刷开机界面,这是就能看到屏幕上有显示,这个现实并不是zygote启动主lunch的一个显示,这个显示是使用OpenGLES这种操作实现的。首先他会得到surfaceflinge中的一层,然后调用OpenGL显示的操作,去把他相应的一些图片刷出来,这个就是bootanim的一个显示过程。
那么当我们打开一个Android设备,手机或者电视,在打开之后会有第一幅图片,这个图片都是我们在uboot或者内核中来显示的第一幅图,给人的第一印象就是启动很快,因为UI很快刷出来,也就是那个闪烁一次的Android图片,这个界面就是bootanim来操作的,他调用的是OpenGLES的一些操作来显示的,在显示过程中我们会发现,当我们的祝home界面启动之后,我们这些刷简单Android图片的这些界面就会消失,这个过程是因为当system_server他启动系统HomeUI的时候关闭了bootanim。这就是我们整个Android系统启动过程中UI显示的一个过程。
下面我们来看一下bootanim的一个启动和退出的框架图
在这个框架图中,我们会涉及到下面几个服务,第一个是我们的init进程,第二个是surfaceflinge Service服务,第三个是bootanim服务,第四个是Zygote进程,最后一个就是System_service服务,我们来看一下他们整个交互流程是怎样的。
首先我们的init进程会创建surfaceflinge Service和我们的Zygote服务,而surfaceflinge Service这个服务主要是初始化我们显示部分,管理我们显示的分层。当我们surfaceflinge 这个服务初始化完成之后,他就会调用我们的startBootAnim,他调用的过程就是启动bootanimation,启动之后他就开始和我们的surfaceflinge Service进行交互,然后得到一个显示的层,然后他会根据自己的一个显示机制去刷新我们的屏幕。在做这些相关操作的同时,我们的init进程还孵化出了我们的zygote服务,而我们的zygote服务,它主要是创建我们java层的主要服务和应用,其中最主要的服务就是我们的System_service服务,他用于启动我们整个Android系统java层的服务,在我们启动过程中会启动一个ActvityManagerService服务,它用来管理我们所有的应用,在启动过程中,他最后会调用startHomeActivityLocked这个应用,他就会真正的启动我们系统的一个lunch,在启动过程中,他会申请一个相关的显示,而这个显示是由WindowManagerService来完成的。当我们的startHomeActivityLocked启动完成之后,他就会向我们的WindowManagerService发送一个消息,这个消息就是我们的bootFinished,也就是我们整个系统可以正常运行了,调用这个之后我们的WindowManagerService就会向surfaceflinge Service这个服务发送一个消息,这个消息就是bootFinished,当我们的surfaceflinge Service拿到这个消息之后,他会做一件事情,将我们的service.bootanim.exit设置成1,而我们的bootanimation在不断刷新界面过程中,会实时检查service.bootanim.exit的值,如果这个值是1,那么bootanimation就会退出当前刷新,因为我们系统的主UI已经起来了,他的使命也就完成了,然后就会显示Android系统的主lunch,这就是我们bootanim的一个启动过程。
下面我们再来看一下bootanim的一个工作流程
首先我们会创建一个bootanimation的一个对象,然后调用他的readyToRun来做一下初始化工作,主要是申请一个surface,然后初始化opengles,这个过程我们还要和surfaceflinge Service打一个交道,当我们的初始化完成之后,就会根据我们的系统设置来决定是使用Android这种方式来进行显示,还是用movie来进行显示,这两种方式显示的过程是一样的,只不过显示内容是不一样的,我们的显示内容是一个zip包的格式,这个包会有我们的图片文件,我们的png文件,然后还有一个相关的配置,也就是我们的configure文件,当我们显示之前,我们首先会得到整个显示文件的信息,包括显示的大小,长和宽,以及显示的帧率,和我们显示图片的资源。配置之后,我们就会调用opengles的一些方法,然后再对我们这些图像进行处理,真正的显示。在显示过程中我们也会检查我们退出的priority,当我们检查到priority的设置为true的话,那我们就会直接退出,这些就是bootanimation的一个工作流程。
下面我们打开我们的bootanimation的代码,他的源文件在frameworks/base/cmds/bootanimation/bootanimation_main.cpp
我们来看一下main函数,首先会得到一个priority,看是否要显示我们的bootanimation,如果说我们的noBootAnimation是假的话,那么我们就要做一个bootanimation的显示过程,首先我们会创建一个ProcessState对象,然后启动我们一个线程池,创建了一个bootanimation的对象,在创建过程中,我们就会把这个对象添加到线程池中,然后去做一下相关工作,在这个new BootAnimation过程中,他会做下面的操作,这个函数继承了Thread这个类,这个类呢,当我们初始化的时候会有一个强指针,也就是强制的执行onFirstRef这个函数,在这里边他会做一些相关的操作,做完之后他还会做一个readyToRun的工作
readyToRun第一个就会和我们的surfaceflinge服务做一个交互,拿到一个显示的层,他会创建一个surfaceComposerClient,这就是我们surface的一个客户端,然后通过binder机制向我们的surfaceservice拿到显示的层,拿到之后他会创建一个显示的宽和高,以及各式,并且把显示的layer也给设置上,设置好之后就会开始做一些opengles的工作,这些工作都是标准的opengles的函数当我们把opengles初始化完成之后,代码就会决定,我们是使用Android的方式还是使用movie的方式来刷新界面,他在这里会判断下面几个目录,我们来看一下他们的定义
如果有这个system/media/bootanimation-encrypted.zip包的话,那么我们启动的时候就会刷新这个zip包,如果说我们的zip包是system/media/bootanimation.zip的话,那么就会刷新这个包,如果zip包时date/local/bootanimation.zip的话,那么就会刷新这个包,如果没有,那么我们就会刷新我们Android默认的zip包。
当我们判断完之后呢,我们的mZip对象就会是一个全局的,所以他会保存起来,然后在这里边如果有一个条件为真的话,那么我们就会调用我们movie的方法去刷新界面,当我们把这个init所有初始化完成之后呢,我们就会进入到我们的threadLoop,他会在这里真正的刷新我们的界面,
这个mAndroidAnimation变量,决定了我们是使用Android方法还是movie的方法来刷新界面,我们在这里应该是使用的movie的方法,下面我们来看一下movie的方法。
这个方法第一个就是拿到我们的zip包,然后进行一下相关的分析,包括我们的配置文件,以及图片信息,然后会解析我们的配置文件,包括我们显示的宽度、高度、帧率,以及后面所显示的一个频率。当我们把配置文件解析完成之后,就开始获取到我们一些图片的信息,这个就是我们获取图片信息的一个过程,把这些图片全部加载过来,加载完成之后我们就会用opengles将屏幕进行清屏,然后就会用一个for循环不断地刷新界面,这些刷新的过程都是调用opengles的过程,我们在刷新的过程中还会不断地检查我们的环境变量是否已经设置为退出,当我们检查完退出之后,我们的刷新过程也就完成了,然后退出movie,然后做一些清理工作,然后直接返回,返回之后我们整个bootanimation的启动过程以及刷新过程就结束了,这个服务也就停止了,这就是bootanimation的一个执行过程。
下面我们来看surfaceflingeservice是如何来启动和停止bootanimation的。我们来打开frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp,找到他的main函数
首先他也会初始化一个ProcessState,这个就是binder的一个机制,然后会启动一个线程池,启动完之后创建了一个surfaceflinger的一个对象,当这个对象创建完之后会调用他的init方法。这个init方法主要是对我们opengles做一些设置,根据我们硬件的配置来设置我们的参数,当我们整个surfaceflinger初始化完成之后呢,在最后就会调用startBootAnim,它主要做了两件事情,第一设置我们的service.bootanim.exit0,也就是现在需要不断地刷新我们的屏幕,第二个就是启动了我们的bootanim这个服务,我们启动bootanim用的就是startBootAnim这个方法。我们bootanim的退出也是在这个类中来实现的,当我们的主lunch启动之后呢,他就会向我们的surfaceflinger来发送消息,说我们的boot已经finished,这时候我们的surfaceflingerservice就会调用我们的bootFinished来将我们的bootanim停止,他停止所做的事情就是将我们的service.bootanim.exit设置为1,设置好之后我们的bootanim就退出了。这就是bootanimation启动、执行、退出的一个过程。
下面我们来看一下bootanimation.zip这个包里面的内容,和配置文件的一个格式,首先要切到adb下把我们板子上的这个包给pull下来
然后我们来看一下这个文件,我们先将他解压出来,
可以看到他有三个文件,我们来看一下desc.txt
我们再来看一下这些数字代表什么意思
我们的part0part1就是我们显示的图片,我们就不再看了
这样我们就会知道,我们bootanimation.zip的格式了
下面我们来看一下如何制作我们的bootanimation.zip,首先我们要替换显示的图片,然后按自己的喜好来修改desc.txt的配置,修改完之后我们就直接压缩这个zip包,压缩时要注意格式为存储的格式,不能直接压缩
现在我们自己的zip压缩包就弄完了,我们可以在板子上替换成自己的压缩包,那么在开机时就会显示我们自己的图片了。

相关帖子

沙发
jiang20082233| | 2015-12-11 14:38 | 只看该作者
   我顶。 。 关注很久了。。。楼主加油

使用特权

评论回复
板凳
xiaohai8856|  楼主 | 2015-12-11 14:56 | 只看该作者
谢谢,有空常来

使用特权

评论回复
地板
xiaohai8856|  楼主 | 2015-12-15 09:11 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

315

帖子

16

粉丝