8.1.2 三层之间的关系
应用层调用中间层PackageManager提供的API接口,一般通过以下代码:
PackageManager packageManager=getContext().getPackageManager();
getContext方法返回一个Context类型的对象,其功能由子类ContextImpl实现。在ContextImpl的getPackageManager方法中,主要做了两部分工作:
1)获得一个IPackageManager的Binder代理对象;
2)以该对象为参数构造一个ApplicationPackageManager对象返回。
代码如下:
public PackageManager getPackageManager(){
IPackageManager pm=ActivityThread.getPackageManager();
if(pm!=null){
//将服务接口pm存入ApplicationPackageManager成员变量mPm中
return(mPackageManager=new ApplicationPackageManager(this, pm));
}
return null;
}
获取Binder代理对象是通过ActivityThread上的getPackageManager方法。代码如下:
public static IPackageManager getPackageManager(){
IBinder b=ServiceManager.getService("package");
sPackageManager=IPackageManager.Stub.asInterface(b);
return sPackageManager;
}
这里是从ServiceManager中查询名为package的远程服务,并将其代理返回给调用方。可见应用层使用package服务的过程是一个典型的Binder通信模型。首先,Client端通过getPackageManager调用ServiceManager的getService方法,查询系统中已经注册的package系统服务,并返回服务的BinderProxy。然后,通过IPackageManager.Stub.asInterface方法将BinderProxy转化为服务接口IPackage Manager;最后Client端将服务接口存入ApplicationPackageManager的mPm成员变量中。ApplicationPackageManager是Package Manager的子类,Client端可以通过PackageManager提供的接口访问服务的BinderProxy,进而访问服务。
PackageManager的类关系如图8-2所示。
图 8-2 PackageManager的类关系
关于如何获取远程服务的Binder代理在第6章已经详细分析,本章不赘述。获取远程服务代理之后,以该代理对象为参数构造ApplicationPackageManager对象返回对调用方。为什么不是返回PackageManager呢?
因为PackageManager是一个抽象类,其具体的功能由其子类实现。读者可以在Eclipse中查看PackageManager的完整继承层次,如图8-3所示。
图 8-3 PackageManager的继承结构
注意 在Eclipse中可以通过鼠标选中PackageManager的类名,然后按Ctrl+T组合键显示类的继承树信息。
PackageManager有两个直接子类:ApplicationPackageManager和MockPackageManager。其中MockPackageManager及其子类只是测试框架的一部分,不提供真正的系统功能。应用层对PackageManager中API接口的调用其实是调用的ApplicationPackageManager中的实现方法。
注意 关于Android测试框架可以参考其官方文档http://developer.android.com/guide/topics/testing/index.html。
既然PackageManager的作用仅仅是返回名为package的Android系统服务的Binder代理对象。那Binder服务端是什么呢?
package系统服务是在Android启动过程的init2阶段启动的Java系统服务之一,其功能由PackageManagerService实现,其代码位于/frameworks/base/services/java/com/android/server/SystemServer.java。代码如下:
class ServerThread extends Thread{
//设备加密状态
private static final String ENCRYPTING_STATE="trigger_restart_min_framework";
private static final String ENCRYPTED_STATE="1";
……
public void run(){//ServerThread的run方法中启动Java系统服务
……
//工厂测试的系统属性配置项
String factoryTestStr=SystemProperties.get("ro.factorytest");
int factoryTest="".equals(factoryTestStr)?
SystemServer.FACTORY_TEST_OFF:Integer.parseInt(factoryTestStr);
……
IPackageManager pm=null;//引用package系统服务
……
try{
……
//系统属性配置的加密状态,设置加密状态后,onlyCore赋值为true
String cryptState=SystemProperties.get("vold.decrypt");
boolean onlyCore=false;
if(ENCRYPTING_STATE.equals(cryptState)){
onlyCore=true;
}else if(ENCRYPTED_STATE.equals(cryptState)){
onlyCore=true;
}
//启动package系统服务
pm=PackageManagerService.main(context,
factoryTest!=SystemServer.FACTORY_TEST_OFF,
onlyCore);
……
由以上代码可知,ServerThread在run方法中直接调用了PackageManagerService的main方法,并传入了两个关键参数:factoryTest和onlyCore。factoryTest表示是否是工厂测试启动模式;onlyCore表示是否只加载核心应用程序。factoryTest由属性系统ro.factorytest指定,而onlyCore由属性系统vold.decrypt指定。如果未指定这两个值,默认都是false。
接下来定位到PackageManagerService的main方法,代码如下:
public static final IPackageManager main(Context context,
boolean factoryTest, boolean onlyCore){
PackageManagerService m=new PackageManagerService(context,
factoryTest, onlyCore);
ServiceManager.addService("package",m);
return m;
}
可见,在Android启动过程中,通过调用PackageManagerService的main方法,创建PackageManagerService对象,并将该对象注册为ServiceManager管理的系统服务,服务名为package。PackageManagerService的构造过程便是package系统服务的启动过程。
这里为什么用main方法返回PackageManagerService对象,而不是直接new一个对象返回呢?原因有以下两点:
在Java和C语言中,main方法都是可执行程序的入口函数。这里是把package服务形象化为一个独立的服务程序,其入口函数自然就是main方法。
服务的启动和添加是整体的过程,放在一个方法中便于管理。
创建package服务便进入其构造函数,开始服务的启动过程,执行各种包处理操作。
注意 本节读者只需要了解package服务启动流程的主体过程,以此对package服务的启动有一个整体的认识。本章其余小节将详细分析其具体流程。
分析到这里,读者对Android包管理器三层体系结构中各层的关系和主要功能有了一定理解。下面将针对package服务做深入分析。