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内部。