快捷搜索:  汽车  科技

activity 流程和表单如何分开部署(应用程序与AMS的通讯实现)

activity 流程和表单如何分开部署(应用程序与AMS的通讯实现)private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { //1.获得一个代理对象 IBinder b = ServiceManager.getService("activity"); //2.将这个代理对象再通过一层封装 IActivityManager am = asInterface(b); return am; } }; static public IActivityM

1、前言

咱们在许多和Framework解析相关的文章中,都会看到ActivityManagerService这个类,可是在上层的应用开发中,却不多直接会使用到他

那么咱们为何要学习它的呢,一个最直接的好处就是它是咱们理解应用程序启动过程的基础,只有把和ActivityManagerService以及和它相关的类的关系都理解透了,咱们才能理清应用程序启动的过程

今天这篇文章,咱们就来对ActivityManagerService与应用进程之间的通讯方式作一个简单的总结,这里咱们根据进程之间的通讯方向,分为两个部分来讨论:

  • 从应用程序进程到管理者进程ide
  • (a) IActivityManager (b) ActivityManagerNative (c) ActivityManagerProxy (d) ActivityManagerService函数
  • 从管理者进程到应用程序进程学习
  • (a) IApplicationThread (b) ApplicationThreadNative (c) ApplicationThreadProxy (d) ApplicationThreadui
2、从应用程序进程到管理者进程

在这一方向上的通讯,应用程序进程做为客户端,而管理者进程则做为服务端。举一个最简单的例子,当咱们启动一个Activity,就须要通知全局的管理者,让它去负责启动,这个全局的管理者就运行在另一个进程,这里就涉及到了从应用程序进程到管理者进程的通讯

这一个方向上通讯过程所涉及到的类包括:

2.1 应用程序进程向管理者进程发送消息

当咱们想要启动一个Activity,会首先调用到Activity的:

@Override public void startActivityForResult( String who Intent intent int requestCode @Nullable Bundle options) { //... Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this mMainThread.getApplicationThread() mToken who intent requestCode options); //... }

以后调用到Instrumentation的:

public ActivityResult execStartActivity( Context who IBinder contextThread IBinder token Activity target Intent intent int requestCode Bundle options) { //.... int result = ActivityManagerNative.getDefault() .startActivity(whoThread who.getBasePackageName() intent intent.resolveTypeIfNeeded(who.getContentResolver()) token target != null ? target.mEmbeddedID : null requestCode 0 null options); //... }

这里咱们看到了上面UML图中ActivityManagerNative,它的getDefault()方法返回的是一个IActivityManager的实现类:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { //1.获得一个代理对象 IBinder b = ServiceManager.getService("activity"); //2.将这个代理对象再通过一层封装 IActivityManager am = asInterface(b); return am; } }; static public IActivityManager getDefault() { return gDefault.get(); }

这里,对于gDefault变量有两点说明:

  • 这是一个static类型的变量,所以在程序中的任何地方调用getDefault()方法访问的是内存中的同一个对象
  • 这里采用了Singleton模式,也就是懒汉模式的单例,只有第一次调用get()方法时,才会经过create()方法来建立一个对象

create()作了两件事:

  • 经过ServieManager获得IBinder,这个IBinder是管理进程在应用程序进程的代理对象,经过IBinder的transact方法,咱们就能够向管理进程发送消息:

public boolean transact(int code Parcel data Parcel reply int flags)

  • 将IBinder传入asInterface(IBinder b)构建一个IActivityManager的实现类,能够看到,这里返回的是一个ActivityManagerProxy对象:

static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } //这一步先忽略.... IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ActivityManagerProxy(obj); }

下面,咱们在来看一下这个ActivityManagerProxy,它实现了IActivityManager接口,咱们能够看到它所实现的IActivityManager接口方法都是经过构造这个对象时所传入的IBinder.transact(xxxx)来调用的,这些方法之间的区别就在于消息的类型以及参数。

class ActivityManagerProxy implements IActivityManager { public ActivityManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public int startActivity(IApplicationThread caller String callingPackage Intent intent String resolvedType IBinder resultTo String resultWho int requestCode int startFlags ProfilerInfo profilerInfo Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); //这个也很重要,咱们以后分析.. data.writeStrongBinder(caller != null ? caller.asBinder() : null); //发送消息到管理者进程... mRemote.transact(START_ACTIVITY_TRANSACTION data reply 0); reply.readException(); int result = reply.readInt(); reply.recycle(); data.recycle(); return result; } }

通过上面的分析,咱们用一句话总结:

应用程序进程经过ActivityManagerProxy内部的IBinder.transact(...)向管理者进程发送消息,这个IBinder是管理者进程在应用程序进程的一个代理对象,它是经过ServieManager得到的。

2.2 管理者进程处理消息

下面,咱们看一下管理者进程对于消息的处理,在管理者进程中,最终是经过ActivityManagerService对各个应用程序进行管理的。

它继承了ActivityManagerNative类,并重写了Binder类的onTransact(...)方法,咱们前面经过ActivityManagerProxy的IBinder对象发送的消息最终会调用到管理者进程中的这个函数当中,ActivityManagerNative对该方法进行了重写:

@Override public boolean onTransact(int code Parcel data Parcel reply int flags) throws RemoteException { switch (code) { case START_ACTIVITY_TRANSACTION: data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); String callingPackage = data.readString(); Intent intent = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); IBinder resultTo = data.readStrongBinder(); String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); ProfilerInfo profilerInfo = data.readInt() != 0 ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; //这里在管理者进程进行处理操做.... int result = startActivity(app callingPackage intent resolvedType resultTo resultWho requestCode startFlags profilerInfo options); reply.writeNoException(); reply.writeInt(result); return true; //... }

在onTransact(xxx)方法中,会根据收到的消息类型,调用IActivityManager接口中所定义的不一样接口,而ActivityManagerNative是没有实现这些接口的,真正的处理在ActivityManagerService中,ActivityManagerService开始进行一系列复杂的操做,这里以后咱们介绍应用程序启动过程的时候再详细分析。

@Override public final int startActivity(IApplicationThread caller String callingPackage Intent intent String resolvedType IBinder resultTo String resultWho int requestCode int startFlags ProfilerInfo profilerInfo Bundle bOptions) { return startActivityAsUser(caller callingPackage intent resolvedType resultTo resultWho requestCode startFlags profilerInfo bOptions UserHandle.getCallingUserId()); }

一样的,咱们也用一句话总结:

管理者进程经过onTransact(xxxx)处理应用程序发送过来的消息

3、从管理者进程到应用程序进程

接着,咱们考虑另外一个方向上的通讯方式,从管理者进程到应用程序进程,这一方向上的通讯过程涉及到下面的类:

ApplicationThread的整个框架和上面很相似,只不过在这一个方向上,管理者进程做为客户端,而应用程序进行则做为服务端。

3.1 管理者进程向应用程序进程发送消息

前面咱们分析的时候,应用程序进程向管理者进程发送消息的时候,是经过IBinder这个管理者进程在应用程序进程中的代理对象来实现的,而这个IBinder则是经过ServiceManager获取的:

IBinder b = ServiceManager.getService("activity");

同理,若是管理者进程但愿向应用程序进程发送消息,那么它也必须设法获得一个应用程序进程在它这边的代理对象。

咱们回忆一下,在第二节的分析中,应用者进程向管理者进程发送消息的同时,经过writeStringBinder,放入了下面这个对象:

public int startActivity(IApplicationThread caller ...) { //... data.writeStrongBinder(caller != null ? caller.asBinder() : null); //... mRemote.transact(START_ACTIVITY_TRANSACTION data reply 0); }

这个caller是在最开始调用startActivityForResult时传入的:

ActivityThread mMainThread; @Override public void startActivityForResult( String who Intent intent int requestCode @Nullable Bundle options) { //... Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this mMainThread.getApplicationThread() mToken who intent requestCode options); //... }

经过查看ActivityThread的代码,咱们能够看到它实际上是一个定义在ApplicationThread中的ApplicationThread对象,它的asBinder实现是在ApplicationThreadNative当中:

public IBinder asBinder() { return this; }

在管理者进程接收消息的时候,就能够经过readStrongBinder得到这个ApplicationThread对象在管理者进程的代理对象IBinder:

@Override public boolean onTransact(int code Parcel data Parcel reply int flags) throws RemoteException { switch (code) { case START_ACTIVITY_TRANSACTION: //取出传入的ApplicationThread对象,以后调用asInterface方法.. IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); //... int result = startActivity(app callingPackage intent resolvedType resultTo resultWho requestCode startFlags profilerInfo options); return true; } }

接着,它再经过asInterface(IBinder xx)方法把传入的代理对象经过ApplicationThreadProxy进行了一层封装:

static public IApplicationThread asInterface(IBinder obj) { if (obj == null) { return null; } IApplicationThread in = (IApplicationThread) obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ApplicationThreadProxy(obj); }

以后,管理者进程就能够经过这个代理对象的transact(xxxx)方法向应用程序进程发送消息了:

class ApplicationThreadProxy implements IApplicationThread { private final IBinder mRemote; public ApplicationThreadProxy(IBinder remote) { mRemote = remote; } public final IBinder asBinder() { return mRemote; } public final void schedulePauseActivity(IBinder token boolean finished boolean userLeaving int configChanges boolean dontReport) throws RemoteException { //.... mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION data null IBinder.FLAG_ONEWAY); //... }

这一个过程能够总结为:

管理者进程经过ApplicationThreadProxy内部的IBinder向应用程序进程发送消息,这个IBinder是应用程序进程在管理者进程的代理对象,它是在管理者进程接收应用程序进程发送过来的消息中得到的。

3.2 用户进程接收消息

在用户程序进程中,ApplicationThread的onTransact(....)就能够收到管理者进程发送的消息,以后再调用ApplicationThread所实现的IApplicationThread的接口方法进行消息的处理:

@Override public boolean onTransact(int code Parcel data Parcel reply int flags) throws RemoteException { switch (code) { case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION: data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean finished = data.readInt() != 0; boolean userLeaving = data.readInt() != 0; int configChanges = data.readInt(); boolean dontReport = data.readInt() != 0; schedulePauseActivity(b finished userLeaving configChanges dontReport); return true; }4、小结

以上就是应用程序进程和管理者进程之间的通讯方式,究其根本,都是经过获取对方进程的代理对象的transact(xxxx)方法发送消息,而对方进程则在onTransact(xxxx)方法中进行消息的处理,从而实现了进程之间的通讯

有需要文章中完整代码的同学 现在私信发送 “底层源码” 即可免费获取

现在私信发送 “进阶” 还可以获取《更多 Android 源码解析 核心笔记 面试真题》

activity 流程和表单如何分开部署(应用程序与AMS的通讯实现)(1)

最后我想说:

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

猜您喜欢: