目录
一、什么是AIDL
二、PackageManagerService中的AIDL
1、客户端PackageManager的初始化
2、服务端PackageManagerService的初始化
3、客户端PackageManager和服务端PackageManagerService的交互
三、AIDL的Binder使用分析
四、总结
一、什么是AIDL
Google官方文档的定义:
AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。
简单理解下就是:
AIDL其实就是通过Binder实现的,并且只用开发者定义好aidl文件后,Android 编译系统就会帮我们自动生成用于binder通信的一大堆文件。
如果还不了解Binder可以参考之前的文章:Android Binder 进程间通讯机制
因此它的作用就是:
方便系统为我们生成代码从而实现跨进程通讯,也就是说这个AIDL就只是一个封装了Binder的快速跨进程通讯的工具
二、PackageManagerService中的AIDL
如果之前有看:通过MediaPlayer简单理解Binder的使用
就会发现MediaPlayer的binder通信都是通过c++代码实现的 ,不方便java开发者学习。
并且Android 系统中的大量进程间通信实际上都是通过aidl的方式进行的。因此在学习PackageManagerService之前。我们有必要先学习下aidl是怎么进行进程间通信的
1、客户端PackageManager的初始化
frameworks/base/core/java/android/content/pm/PackageManager.java
69 public abstract class PackageManager {
70 private static final String TAG = "PackageManager";
71
72 /** {@hide} */
73 public static final boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = true;
74
75 /**
76 * This exception is thrown when a given package, application, or component
77 * name cannot be found.
78 */
79 public static class NameNotFoundException extends AndroidException {
80 public NameNotFoundException() {
81 }
82
83 public NameNotFoundException(String name) {
84 super(name);
85 }
86 }
...
5879 }
原来PackageManager就是个普通的接口类,也没有实现其他接口,或者继承其他类。具体的实现ApplicationPackageManager
frameworks/base/core/java/android/app/ApplicationPackageManager.java
99 public class ApplicationPackageManager extends PackageManager {
100 private static final String TAG = "ApplicationPackageManager";
101 private final static boolean DEBUG_ICONS = false;
102
103 private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
104
105 // Default flags to use with PackageManager when no flags are given.
106 private final static int sDefaultFlags = PackageManager.GET_SHARED_LIBRARY_FILES;
...
1349 ApplicationPackageManager(ContextImpl context,
1350 IPackageManager pm) {
1351 mContext = context;
1352 mPM = pm;
1353 }
...
2484 }
可以看到这个ApplicationPackageManager 也仅仅是一个普通的java类。但是他的构造方法的第二个参数却是IPackageManager
并且把它当成服务端再用。那现在就看下这个ApplicationPackageManager是在哪初始化的,并且传入的参数IPackageManager又是从哪来的
frameworks/base/core/java/android/app/ContextImpl.java
211 public PackageManager getPackageManager() {
212 if (mPackageManager != null) {
213 return mPackageManager;
214 }
215
216 IPackageManager pm = ActivityThread.getPackageManager();
217 if (pm != null) {
218 // Doesn't matter if we make more than one instance.
219 return (mPackageManager = new ApplicationPackageManager(this, pm));
220 }
221
222 return null;
223 }
看到他的参数IPackageManager是从 ActivityThread.getPackageManager()获取的
frameworks/base/core/java/android/app/ActivityThread.java
1838 public static IPackageManager getPackageManager() {
1839 if (sPackageManager != null) {
1840 //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1841 return sPackageManager;
1842 }
1843 IBinder b = ServiceManager.getService("package");
1844 //Slog.v("PackageManager", "default service binder = " + b);
1845 sPackageManager = IPackageManager.Stub.asInterface(b);
1846 //Slog.v("PackageManager", "default service = " + sPackageManager);
1847 return sPackageManager;
1848 }
可以看到通过ServiceManager.getService("package") 获取指定的IBinder
然后通过IPackageManager.Stub.asInterface(b) 将IBinder 转化为IPackageManager
这样就完成了客户端的分析:
客户端再初始化的时候会通过ServiceManager获取服务端的代理
将服务端的代理IPackageManager传入客户端构造,并在客户端使用
2、服务端PackageManagerService的初始化
看下服务端PackManagerService的初始化
frameworks/base/services/java/com/android/server/SystemServer.java
466 traceBeginAndSlog("StartPackageManagerService");
467 mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
468 mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
469 mFirstBoot = mPackageManagerService.isFirstBoot();
470 mPackageManager = mSystemContext.getPackageManager();
471 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
在SystemServer中调用PackageManagerService.main()方法初始化,看下main方法里都干了什么?
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
2008 public static PackageManagerService main(Context context, Installer installer,
2009 boolean factoryTest, boolean onlyCore) {
2010 // Self-check for initial settings.
2011 PackageManagerServiceCompilerMapping.checkProperties();
2012
2013 PackageManagerService m = new PackageManagerService(context, installer,
2014 factoryTest, onlyCore);
2015 m.enableSystemUserPackages();
2016 ServiceManager.addService("package", m);
2017 return m;
2018 }
可以看到main方法里创建了PackageManagerService 服务并添加到ServiceManager中
然后看下PackageManagerService的定义
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
355 public class PackageManagerService extends IPackageManager.Stub {
356 static final String TAG = "PackageManager";
357 static final boolean DEBUG_SETTINGS = false;
358 static final boolean DEBUG_PREFERRED = false;
359 static final boolean DEBUG_UPGRADE = false;
...
21445 }
可以看到原来PackageManagerService 就是继承了IPackageManager的内部类Stub,看下IPackageManager
frameworks/base/core/java/android/content/pm/IPackageManager.aidl
62 interface IPackageManager {
63 void checkPackageStartable(String packageName, int userId);
64 boolean isPackageAvailable(String packageName, int userId);
65 PackageInfo getPackageInfo(String packageName, int flags, int userId);
66 int getPackageUid(String packageName, int flags, int userId);
67 int[] getPackageGids(String packageName, int flags, int userId);
...
579 }
可以看到aidl实际就是一个类似于java中的接口类,然后定义了一下基本的接口方法,并没有看到内部类Stub啊
原来这就是aidl的便捷所在,只需要定义好aidl文件,编译的时候系统就会自动生成IPackageManager.java文件
让我们看下自动生成的IPackageManager.java文件
3、客户端PackageManager和服务端PackageManagerService的交互
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/pm/IPackageManager.java
public interface IPackageManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager
{
private static final java.lang.String DESCRIPTOR = "android.content.pm.IPackageManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.content.pm.IPackageManager interface,
* generating a proxy if needed.
*/
public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.content.pm.IPackageManager))) {
return ((android.content.pm.IPackageManager)iin);
}
return new android.content.pm.IPackageManager.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
private static class Proxy implements android.content.pm.IPackageManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
IPackageManager接口类中定义了服务端和客户端通信的业务函数,还定义了内部类Stub,该类从Binder派生并实现了IPackageManager接口。
PackageManagerService继承自IPackageManager.Stub类,由于Stub类从Binder派生,因此PackageManagerService将作为服务端参与Binder通信。
Stub类中定义了一个内部类Proxy,该类有一个IBinder类型(实际类型为BinderProxy)的成员变量mRemote,根据第2章介绍的Binder系统的知识,mRemote用于和服务端PackageManagerService通信。
IPackageManager接口类中定义了许多业务函数,但是出于安全等方面的考虑,Android对外(即SDK)提供的只是一个子集,该子集被封装在抽象类PackageManager中。客户端一般通过Context的getPackageManager函数返回一个类型为PackageManager的对象,该对象的实际类型PackageManager的子类ApplicationPackageManager。这种基于接口编程的方式,虽然极大降低了模块之间的耦合性,却给代码分析带来了不小的麻烦。
ApplicationPackageManager类继承自PackageManager类。它并没有直接参与Binder通信,而是通过mPM成员变量指向一个IPackageManager.Stub.Proxy类型的对象。
三、AIDL的Binder使用分析
剩下的步骤
1、asInterface将参数IBinder 转化为IPackageManager 可以参考通过MediaPlayer简单理解Binder的使用 中的IBinder转化为IMediaPlayerService的内容
2、onTransact方法的回调 也可以参考通过MediaPlayer简单理解Binder的使用 中的对应部分
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_checkPackageStartable:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _arg1;
_arg1 = data.readInt();
this.checkPackageStartable(_arg0, _arg1);
reply.writeNoException();
return true;
}
case TRANSACTION_isPackageAvailable:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _arg1;
_arg1 = data.readInt();
boolean _result = this.isPackageAvailable(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_getPackageInfo:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
onTransact 方法中的具体实现就是调用this.xxx,而这个this正事继承了IPackageManager.Sutb 的 PackageManagerService
四、总结
1、服务端PackageManagerService 开机初始化后将自己添加到ServiceManager.addService()
2、客户端ApplicationPackageManager 通过ServiceManager.getService()找到服务端的代理IPackageManager
3、创建客户端的时候通过客户端构造方法将IPackageManager传入,并使用
4、IPackageManager代理最终会通过onTransact方法中的this.xxx 调用继承了IPackageManager的服务端PackageManagerService执行具体的方法
至此,ApplicationPackageManager 和PackageManagerService的通信到此结束。后续分析时就可以知道直接跳过两个进程通信的部分,直接看相应业务代码了。
接下来想了解PackageManagerService可以参考:PackageManagerService服务框架分析
注:图片来源网络,侵删!