Binder是一种架构,该架构提供了服务端接口,Binder驱动、客户端接口三个模块,如下图:
为了我们更好的分析这三个模块,我先给出我写的demo音乐播放器服务写aidl,抛出start和stop方法 自动生成的java文件
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: E:\\android-studio-workspace\\MyBinder\\app\\src\\main\\aidl\\com\\example\\user\\mybinder\\IMyAidlInterface.aidl
*/
package com.example.user.mybinder;
// Declare any non-default types here with import statements
public interface IMyAidlInterface extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.user.mybinder.IMyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.example.user.mybinder.IMyAidlInterface";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.user.mybinder.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.user.mybinder.IMyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.user.mybinder.IMyAidlInterface))) {
return ((com.example.user.mybinder.IMyAidlInterface) iin);
}
return new com.example.user.mybinder.IMyAidlInterface.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_basicTypes: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0 != data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_start: {
data.enforceInterface(DESCRIPTOR);
this.start();
reply.writeNoException();
return true;
}
case TRANSACTION_stop: {
data.enforceInterface(DESCRIPTOR);
this.stop();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.user.mybinder.IMyAidlInterface {
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;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void start() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_start, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void stop() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_start = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public void start() throws android.os.RemoteException;
public void stop() throws android.os.RemoteException;
}
服务端:它其实就是一个binder对象(有能力的程序员可以自己写利用binder对象来完成服务端的功能,具体如何做不清楚书上写的),当我们创建aidl文件(aidl创建后rebind后就会自动生成相应的java文件 ,其实可以直接自己写java文件,自动生成的java文件只是一种普遍的习惯),在Service里自己写binder对象该对象继承aidl生成的java文件中 Stub(它继承了binder实现),在onBinder中返回自己的binder对象的时候服务端内部就会启动一个隐藏程序,该隐藏程序用来接收bidner驱动的消息,接受消息后会执行binder对象中的onTransact()函数,因此要实现binder服务就必须重载onTransact()方法。
1 、根据函数第一个参数code 执行不动的方法,code 是Stub中定义的全局不变变量,会根据code不同执行相应的操作。(也有一些是在Ibinder中已经定义好的,主要是自己添加的方法的code)。
2、onTrabsact()作用是将它的参数转化为服务端方法所用到的参数,onTransact()的参数来源则是代理proxy中获得的binder驱动对象IBinder mRemote调用的transact()方法中的参数。因此,每个方法都是利用binder驱动的transact()方法发送消息给服务端,服务端通过继承自aidl生成java文件中stub的binder对象的onTransact方法将参数转化为服务的对应方法参数。如客户端调用start()方法调用过程:
客户端 binder获取代理proxy->start()------>binder驱动调用transact()--------->服务端自定义binder继承自aidl 中Stub,利用Stub的静态方法onTrancsact()将transact的参数转化为服务的参数 ------> 执行服务中的start()方法 -- > 数据返回binder驱动 -- >客户端
binder驱动端:当服务端创建时候,aidl生成的java文件中proxy类中会创建IBinder mRemote 对象,它重载了transact(0方法,代理就是通过它调用transact方法来向服务端发送和接受消息的,trancsact主要3个功能,见流程图。
客户端:客户端是利用binderService 的回调函数获得代理对象,代理对象引用了binder驱动 mRemote对象,在代理的start()、stop()方法中利用mRemote的transact()向服务端发送消息,从而执行服务中方法,然后通过mRemote再返回结果。
因此我们了解了一下知识点:
1 、binder框架中有2个binder 一个是服务端的binder 另一个是驱动binder,服务端会有多个服务则存在多个binder对象,因此会多一个线程,而binder驱动端则不会多产生一个线程。
2、binder 中利用aidl工具生成的java文件中transact和ontransact()参数来确定参数的顺序,保证了传递和接受数据的顺序。
3、aidl生成的java文件包含三部分:
(1)、java Interface,IService,其内部包含aidl声明的一些方法,并且该接口继承与 android.os.IInterface 接口,因此得提供asBinder()方法。
(2)、一个静态的公有虚类Stub 继承android.os.Binder 且implements Iservice , 因为Iservice接口的方法由它的成员类proxy来实现,因此定义为虚类。
(3)、proxy类,即所谓的代理,stub的asInterface()方法就可以返回代理对象,它是Stub的成员类
之所以把三个类写在一个文件内主要是方便维护和代码的简洁。
4 transact()的最后一个参数是IPC调用的2中模式,0 则是双向的,即服务端执行执行玩指定服务后会返回一定数据,1则表示不返回任何数据。调用该方法后客户端线程进入Binder驱动。
5,Binder 内部有 asInterface(android.os.IBinder obj),服务端内部当然也可以使用该服务,而Binder内部有queryLocalInterface(String description)方法,通过字符串判断该binder对象是否为本地的Binder引用。当创建的Binder对象时,服务端进程内部创建Binder对象,binder驱动中也会创建一个Binder对象。如果从远程获取服务端的Binder,则只会返回Binder驱动中的Binder对象,而如果从服务端进程内部获取Binder对象,则会获得服务端本身的Binder对象。因而mRemote是对binder驱动的一个引用,onserviceConnected()参数IBinder service是Binder驱动的binder引用,然后返回的是proxy,代理持有Binder驱动的binder引用mRemote,从而可以向服务端发送消息。
系统服务binder对象(ServiceManager 介绍)
写程序时,经常用到getSystemService(String serviceName)方法来获取一个系统服务,那么这些服务的binder引用是如何传递给客户端的呢?须知系统服务并不是通过startService()启动的。
getSystemService()方法的实现是在ContextImpl类中,该方法所返回的Service很多,而这些service一般都是由ServiceManager管理。
serviceManager管理服务
serviceManager是一个独立的进程,其本身也是个service,Framwork提供了个系统方法 BinderInternal.getContextObject(),用来获取serciceManager对应的Binder应用。该方法返回ServiceManager后,可通过ServiceManager提供的方法,获取其他系统的sercice的Binder引用。这样设计的好处就是系统只需要暴漏一个全局Binder,就可以通过这个全局binder获取其他的系统服务的binder引用,隐藏其他系统服务,从而有助于系统的扩展,以及调用系统服务的安全检查。其他服务启动时候将自己的binder对象传递给ServiceManager,即所谓的注册(addSercice)。
下面的代码可以看出ContextImpl.getSystemService()中各种Service的具体获取方式,如INPUT_METHOD_SERVCICE,的代码如下:
}else if(INPUT_METHOD_SERVICE.equals(name)) return InputMethodManager.getInstance(this);
InputMethodManager.getInstance()的方法如下
synchronized (mInstanceSync){ if(mInstance != null){ return mInstance; } IBinder b = SystemManager.getService(Context.INPUT_METHOD_SERVICE); IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); mInstace = new InputMethodManager(srvice , mainLooper); } rerurn mInstance
从上面的函数可以看出ServiceManager 获取InputMethod service 对应的Binder 对象b,然后将该binder对象作为IIputmethodManager.Stub.asInterface()的参数,返回一个IInputMethodManger的统一接口。
而SystemManager.getService()方法的代码如下:
public static IBinder gerService(String name){ try{ IBinder service =sCashe.get(name); if(service != null){ return service; }else { return getIServiceManager().getService(name); } }catch(remoteException e){ Log.e(TAG , "error in getService" , e); } return null }
即首先从sCashe缓存中查看是否有对应的Binder对象,有则返回,没有则调用getIServiceManager().getservice(name),第一个函数getIserviceMnager()即用于返回系统中唯一的ServiceManager对应的Binder,其代码如下:
prviate static IserviceManager gerIServiceManger(){ if(sServiceMnager != null){ return sServiceManager; } //find the Service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
以上代码中,BinderInternal.getContextobject静态方法即用于迂回ServiceManager 对用的全局Binder对象,该方法不需要任何参数,因为它的作用是固定的。从这个角度来看,这个方法的命名似乎应该更明确一些,如:getServiceManager()。
关于使用addService()向ServiceManager中添加一个服务一般是在SystemService进程启动时完成。