一、概述
PackageManagerService是Android中比较重要的服务,它负责系统中Package的管理,应用程序的安装、卸载、信息查询等。
上图主要展示了PackageManagerService及客户端的通信方式,以及相关类的继承关系。为了简化描述,下文中我们将PackageMangerService称为”PKMS”。
1、
PKMS的客户端,必须通过PackageManager才能发送请求给PKMS,即可以认为PackageManger是PKMS的代理对象。
PackageManager是一个抽象类,实际的实现类是ApplicationPackageManager。当客户端利用Context的getPacakgeManager函数获取PackageManger时,获取的就是ApplicationPacakgeManager。
2、
ApplicationPackageManager与PKMS的交互实际上是基于Binder通信的,只不过利用AIDL文件封装了实现细节。
我们看看ApplicationManager的构造函数:
ApplicationPackageManager(ContextImpl context,
IPackageManager pm) {
mContext = context;
mPM = pm;
}
容易看出,ApplicationPackageManger中持有了IPackageManger对象。
IPacakgeManager对象是怎么得到的?
我们以ActivityThread.java中handleBindApplication函数中的一小段代码为例:
.......
try {
//getPackageManager函数将获取到IPackageManager对象
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
.......
}
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
//在之前的博客介绍Java层的Binder通信时,我们知道这里最终将会返回BinderProxy对象
IBinder b = ServiceManager.getService("package");
//将BinderProxy对象,转换成实际的业务代理对象
sPackageManager = IPackageManager.Stub.asInterface(b);
}
现在我们知道了,IPackageManager是PKMS的业务代理,其中服务端和客户端通信的业务函数由
framework/base/core/java/android/content/pm/IPackageManager.aidl文件来定义。
如上图所示,PKMS继承自IPackageManager.Stub,其实上也是基于Binder的服务端。
二、PKMS的启动
PKMS由SystemService在开机的时候启动,在SystemServer.java的run方法中:
private void run() {
.......
try {
.....
startBootstrapServices();
.....
startOtherServices();
.....
} ......
}
private void startBootstrapServices() {
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
Installer installer = mSystemServiceManager.startService(Installer.class);
.........
//根据系统属性,决定是否为加密设备加密
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (E