3.2 SystemServer分析

SystemServer是由Zygote孵化而来的一个进程,通过ps命令,可知其进程名为system_server。

注意 system_server进程在DDMS中看到的进程名为system_process。

3.2.1 main函数分析

SystemServer核心逻辑的入口是main函数,其代码如下:

[—>SystemServer.java:main]


public static void main(String[]args){

if(System.currentTimeMillis()<EARLIEST_SUPPORTED_TIME){

//如果系统时钟早于1970年,则设置系统时钟从1970年开始

Slog.w(TAG,"System clock is before 1970;setting to 1970.");

SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);

}

//判断性能统计功能是否开启

if(SamplingProfilerIntegration.isEnabled()){

SamplingProfilerIntegration.start();

timer=new Timer();

timer.schedule(new TimerTask(){

@Override

public void run(){

//SystemServer性能统计,每小时统计一次,统计结果输出为文件

SamplingProfilerIntegration.writeSnapshot("system_server",

null);

}//SNAPSHOT_INTERVAL定义为1小时

},SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

}

//和Dalvik虚拟机相关的设置,主要是内存使用方面的控制

dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

//加载动态库libandroid_servers.so

System.loadLibrary("android_servers");

init1(args);//调用native的init1函数

}


main函数首先做一些初始化工作,然后加载动态库libandroid_servers.so,最后调用native的init1函数。该函数在libandroid_servers.so库中实现,其代码如下:

[—>com_android_server_SystemServer.cpp:system_init]


extern"C"int system_init();

static void android_server_SystemServer_init1(JNIEnv*env, jobject clazz)

{

system_init();//调用上面那个用extern声明的system_init函数

}


而system_init函数又在另外一个库libsystem_server.so中实现,代码如下:

[—>System_init.cpp:system_init]


extern"C"status_t system_init()

{

LOGI("Entered system_init()");

//初始化Binder系统

sp<ProcessState>proc(ProcessState:self());

//获取ServiceManager的客户端对象BpServiceManager

sp<IServiceManager>sm=defaultServiceManager();

//GrimReaper俗称死神

sp<GrimReaper>grim=new GrimReaper();

/*

下面这行代码的作用就是注册grim对象为ServiceManager死亡信息的接收者。一旦SM死亡,

Binder系统就会发送讣告信息,这样grim对象的binderDied函数就会被调用。该函数内部

将杀死(kill)自己(即SystemServer)。

笔者觉得,对于这种因挚爱离世而自杀的物体,叫死神不太合适

*/

sm->asBinder()->linkToDeath(grim, grim.get(),0);

char propBuf[PROPERTY_VALUE_MAX];

//判断SystemServer是否需要启动SurfaceFlinger服务,该值由init.rc

//脚本设置,默认为零,即不启动SF服务

property_get("system_init.startsurfaceflinger",propBuf,"1");

/*

从Android4.0开始,和显示相关的核心服务surfaceflinger可独立到另外一个进程中。

笔者认为,这可能和目前SystemServer的负担过重有关。另外,随着智能终端上HDMI的普及,

未来和显示相关的工作将会越来越繁重。将SF放在单独进程中,不仅可加强集中管理,也可充分

利用未来智能终端上多核CPU的资源

*/

if(strcmp(propBuf,"1")==0){

SurfaceFlinger:instantiate();

}

//判断SystemServer是否启动传感器服务,默认将启动传感器服务

property_get("system_init.startsensorservice",propBuf,"1");

if(strcmp(propBuf,"1")==0){

//和SF相同,传感器服务也支持在独立进程中实现

SensorService:instantiate();

}

//获得AndroidRuntime对象

AndroidRuntime*runtime=AndroidRuntime:getRuntime();

JNIEnv*env=runtime->getJNIEnv();

……//查找Java层的SystemServer类,获取init2函数的methodID

jclass clazz=env->FindClass("com/android/server/SystemServer");

……

jmethodID methodId=env->GetStaticMethodID(clazz,"init2","()V");

……//通过JNI调用Java层的init2函数

env->CallStaticVoidMethod(clazz, methodId);

//主线程加入Binder线程池

ProcessState:self()->startThreadPool();

IPCThreadState:self()->joinThreadPool();

return NO_ERROR;

}


SystemServer的main函数究通过init1函数,从Java层穿越到Native层,做了一些初始化工作后,又通过JNI从Native层穿越到Java层去调用init2函数。

init2函数返回后,最终又回归到Native层。

是不是感觉init1和init2这两个函数的命名和我们初学编程时自定义的函数名非常像呢?其实代码中有一段“扭捏”的注释,解释了编写这种“初级”代码的原因,也就是在对AndroidRuntime初始化前必须先初始化一些核心服务。