Android IPC通讯之Binder机制分析
优势:
与Linux中的Pipe管道、信号Signal、消息队列Message、共享内存Share Memory、Socket插口等相比较,Binder在进程间传输数据,只需要执行一次拷贝操作。因此它不仅提高了效率,而且节省了内存空间。
角色:
- Server: 提供服务的进程称为server进程。
- Client: 使用服务的进程称为client进程。
- Binder驱动: 提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信。Client和Server之间的进程间通信通过Binder驱动程序间接实现。
- Service Manager: 一个守护进程,用来管理Server,并向Client提供查询Server接口的能力
交互过程:
1.Server进程,先通过ServiceManager注册服务,实际上是写入Binder驱动和保存到serviceInfo(已经注册的服务列表)。
2.Client进程在访问Server服务之前,先通过ServiceManager查询获取到它的一个BinderProxyd对象,然后通过这个Binder代理接口向它发送进程间通讯请求,调用transact(),写入相关信息。
3.在server进程中,每个服务都对应一个Binder对象,它通过一个stub来等待Client进程发来进程间通讯请求,触发onTransact(),获取到详细数据。
Binder机制分析如下:
1. ServiceManager类的代理,实现注册和查询服务:
接下来查看,如何创建一个SericeManager的代理类,客户端通过该代理类进行通讯:
查看ServiceManager源码:
public final class ServiceManager {
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// 获取到代理对象
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
}
查看,BinderInternal类
public class BinderInternal {
//从native获取到对应的指针
public static final native IBinder getContextObject();
}
查看,ServiceManagerNative源码:
public abstract class ServiceManagerNative extends Binder implements IServiceManager{
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
*/
static public IServiceManager asInterface(IBinder obj){
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
public IBinder asBinder(){
return this;
}
}
class ServiceManagerProxy implements IServiceManager {
private IBinder mRemote;
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
//......省略部分源码
}
ServiceManagerNative类似服务端的stub类,用于接受到Client端发来的数据,进行操作。
ServiceManagerProxy是客户端的proxy类,通过BinderProxy对象(即mRemote对象)进行远程通讯。
Server进程通过ServiceManager进行addService()
注册服务或者Client进程通过ServiceManager进行getService(String name)
查询服务等操作,实际上都是通过ServiceManagerProxy中的mRemote跨进程操作的。
这里不介绍Binder驱动,涉及 C++层比较繁琐,相关方面,自行百度理解。
编写常见的AIDL案例,分析Binder机制
编写一个aidl文件:
package com.xingen.remoteservice;
import com.xingen.remoteservice.bean.ProcessBean;
// Declare any non-default types here with import statements
//使用 Android Studio,增量编译几乎会立即生成 Binder 类
//在.aidl文件中定义一些方法
interface CommonAidlInterface {
/**
* 获取一个随机数的字符串
*/
String getRandomNumberStr();
/**
* 获取远程服务返回的对象,注意点:需要import导入该对象
*/
ProcessBean getRemoteServiceObject();
}
生成对应的java:
package com.xingen.remoteservice;
// Declare any non-default types here with import statements
//使用 Android Studio,增量编译几乎会立即生成 Binder 类
//在.aidl文件中定义一些方法
public interface CommonAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements CommonAidlInterface
{
private static final String DESCRIPTOR = "com.xingen.remoteservice.CommonAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.xingen.remoteservice.CommonAidlInterface interface,
* generating a proxy if needed.
*/
public static CommonAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof CommonAidlInterface))) {
return ((CommonAidlInterface)iin);
}
return new 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_getRandomNumberStr:
{
data.enforceInterface(DESCRIPTOR);
String _result = this.getRandomNumberStr();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getRemoteServiceObject:
{
data.enforceInterface(DESCRIPTOR);
com.xingen.remoteservice.bean.ProcessBean _result = this.getRemoteServiceObject();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements CommonAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public String getRandomNumberStr() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRandomNumberStr, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 获取远程服务返回的对象,注意点:需要import导入该对象
*/
@Override public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.xingen.remoteservice.bean.ProcessBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRemoteServiceObject, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.xingen.remoteservice.bean.ProcessBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getRandomNumberStr = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getRemoteServiceObject = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public String getRandomNumberStr() throws android.os.RemoteException;
/**
* 获取远程服务返回的对象,注意点:需要import导入该对象
*/
public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException;
}
CommonAidlInterface接口:
CommonAidlInterface接口是IInteface的子接口,用于Stub类和Proxy的通用父类接口。
Stub类:
Stub类是Binder的子类,用于Server进程中,onTransact()
方法中接收传递过来的信息。
Proxy类:
Proxy中有一个IBinder类型的mRemote对象,它实际上是一个BinderProxy对象(通过ServiceManager)。BinderProxy是一个Java服务代理对象,实现了IBinder接口。
2. Client端的Proxy代理(实际包含BinderProxy对象)信息传递:
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//Stub.asInterface(service)转成对应的服务接口
remoteServiceInterface = CommonAidlInterface.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
remoteServiceInterface = null;
}
};
绑定Service会返回一个IBinder对象,实际上是BinderProxy类,该对象是查询ServiceManager获取到的。
public static CommonAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//本地进程会走这一步
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof CommonAidlInterface))) {
return ((CommonAidlInterface)iin);
}
//远程进程会返回Proxy
return new Proxy(obj);
}
private static class Proxy implements CommonAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
}
Stub.asInterface(iBinder)
是将BinderProxy对象封装到一个代理Proxy中,用于更好操作。
跨进程间的传递信息的调用:
remoteServiceInterface.getRemoteServiceObject();
实际上调用的是Proxy中的getRemoteServiceObject():
@Override public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.xingen.remoteservice.bean.ProcessBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRemoteServiceObject, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.xingen.remoteservice.bean.ProcessBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
会调用BinderProxy的transact()方法,传入数据和结果的parcel对象,会写入Binder驱动中。
3. Server端的Stub(Binder子类)接受到远程的信息:
Binder驱动监听到Client端远程信息,会触发Binder中的onTransact()方法。
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
case TRANSACTION_getRandomNumberStr:
{
data.enforceInterface(DESCRIPTOR);
//调用该方法
String _result = this.getRandomNumberStr();
reply.writeNoException();
//写入返回结果
reply.writeString(_result);
return true;
}
case TRANSACTION_getRemoteServiceObject:
{
data.enforceInterface(DESCRIPTOR);
com.xingen.remoteservice.bean.ProcessBean _result = this.getRemoteServiceObject();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
最后,响应到service中的Stub匿名内部类中,调用各种对应的方法。
public class CommonRemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG,TAG+" 被绑定");
return mBinder;
}
/**
* 获取进程信息的对应实体
* @return
*/
private ProcessBean getProcessBean(){
return ProcessUtils.getProcess(this.getApplicationContext(),ProcessUtils.getCurrentProcessId());
}
/**
* 获取一个随机字符串
* @return
*/
private String getRandomUUIDStr(){
return UUID.randomUUID().toString();
}
/**
* 创建一个CommonAidlInterface.aidl对应的CommonAidlInterface.java中的Stub接口
*
* 用于与远程服务通讯,这里是本类(CommonRemoteService)通讯
*/
private final CommonAidlInterface.Stub mBinder=new CommonAidlInterface.Stub() {
@Override
public String getRandomNumberStr() throws RemoteException {
return CommonRemoteService.this.getRandomUUIDStr();
}
@Override
public ProcessBean getRemoteServiceObject() throws RemoteException {
return CommonRemoteService.this.getProcessBean();
}
};
}