上文分析了 mContext.getPackageManager() 调用流程,本文再简单说下 mPM.getPacakgeInfo()调用流程。
这里就涉及到了 binder 知识。
mPM 是 ApplicationPackageManager.java 类型,此类封装了 IPackageManager 的实现。
@Override
public PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException {
return getPackageInfoAsUser(packageName, flags, mContext.getUserId());
}
@Override
public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
throws NameNotFoundException {
try {
PackageInfo pi = mPM.getPackageInfo(packageName, flags, userId);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
}
base/core/java/android/content/pm/IPackageManager.aidl
/**
* See {@link PackageManager} for documentation on most of the APIs
* here.
*
* {@hide}
*/
interface IPackageManager {
void checkPackageStartable(String packageName, int userId);
boolean isPackageAvailable(String packageName, int userId);
PackageInfo getPackageInfo(String packageName, int flags, int userId);
.........................
说白了,aidl 文件顾名思义就是定义接口描述:接口名称,接口参数,返回值类型。跨进程通讯双方遵循这个格式传递数据。
Android在编译代码的时候转化未 IPackageManager.java文件:
@Override public android.content.pm.PackageInfo getPackageInfo(java.lang.String packageName, int flags, int userId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.content.pm.PackageInfo _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(packageName);
_data.writeInt(flags);
_data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_getPackageInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.content.pm.PackageInfo.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
从上面自动生成的代码可以看出,
getPackageInfo 函数讲传入参数打包成 Parcel请求,作为一个业务调用
mRemote.transact 函数发送到系统进程。
这个 mRemote 是个代理类,在 IPacakgeManager.java 实例化时就被创建:
/**
* 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);
}
..........
private static class Proxy implements android.content.pm.IPackageManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
.............
这个 transact 函数是在 frameworks/base/core/java/android/os/Binder.java 中由 BinderProxy 类实现的:
final class BinderProxy implements IBinder {
public native boolean pingBinder();
public native boolean isBinderAlive();
public IInterface queryLocalInterface(String descriptor) {
return null;
}
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
return transactNative(code, data, reply, flags);
}
从前面 IPackageManager 从 ActivityThread.java 中获取到的,这个从 ServiceManager 获取的 IBinder 接口来自于 PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub {
....
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
return m;
}
所以那个 transact 函数最终掉一个到 Binder.java 里的实现,最终走到 c 语言 so 库里执行。