在学习Binder机制前,先简单说说Linux现有的所有进程间IPC机制:
Binder | 共享内存 | Socket | |
---|---|---|---|
性能 | 拷贝一次 | 无需拷贝 | 拷贝两次 |
特点 | 基于C/S架构,易用性高 | 控制复杂,易用性差 | 基于C/S架构,通用接口,传输效率低、开销大 |
安全 | 每个App分配UID,同时支持实名和匿名 | 依赖上层协议,访问接入点是开放的 | 依赖上层协议,访问接入点是开放的 |
Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。如下图所示。
无论是注册服务和获取服务的过程都需要ServiceManager,需要注意的是此处的Service Manager是指Native层的ServiceManager(C++),并非指framework层的ServiceManager(Java)。
ServiceManager是整个Binder通信机制的大管家,是Android进程间通信机制Binder的守护进程。当Service Manager启动之后,Client端和Server端通信时都需要先获取Service Manager接口,才能开始通信服务。
图中Client/Server/ServiceManage之间的相互通信都是基于Binder机制。既然基于Binder机制通信,那么同样也是C/S架构,则图中的3大步骤都有相应的Client端与Server端。
图中的Client,Server,Service Manager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互的,从而实现IPC通信方式。其中Binder驱动位于内核空间,Client,Server,Service Manager位于用户空间。
Binder驱动和Service Manager可以看做是Android平台的基础架构,而Client和Server是Android的应用层,开发人员只需自定义实现Client、Server端,借助Android的基本平台架构便可以直接进行IPC通信。
AIDL = Android Interface Definition Language,主要目的是简化调用Binder的流程。
在Android中使用AIDL需要首先编写xxx.aidl文件,然后Android Studio会根据该.aidl文件自动生成xxx.java文件
interface IDemoAidlInterface {
void functionA(int arg);
void functionB(String arg);
}
* This file is auto-generated. DO NOT MODIFY.
*/
package com.example.serverdemo;
public interface IDemoAidlInterface extends android.os.IInterface {
public void functionA(int arg) throws android.os.RemoteException;
public void functionB(java.lang.String arg) throws android.os.RemoteException;
/**
* Default implementation for IDemoAidlInterface.
*/
public static class Default implements com.example.serverdemo.IDemoAidlInterface {
@Override
public void functionA(int arg) throws android.os.RemoteException {
}
@Override
public void functionB(java.lang.String arg) throws android.os.RemoteException {
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.serverdemo.IDemoAidlInterface {
static final int TRANSACTION_functionA = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_functionB = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
private static final java.lang.String DESCRIPTOR = "com.example.serverdemo.IDemoAidlInterface";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.serverdemo.IDemoAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.serverdemo.IDemoAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.serverdemo.IDemoAidlInterface))) {
return ((com.example.serverdemo.IDemoAidlInterface) iin);
}
return new com.example.serverdemo.IDemoAidlInterface.Stub.Proxy(obj);
}
public static boolean setDefaultImpl(com.example.serverdemo.IDemoAidlInterface impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.example.serverdemo.IDemoAidlInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
@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 {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_functionA: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
this.functionA(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_functionB: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.functionB(_arg0);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.example.serverdemo.IDemoAidlInterface {
public static com.example.serverdemo.IDemoAidlInterface sDefaultImpl;
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 void functionA(int arg) 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(arg);
boolean _status = mRemote.transact(Stub.TRANSACTION_functionA, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().functionA(arg);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void functionB(java.lang.String arg) 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.writeString(arg);
boolean _status = mRemote.transact(Stub.TRANSACTION_functionB, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().functionB(arg);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
}
}
通过Binder进行进程通信的关键,在于自动生成的xxx.java文件,而非xxx.aidl文件,后者只是为了简化开发者编写生成前者的操作。
在文件编写生成完成后,在Android中使用AIDL进行远程调用的关键动作为以下三个:
com.example.serverdemo.IDemoAidlInterface.Stub#asInterface</pre>
如果客户端与服务端处于同进程:
return ((com.example.serverdemo.IDemoAidlInterface) iin);</pre>
如果客户端与服务端处于异进程:
return new com.example.serverdemo.IDemoAidlInterface.Stub.Proxy(obj);</pre>
http://gityuan.com/2015/10/31…
由于水平有限,有错误的地方在所难免,未免误导他人,欢迎大佬指正!码字不易,感谢大家的点赞关注!有一起学习的小伙伴可以关注下我的公众号——【❤️程序猿养成中心❤️
】每周会定期做关于Android的技术分享。