通过PackageManagerService理解AIDL中的Binder应用

目录

一、什么是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服务框架分析

注:图片来源网络,侵删!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为软件架构师,我可以给你一些关于Package Manager Service(软件包管理服务)的理解Package Manager Service是一种在操作系统负责管理软件包的核心服务。它提供了一组API和功能,用于安装、升级、卸载和管理软件包。这些软件包可以是应用程序、库或其他系统组件。 Package Manager Service的主要功能包括: 1. 软件包管理:它允许用户通过命令行或图形用户界面与软件包进行交互。用户可以查看已安装的软件包列表,搜索和安装新的软件包,升级已安装的软件包,以及卸载不再需要的软件包。 2. 依赖管理:在安装或升级软件包时,Package Manager Service会检查所需的依赖关系,并自动下载和安装缺失的依赖项。这确保了系统的软件包能够正确地运行,并且可以满足它们的依赖关系。 3. 版本控制:Package Manager Service会跟踪每个软件包的版本信息。当用户要求升级软件包时,它会检查可用的更新版本,并根据用户的选择来执行升级操作。 4. 存储库管理:Package Manager Service通过管理软件包的存储库来获取和更新软件包。存储库是一个集存储和维护软件包的地方,用户可以从获取所需的软件包。Package Manager Service可以管理多个存储库,并根据用户的配置和偏好进行软件包的检索和更新。 总的来说,Package Manager Service在操作系统扮演着重要的角色,使用户能够方便地管理和维护系统的软件包。它简化了软件安装和更新的过程,并提供了对依赖关系和版本控制的支持。 希望这个简要的解释能够帮助你理解Package Manager Service。如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值