前言
进程间通信的时候,我们经常使用的是AIDL的方式,下面先给出一个简单的栗子:
首先定义我们的AIDL文件,在Android Studio创建一个AIDL文件:
创建AIDL文件.png
定义如下:
package com.nan.testbinder; interface IAidlInterface { String pay(int pwd); }
在这个AIDL里面,我们定义一个接口,里面有一个pay方法来模拟支付宝的支付。输入参数是支付密码,返回支付结果。然后我们rebuild一下项目,AS就会自动为我们定义的AIDL文件生成一个Java文件,这里我们先不详细介绍这个文件:
自动生成的java文件.png
然后创建我么的远程服务:
import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import com.nan.testbinder.IAidlInterface; public class MyService3 extends Service { public static final String TAG = MyService3.class.getSimpleName(); public MyService3() { Log.e(TAG, "MyService3"); } @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind"); return new Interface(); } @Override public void onCreate() { Log.e(TAG, "onCreate"); } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.e(TAG, "onDestroy"); } public class Interface extends IAidlInterface.Stub { @Override public String pay(int pwd) throws RemoteException { if (pwd == 123) { return "支付成功"; } return "支付失败"; } } }
在这个服务里面,我们创建了一个接口类Interface,继承了自动生成的Java文件里面的Stub类。并且复写里面的pay方法。
最后在Service的onBind方法里面返回这个类的对象。
我们在清单文件中把这个服务定义为远程服务,即指定了服务所在的进程为:remote
<service android:name=".service.MyService3" android:enabled="true" android:exported="true" android:process=":remote"> </service>
然后在Activity中定义一个ServiceConnection类,用于跟远程服务连接。这里通过Stub的asInterface方法把IBinder对象转换为AIDL的接口。
转换成功之后,我们就尝试调用接口的pay方法,成功/失败的时候通过一个Toast来打印支付结果。
class MyRemoteServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //通过Stub的asInterface把拿到的IBinder引用转换为AIDL接口的实现类 mRemoteInterface = IAidlInterface.Stub.asInterface(service); if (mRemoteInterface != null) { String result; try { result = mRemoteInterface.pay(123); Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { //连接因为异常而终止才会调用 } }
最后在Activity中绑定服务/解绑服务:
mRemoteConn = new MyRemoteServiceConnection(); Intent intent4 = new Intent(MainActivity.this, MyService3.class); //绑定 bindService(intent4, mRemoteConn, BIND_AUTO_CREATE); //解绑 unbindService(mRemoteConn);
为什么要使用AIDL?
我们在进行进程间通信的时候,我们是无法拿到另外一个进程的类的对象,因为两个进程不在一个内存里面,它们都分配在不同的虚拟机中。这样的话,即使我们的类使用了静态变量,编译通过了,也无法进行通信。
如下图所示,两个进程就像是一个中国人跟一个日本人,假设双方都不懂对方的语言。比如现在中国人要发送一句话”不要“给日本人,但是在日语里面”不要“就是”雅蠛蝶“,因此正常情况下是不能正常沟通的(程序直接不能直接通过变量、函数来访问)。那么AIDL就是我们的中间者,比如说AIDL是英语,假设中国人和日本人都懂英语,那么两者之间就可以间接地沟通了。
下图是跨进程通信的基本架构:
进程间通信模型.png
Android系统会单独地分配一块内存,这块内存专门用于进程间的通信的。一旦我们的远程进程(服务)启动以后,就会在这块内存注册一个IBinder的引用。但是这个引用跟两个进程没有程序上的关系,不能直接把对象扔进来,他只保存了服务的包名、类名、这个服务有哪些变量等等。IBinder的引用的出现也就代表着客户端可以与该服务进行通信了。
进程间通信是类似于C/S架构的,一个AIDL的接口包括Stub以及Proxy,分别叫做存根,代理。Stub主要跟服务端交互,Proxy主要跟客户端交互。进程间通信最基本的概念就是数据的读写,客户端向IBinder中写数据,Stub从IBinder读数据。IBinder就相当于即时通信中的中间服务器。
自动生成的接口类分析
package com.nan.testbinder; public interface IAidlInterface extends android.os.IInterface { public static abstract class Stub extends android.os.Binder implements com.nan.testbinder.IAidlInterface { //包名 private static final java.lang.String DESCRIPTOR = "com.nan.testbinder.IAidlInterface"; public Stub() { this.attachInterface(this, DESCRIPTOR); } public static com.nan.testbinder.IAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.nan.testbinder.IAidlInterface))) { return ((com.nan.testbinder.IAidlInterface) iin); } return new com.nan.testbinder.IAidlInterface.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; } case TRANSACTION_pay: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); java.lang.String _result = this.pay(_arg0); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.nan.testbinder.IAidlInterface { 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; } @Override public java.lang.String pay(int pwd) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(pwd); mRemote.transact(Stub.TRANSACTION_pay, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_pay = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public java.lang.String pay(int pwd) throws android.os.RemoteException; }
下面开始分析,如下图所示,这是Android Studio给出的整个类的结构图,这个接口有两个内部类Stub和Proxy。其中Stub是将来要从IBinder读数据的,Proxy将要从IBinder写数据的。
自动生成的接口类结构.png
其中DESCRIPTOR是本类的包名。因为要保证两边能够通信,需要确保两边要知道对方的类名。
private static final java.lang.String DESCRIPTOR = "com.nan.testbinder.IAidlInterface";
下面是Stub的构造函数,里面调用了父类的attachInterface函数:
public Stub() { this.attachInterface(this, DESCRIPTOR); } public void attachInterface(IInterface owner, String descriptor) { mOwner = owner; mDescriptor = descriptor; }
这里把this(IAidlInterface AIDL的引用,也就是自己)以及DESCRIPTOR描述绑定到Binder里面,
如果是同一个进程之间的通信的话,比如说Activity与同一个进程的Service通信,那么就会直接利用本地的接口引用。
当我们的远程服务启动的时候,就会注册一个IBinder引用,一旦Service绑定成功以后就会回传IBinder引用。但是拿到IBinder并不能马上通信,实际上最终还要拿到AIDL实现类的对象,这样才能通信。也就是说,拿到IBinder并且根据描述DESCRIPTOR来产生我们需要的AIDL的实现类。
例如上述栗子中的代码:
//通过Stub的asInterface把拿到的IBinder引用转换为AIDL接口的实现类 mRemoteInterface = IAidlInterface.Stub.asInterface(service);
下面我们看asInterface的源码,刚刚已经解释过了,如果是同一个进程之间的通信的话,那么就直接使用本地的AIDL实现类引用,因此下面的代码是先通过IBinder的queryLocalInterface方法去找本地的引用。
public static com.nan.testbinder.IAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } //先通过IBinder的queryLocalInterface方法去找本地的引用 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.nan.testbinder.IAidlInterface))) { return ((com.nan.testbinder.IAidlInterface) iin); } return new com.nan.testbinder.IAidlInterface.Stub.Proxy(obj); }
由于IBinder只是一个接口,那么如果要看queryLocalInterface的实现的话,就需要去看Binder的源码:
public IInterface queryLocalInterface(String descriptor) { if (mDescriptor.equals(descriptor)) { return mOwner; } return null; }
这段代码很明确了,就是如果Stub构造的时候保存的DESCRIPTOR与我们需要的descriptor是一致的话,说明是同一个进程的,那就直接返回本地的AIDL实现类(mOwner)。
如果本地没有,那么就是不同进程的,那么这时候就需要通过IBinder引用去初始化我们的AIDL对象:
return new com.nan.testbinder.IAidlInterface.Stub.Proxy(obj);
下面就需要去看Proxy的构造函数:
Proxy(android.os.IBinder remote) { mRemote = remote; }
再来看一下Proxy的类,它并没有继承Binder,而是直接实现了AIDL的接口:
private static class Proxy implements com.nan.testbinder.IAidlInterface
也就是说,Proxy构造的时候,就是通过IBinder引用转换为AIDL的接口的实现类的过程。
下面继续分析Stub的onTransact方法:
@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_pay: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); java.lang.String _result = this.pay(_arg0); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); }
Stub相当于服务端,以后IBinder要向Stub进行写数据。通信的时候会回调onTransact方法。
进程间通信无非就是“函数的间接调用”,下面这是我在AIDL里面定义的pay方法,如果客户端的pay方法被调用,那么远程的相应的方法也会被调用。
整个过程是这样的,先是客户端通过Proxy向IBinder写数据,Parcel与序列化有关。
@Override public java.lang.String pay(int pwd) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { //把描述和数据写到一个Parcel对象,描述用于控制将来数据发送到哪个对象。 _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(pwd); //写数据,但是不知道是哪一个函数,只知道是第几个函数,先去调用IBinder的transact //然后IBinder去连接远程Stub对象,最后回调远程Stub的onTransact方法 mRemote.transact(Stub.TRANSACTION_pay, _data, _reply, 0); //读取是否有异常 _reply.readException(); //读取结果(返回值),同步读取的 _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; }
下面我们看Binder中transact方法的实现
public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (false) Log.v("Binder", "Transact: " + code + " to " + this); if (data != null) { data.setDataPosition(0); } boolean r = onTransact(code, data, reply, flags); if (reply != null) { reply.setDataPosition(0); } return r; }
池的概念,先进先出的队列的方法:
public static Parcel obtain() { final Parcel[] pool = sOwnedPool; synchronized (pool) { Parcel p; for (int i=0; i<POOL_SIZE; i++) { p = pool[i]; if (p != null) { pool[i] = null; if (DEBUG_RECYCLE) { p.mStack = new RuntimeException(); } return p; } } } return new Parcel(0); }
远程Stub的onTransact方法实现:
@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_pay: { //把DESCRIPTOR传进来作为验证,如果与本地的描述一样的话,下面继续执行。 data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); //回调自己的pay方法 java.lang.String _result = this.pay(_arg0); //把结果返回IBinder,然后再回传给客户端 reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); }
bindService的全过程源码分析
要看bindService的话,先要找到Context的实现类ContextImpl。
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess();//与系统的安全有关,如果你从系统调用的话,就需要关注这个方法 return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), Process.myUserHandle()); }
Android Studio中可以通过Ctrl+H 打开类的继承关系图。
bindService调用了bindServiceCommon,核心代码:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { try { service.prepareToLeaveProcess(this); //核心代码,开始了进程间通信 int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
ActivityManagerNative继承了Binder,并且实现了IActivityManager接口,因此与进程通信有关。
public abstract class ActivityManagerNative extends Binder implements IActivityManager{ }
对比
public static abstract class Stub extends android.os.Binder implements com.nan.testbinder.IAidlInterface{ }
发现ActivityManagerNative就是一个Stub对象,仔细观察这个类就会发现下面的Proxy。与系统服务进行通信。
ActivityManagerNative.png
继续分析:
static public IActivityManager getDefault() { return gDefault.get(); }
拿到系统服务IBinder的引用,通过asInterface方法把IBinder引用转换为需要的IActivityManager接口(实质上是AIDL接口):
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { //通过 IBinder b = ServiceManager.getService("activity"); IActivityManager am = asInterface(b); return am; } };
所以说,下面这句代码实际上是通过进程间通信,向ServiceManager获取名字为"activity"的系统服务,并且通过asInterface方法把IBinder引用转换为需要的IActivityManager接口的引用,然后调用这个引用的bindService方法。
ActivityManagerNative.getDefault()//这就是一个ActivityManagerService(AMS) .bindService();
系统服务,进程之间的通信
ServiceManager--管理所有系统服务。ServiceManager相当于总台,我们通过打电话(我们的进程与系统进程进行进程间通信)的方式,就可以拿到对应的服务的AIDL引用。
所有系统服务启动的时候都需要向ServiceManager注册自己的引用:就是把自己的IBinder引用给ServiceManager。在AIDL创建Stub的时候会通过调用父类Binder的构造函数,通过NDK的方式去注册。
而IActivityManager的实现类是ActivityManagerService(AMS),AMS是四大组件进行进程间通信的一个比较重要的类。(因为他实现类AIDL接口:ActivityManagerNative)
public final class ActivityManagerService extends ActivityManagerNative implements ... { }
而AMS里面bindService是这样实现的,注意:现在已经是在系统服务(AMS)的进程里面了。由系统进程继续后续操作:
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); synchronized(this) { //最后是通过mServices(ActiveService)对象的bindServiceLocked,这里开始了进程间通信 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
最后是通过mServices(ActiveServices)对象的bindServiceLocked,这里开始了进程间通信,这个方法比较长,只看核心的代码:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException { //判断进程 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); //ActivityRecord用于记录Activity,然后是为了方便处理 ActivityRecord activity = null; if (token != null) { activity = ActivityRecord.isInStackLocked(token); if (activity == null) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; } } int clientLabel = 0; PendingIntent clientIntent = null; final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID; //判断是不是在本进程 if (isCallerSystem) { service.setDefusable(true); clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT); if (clientIntent != null) { clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0); if (clientLabel != 0) { service = service.cloneFilter(); } } } //一些权限的检测 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "BIND_TREAT_LIKE_ACTIVITY"); } //这个跟Service的生命周期有关 ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal); try { AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent); //把我们的connection对象保存(注册)起来,服务绑定成功以后用于回调 IBinder binder = connection.asBinder(); ArrayList<ConnectionRecord> clist = s.connections.get(binder); if (clist == null) { clist = new ArrayList<ConnectionRecord>(); s.connections.put(binder, clist); } clist.add(c); if (s.app != null && b.intent.received) { try { //连接回调给MainActivity c.conn.connected(s.name, b.intent.binder); } catch (Exception e) { } //如果是第一次绑定的时候,就会调用这里 if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { requestServiceBindingLocked(s, b.intent, callerFg, false); } getServiceMap(s.userId).ensureNotStartingBackground(s); } finally { Binder.restoreCallingIdentity(origId); } return 1; }
然后我们看ActiveServices中的requestServiceBindingLocked的实现,先通过forceProcessStateUpTo去启动另外一个进程的ActivityThread的进程(即通过C++的方式反射调用了ActivityThread的main方法,并且启动了消息循环)。(先启动进程,然后启动进程里面的服务,没毛病!ApplicationThread的启动代表APP的启动,即Application的启动)
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { if ((!i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); //启动ActivityThread r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); //r是ServiceRecord对象,专门用来保存Service的记录,与ActivityRecord类似 //app是ServiceRecord的一个成员变量ProcessRecord,专门用来保存进程的记录 //thread是ProcessRecord的一个成员变量IApplicationThread,是整个Android组件启动的核心类 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); if (!rebind) { i.requested = true; } i.hasBound = true; i.doRebind = false; } catch (TransactionTooLargeException e) { } catch (RemoteException e) { } } return true; }
IApplicationThread的实现类ApplicationThread是整个Android组件启动的核心类,也是跟进程间通信有关的类,根据下面的类的关系分析:
public interface IApplicationThread extends IInterface { } public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { } private class ApplicationThread extends ApplicationThreadNative { }
最终发现IApplicationThread的实现类是ActivityThread的一个内部类:ApplicationThread!!!
ApplicationThread.png
因此调用ApplicationThread的bindService的时候就会启动另外一个ActivityThread,并且发送消息给系统Handler(H),启动Service:
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); //保存关于Service的一些参数 BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; //发送消息给系统Handler,启动Service sendMessage(H.BIND_SERVICE, s); }
系统Handler接受消息以后:
case BIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
handleBindService:
private void handleBindService(BindServiceData data) { //mServices是在handleCreateService的时候通过反射创建的 Service s = mServices.get(data.token); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { //绑定一个Service,回调onBind方法 IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); //然后又通过进程间通信,把这个服务的IBinder对象放到Binder驱动里面 ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }
来到这里,就会回调ServiceConnection的onServiceConnected方法,拿到IBinder引用以后,就需要去创建用于通信的AIDL接口的引用。
class MyRemoteServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { mRemoteInterface = IAidlInterface.Stub.asInterface(service); if (mRemoteInterface != null) { String result; try { result = mRemoteInterface.pay(123); Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { //连接因为异常而终止才会调用 } }
首先去初始化Stub,在Stub构造的时候,并且把描述保存起来。
public Stub() { this.attachInterface(this, DESCRIPTOR); } public void attachInterface(IInterface owner, String descriptor) { mOwner = owner; mDescriptor = descriptor; }
我们bindService的时候,先会找到系统服务,由系统服务创建相应的进程和服务,然后回调的时候传回IBinder。
Service的创建是通过反射的方式的,当AIDL引用被创建的时候,首先会调用Stub的构造函数创建Stub,因为Stub继承了Binder,根据Java的语法,这时候先会调用Binder的构造init方法,注册IBinder引用到专门用于进程通信的内存里面:
public Binder() { init(); if (FIND_POTENTIAL_LEAKS) { final Class<? extends Binder> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Binder class should be static or leaks might occur: " + klass.getCanonicalName()); } } }
其中这里的init方法是一个native方法:
private native final void init();
在这个init方法里面就会进行IBinder的注册。
然后通过我们手动调用Stub的asInterface把拿到的IBinder引用转换为AIDL接口的实现类:
//通过Stub的asInterface把拿到的IBinder引用转换为AIDL接口的实现类 mRemoteInterface = IAidlInterface.Stub.asInterface(service);
先在自己的进程找IBinder引用,如果有,就直接返回自身,没有的话,就创建代理Proxy:
public static com.nan.testbinder.IAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } //先通过IBinder的queryLocalInterface方法去找本地的引用 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.nan.testbinder.IAidlInterface))) { return ((com.nan.testbinder.IAidlInterface) iin); } return new com.nan.testbinder.IAidlInterface.Stub.Proxy(obj); }
我们在MainActivity拿到引用以后,就可以调用我们自己实现的pay方法进行进程间通信了。
数据是怎么写倒IBinder里面的呢?
我们知道数据是通过Proxy写到IBinder里面的,例如我们刚刚看过的代码:
@Override public java.lang.String pay(int pwd) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(pwd); //把数据写到IBinder驱动里面 mRemote.transact(Stub.TRANSACTION_pay, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; }
这是我们自定义AIDL类里面的自定义pay方法,这里我们深入分析mRemote.transact(...)这个方法。
首先从上面的分析知道,mRemote是在Proxy构造的时候传进来的(在不同进程里的时候)。
这里再强调一次,如果是同一个进程的话,Binder就是自身,因为Stub这个类本身就是继承了Binder。
public Stub() { this.attachInterface(this, DESCRIPTOR); } public static com.nan.testbinder.IAidlInterface asInterface(android.os.IBinder obj) { //... return new com.nan.testbinder.IAidlInterface.Stub.Proxy(obj); }
所以说我们要看transact的实现,实际上就要看他的实现类Binder内部类的BinderProxy的transact:
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); }
里面调用了native方法transactNative,也就是说IBinder的底层驱动是通过C++来实现的,通过底层代码把数据写到IBinder驱动里面。
返回的时候通过Binder的onTransact函数,通过dump方法把数据拿回来:
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (code == INTERFACE_TRANSACTION) { reply.writeString(getInterfaceDescriptor()); return true; } else if (code == DUMP_TRANSACTION) { ParcelFileDescriptor fd = data.readFileDescriptor(); String[] args = data.readStringArray(); if (fd != null) { try { //通过dump方法把数据拿回来 dump(fd.getFileDescriptor(), args); } finally { IoUtils.closeQuietly(fd); } } // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } return true; } else if (code == SHELL_COMMAND_TRANSACTION) { ParcelFileDescriptor in = data.readFileDescriptor(); ParcelFileDescriptor out = data.readFileDescriptor(); ParcelFileDescriptor err = data.readFileDescriptor(); String[] args = data.readStringArray(); ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data); try { if (out != null) { shellCommand(in != null ? in.getFileDescriptor() : null, out.getFileDescriptor(), err != null ? err.getFileDescriptor() : out.getFileDescriptor(), args, resultReceiver); } } finally { IoUtils.closeQuietly(in); IoUtils.closeQuietly(out); IoUtils.closeQuietly(err); // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } } return true; } return false; }
IBinder引用什么时候放到共享内存时候?
AIDL中Stub构造的时候,就会调用父类Binder的构造,调用NDK的init方法,进行注册。
源码分析相关
源码分析的两种方法:架构上面分析(类的关系)、流程上面的分析
源码分析的时候需要不断去找接口的实现类
源码分析的推荐学习顺序:
Binder、Handler消息机制、VIew、事件分发、系统服务(ServiceManager代表着系统服务、AMS代表着应用程序启动流程)、四大组件的架构
、WindowManager、学习系统应用源码(Launcher等)