Android系统的本地部分启动流程可以分为以下的几个步骤:
(1)BootLoader运行(Linux通用内容,如U-Boot的启动);
(2)Linux内核运行(Linux通用内容,通常是二进制机器代码形式存在);
(3)内核加载根文件系统(Linux通用内容:如从Flash中加载);
(4)init进程运行(用户空间的第一个进程);
(5)运行init.rc脚本;
(6)加载system和data文件系统;
(7)运行各种服务(主要为各个守护进程);
了解Android系统启动流程需要关注以下几个方面:
(1)系统总体的结构(如几个单独的映像);
(2)各个具体程序的组成部分(如可执行程序和配置内容);
(3)系统的运行时结构(如分成若干个进程);
(4)启动流程中系统控制权的转移;
一、启动流程介绍
1. 硬件启动流程
由图可知,系统开机时按照确定的复位时序启动,然后执行bootloader,进入内核初始化操作,当内核初始化完
毕后,便运行linux的第一个应用程序,即android系统的init。
2. android init 流程分析
Init流程的关键点在于分析*.rc文件,这个*.rc是android的启动脚本,其定义了android待执行的一些命令及相关
service。解析完该文件后,init把待执行的相关命令添加到执行队列,这样在init的轮询过程中,依次执行这些命令。
Init的轮询过程就是启动所有执行队列里command,重启所有需要重启的service,同时启动一个socket用于接收用户对
属性的设置请求,最后接收service终止信号,根据service属性选择重启service或资源回收。
3. Zygote分析
查看zygote在init.rc的启动参数
servicezygote /system/bin/app_process -Xzygote /system/bin --zygote--start-system-server
class main
socket zygotestream 666
Zygote函数原型在app_main.cpp里,通过main函数传递相关参数。阅读main函数代码,发现其最后调用
AppRuntime的start来启动java类ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ?"start-system-server" : "");
start函数有以下三个功能:
(1)调用startVm创建java虚拟机。
(2)调用startReg注册JNI函数。
(3)找到ZygoteInit类,并通过JNI,调用该类的main函数,该函数如下:
public staticvoid main(String argv[]) {
try {
// Start profiling the zygoteinitialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygoteinitialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean upafter startup
gc();
// If requested, start systemserver directly from Zygote
if (argv.length != 2) {
throw newRuntimeException(argv[0] + USAGE_STRING);
}
if(argv[1].equals("start-system-server")) {
startSystemServer();
} else if(!argv[1].equals("")) {
throw newRuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting commandsocket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died withexception", ex);
closeServerSocket();
throw ex;
}
}
该函数主要功能如下:
(1)启动服务端的socket。
(2)调用preload(),预加载java相关类及资源。
(3)Fork子进程SystemServer,所谓fork就是子进程复制父进程的资源,而且只有在子进程或父进程有写操作时,
才进行复制,可节省启动时间。
(4)通过socket监听子进程的请求,然后启动相应服务
从以上分析可知,zygote主要负责启动java虚拟机,注册jni函数,预加载java相关类及资源,启动systemserver
子进程,最后监听子进程的请求,启动响服务。自此,我们需要继续跟踪systemserver子进程,才能继续追溯启动
流程。
4. SystemServer分析
分析zygote启动SystemServer的函数startSystemServer()可知,zygote卵化出了systemserver进程,最后调用到
SystemServer类的main函数,该函数执行的功能主要如下:
public staticvoid main(String[] args) {
…
System.loadLibrary("android_servers");
init1(args);
}
调用android_server_SystemServer_init1函数,该函数如下:
static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
system_init();
}
又调用system_init,如下:
extern"C" status_t system_init()
{
…
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf,"1");
if (strcmp(propBuf, "1") == 0) {
//Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
…
jclass clazz =env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
return UNKNOWN_ERROR;
}
jmethodID methodId =env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz,methodId);
LOGI("System server: entering threadpool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting threadpool.\n");
return NO_ERROR;
}
反过来调用SystemServer的init2,如下:
public staticfinal void init2() {
Slog.i(TAG, "Entered the Androidsystem server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
这里启动了一个ServiceThread线程,最终会执行里面的run函数
public voidrun() {
Slog.i(TAG, "Power Manager");
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
Slog.i(TAG, "Telephony Registry");
ServiceManager.addService("telephony.registry", newTelephonyRegistry(context));
AttributeCache.init(context);
Slog.i(TAG, "Package Manager");
// Only run "core" apps if we're encrypting the device.
String cryptState = SystemProperties.get("vold.decrypt");
boolean onlyCore = false;
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detectedencryption in progress - only parsing core apps");
onlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Deviceencrypted - only parsing core apps");
onlyCore = true;
}
pm = PackageManagerService.main(context,
factoryTest !=SystemServer.FACTORY_TEST_OFF,
onlyCore);
boolean firstBoot = false;
try {
firstBoot = pm.isFirstBoot();
} catch (RemoteException e) {
}
ActivityManagerService.setSystemProcess();…
…
}
该代码很长,但一看就知道,这里启动了java世界的各种服务线程,包括ActivityManagerService、
PackageManagerService.等。
其中PackageManagerService服务线程就是扫描系统的所有app(/system/app、/data/app、
/data/dalvik-cache、/system/framework/*.apk;*.jar、/data/secure、/data/drm、/data/app-private、/data/data.)
并预加载。
再看看与ActivityManagerService相关的内容:
context = ActivityManagerService.main(factoryTest);
ActivityManagerService.setSystemProcess();
ActivityManagerService.installSystemProviders();
ActivityManagerService.self().systemReady
其中在systemReady函数最后一句,
mMainStack.resumeTopActivityLocked(null);
具体代码如下:
final booleanresumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
returnmService.startHomeActivityLocked();
}
}
}
分析代码可知,如果任务队列中有activity,则执行第一个activity,如果没有的话,则启动home程序。由于系统
一开始并没有activity,则启动home程序。
通过上述分析,系统终于启动完毕了,第一个activity产生。值得注意的是,ActivityManagerService的
startHomeActivityLocked,实际上系统发出了一个category字段包含CATEGORY_HOME的intent,如下代码:
if (mFactoryTest!= SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
无论是哪个应用程序,只要声明自己能够响应intent,那么久可以认为是home程序。当系统中有多个程序能够
响应该intent是,系统会弹出一个框,请求用户选择哪个应用程序。当用户选择完,之后每次按home键,系统都会
执行选择的home activity。
二、开机启动界面
1. 开机logo
在init流程时,有一个console_init,里面会加载android系统启动LOGO,如果该LOGO不在,将默认显示
android字样。另外,该LOGO是直接写FRAMEBUFFER的,所以不需要依赖于surface,这个同开机动画不同。
2. 开机动画
系统启动的开机动画,源码里默认是没有的,所以总会跳到android字体闪动的画面。这个闪动的android字体
实际上是两张图,一张镂空的android图,一张发光效果,动画效果就是下面那张发光的效果图不断左右移动,
这两张图存放在:
android4.0.1\frameworks\base\core\res\assets\images
那如何添加自己的开机动画呢?方法如下:
制作一个bootanimation.zip包,然后把它放到/system/media/目录下,重新打包固件。
至于它是如何启动的,还得返回来看看system_init()这个函数,有
SurfaceFlinger::instantiate();
这个函数实际上是把surfaceflinger实例化,最终启动surfaceflinger服务,调用surfaceflinger的readyToRun(),
如下:
status_t SurfaceFlinger::readyToRun()
{
……
// start boot animation
property_set("ctl.start","bootanim");
return NO_ERROR;
}
这里,init.rc里面记录的bootanim进程被创建,开机动画由这个进程放出来。
继续分析,我们回到init.c里
int main()
{
struct pollfd ufds[4];
……
if (!property_set_fd_init && get_property_set_fd()> 0) { //为property创建一个socket
ufds[fd_count].fd = get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
property_set_fd_init = 1;
}
nr =poll(ufds, fd_count, timeout); //等待socket事件到来
for(i = 0; i < fd_count; i++) {
if(ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd()) //处理property设置事件
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
}
……
}
看看handle_property_set_fd,
voidhandle_property_set_fd()
{
r = recv(s, &msg, sizeof(msg), 0);
switch(msg.cmd) {
casePROP_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);
}
}
}
}
再调用handle_control_message,如下:
voidmsg_start(const char *name)
{
if(svc) {
service_start(svc, args);
}
}
这样,开机动画的bootanim就启动了。