10.4 第二阶段:调用setSystemProcess方法

ActivityManagerService启动完成后,进入第二阶段,由ActivityManagerService.setSystemProcess方法完成,其代码如下:


public static void setSystemProcess(){

try{

ActivityManagerService m=mSelf;

/将ActivityManagerService注册到ServiceManager中,命名为activity/

ServiceManager.addService("activity",m, true);

/注册meminfo服务用于调试,其作用可以参考adb shell dumpsys meminfo/

ServiceManager.addService("meminfo",new MemBinder(m));

/注册gfxinfo服务用于调试,其作用可以参考adb shell dumpsys gfxinfo/

ServiceManager.addService("gfxinfo",new GraphicsBinder(m));

/*Android 4.1中新加入的服务,用于转储(dump)应用程序数据库信息

其作用可以参考adb shell dumpsys dbinfo/

ServiceManager.addService("dbinfo",new DbBinder(m));

/注册cpuinfo服务用于调试,其作用可以参考adb shell dumpsys cpuinfo/

if(MONITOR_CPU_USAGE){

ServiceManager.addService("cpuinfo",new CpuBinder(m));

}

/注册permission服务,用于检查进程的权限信息/

ServiceManager.addService("permission",new PermissionController(m));

/通过PackageManagerService查询包名为android的应用程序的ApplicationInfo信息/

ApplicationInfo info=

mSelf.mContext.getPackageManager().getApplicationInfo(

"android",STOCK_PM_FLAGS);

//调用ActivityThread上的方法

mSystemThread.installSystemApplicationInfo(info);

/*生成一个新的ProcessRecord类型的App对象,并将该对象存入

mProcessNames、mPidsSelfLocked/

synchronized(mSelf){

ProcessRecord app=mSelf.newProcessRecordLocked(

mSystemThread.getApplicationThread(),info,

info.processName, false);

app.persistent=true;//不能被回收

app.pid=MY_PID;//system_server的进程ID

app.maxAdj=ProcessList.SYSTEM_ADJ;//设置最大adj值

mSelf.mProcessNames.put(app.processName, app.uid, app);

synchronized(mSelf.mPidsSelfLocked){

mSelf.mPidsSelfLocked.put(app.pid, app);

}

//新加入一个App,需要更新LRU,后续分析

mSelf.updateLruProcessLocked(app, true, true);

}

}catch(PackageManager.NameNotFoundException e){

throw new RuntimeException(

"Unable to find android system package",e);

}

}


setSystemProcess()方法的功能大体可以分成三部分:

1)注册服务。首先将ActivityManagerService注册到ServiceManager中,然后将几个与系统性能调试相关的服务注册到ServiceManager。这些与性能调试相关的服务最终都将调用ActivityManagerService的方法,把它们与ActivityManagerService一起注册到ServiceManager,这样系统的调度和调试功能就完善了。

2)查询并处理ApplicationInfo。首先调用PackageManagerService的接口,查询包名为android的应用程序的ApplicationInfo信息,该信息来自Android启动时APK安装扫描过程,对应于framework-res.apk。然后以该信息为参数调用ActivityThread上的installSystemApplicationInfo方法。

3)创建并处理ProcessRecord。调用ActivityManagerService上的newProcessRecordLocked,创建一个ProcessRecord类型的对象,并保存该对象的信息。

第一部分是标准的注册服务过程,在第6章已经有详细分析,这里不赘述。下面主要分析第二和第三部分。

10.4.1 查询并处理ApplicationInfo

通过第8章和第9章分析可知,查询ApplicationInfo的工作最终由PackageManagerService的getApplicationInfo方法完成,其代码如下:


//传入的参数分别为android、STOCK_PM_FLAGS和当前User ID

public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId){

if(!sUserManager.exists(userId))return null;

synchronized(mPackages){

//首先从PackageManagerService.mPackages中查找包信息

PackageParser.Package p=mPackages.get(packageName);

if(p!=null){

//然后从mSettings.mPackages查找包设置信息

PackageSetting ps=mSettings.mPackages.get(packageName);

if(ps==null)return null;

//由包设置信息和包信息创建应用程序信息

return PackageParser.generateApplicationInfo(p, flags,

ps.getStopped(userId),ps.getEnabled(userId));

}

if("android".equals(packageName)||"system".equals(packageName)){

//由scanPackageLI开机扫描android包时赋值

return mAndroidApplication;

}

if((flags&PackageManager.GET_UNINSTALLED_PACKAGES)!=0){

return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);

}

}

return null;

}


查询ApplicationInfo的工作很简单,熟悉Package Manager(参考第8~9章)的读者很容易理解。接下来分析ApplicationInfo的处理过程,该过程通过调用mSystemThread的installSystemApplicationInfo方法完成。mSystemThread就是执行ActivityManagerService的main方法时,由ActivityThread.systemMain()返回的ActivityThread,其代码如下:


public final class ActivityThread{

……

public void installSystemApplicationInfo(ApplicationInfo info){

synchronized(this){

ContextImpl context=getSystemContext();

//已经是第四次见到系统Context的初始化了

context.init(new LoadedApk(this,"android",context, info,

CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO),null, this);

mProfiler=new Profiler();

}

}


可见installSystemApplicationInfo方法实际上再一次对系统Context进行初始化(第四次),过程是:首先调用getSystemContext()返回之前创建的系统Context对象,然后调用其init方法初始化。

这次初始化与之前的初始化有什么不同呢?这里唯一的不同就是传入LoadedApk构造方法的参数:多了一个ApplicationInfo类型的info参数。在前几次初始化过程中,传入LoadedApk构造函数的ApplicationInfo为null,因此在LoadedApk内部仅仅持有一个默认构造的ApplicationInfo,其不与任何应用程序的实际信息相关联。此处通过PackageManagerService获取frameworks-res.apk对应的实际ApplicationInfo,并存入LoadedApk内部。