前言:
1.Binder是什么?
2.Binder的原理是什么?
3.Binder如何实现?
1.Binder是什么?
Binder是Anroid平台跨进程通信的一种重要的实现方式(
另外三种:
- Messenger
- broadcast
- socket
),是Google基于OpenBinder实现的进程间通信的驱动程序框架, 由于Android是每个应用或者服务(AMS,IMS)都运行在一个独立的进程,每个进程之间的数据是独立的,想要通信就需要一种跨进程的技术.
2.Binder的原理是什么?
2.2 Binder对应的驱动设备文件为:/dev/binder.
- 2.2.1通过Client/Service模式 : C/S之间维护一个线程池进程通信,通过dev/binder该设备文件调用内核中的bingder驱动程序
2.2.1.1.Client组件对应的是BnInterface,描述本地binder对象,service组件对应的是BpInterface。描述本地binder代理对象.
2.2.1.2系统定义了IBinder接口,其中Binder和BinderProxy分别实现了IBinder接口,前者代表服务端Bn,而后者代表客户端Bp.
- 2.2.2 Binder进行进程间通信: 首先要调用open函数打开设备文件dev/binder获得文件描述符,再调用mmp将该描述符映射到内核地址空间,然后分配内核缓冲区,该缓冲区是用来传递数据的,才能通过这个和binder驱动程序交互。
2.3 .
Android应用层系统想启动另外一个进程里面的service或者activity等组件,最终都是通过一个远程的mRemote Binder对象去跨进程通信想AMS发送一个请求启动,下面通过分析AMS来分析Binder的原理。
其中AMS的继承方式:
ActivityManagerService ->ActivityManagerService->Binder
public ActivityManagerNative() {
attachInterface(this, descriptor);
}
/**
* Convenience method for associating a specific interface with the Binder.
* After calling, queryLocalInterface() will be implemented for you
* to return the given owner IInterface when the corresponding
* descriptor is requested.
*/
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
//from IActivityManager
String descriptor = "android.app.IActivityManager";
当启动一个Activity的流程为:
Activity.java:
public void startActivityForResult(Intent intent, int requestCode,@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
}
Instrumentation.java:
public void execStartActivitiesAsUser() {
int result = ActivityManagerNative.getDefault()
.startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
token, options, userId);
}
ActivityManagerNative.java:
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
//
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
//拿到对应的ServiceManaerService
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
。
。
。
}
}
其中gDefault最终拿到的是一个面向底层的客户端BinderProxy对象(ActivityManagerProxy)
从上面代码可以看出最终是调用AMN的startActivity方法。
但是该Binder客户端对象就是是跟底层那个目标通信呢?
ServiceManager.getService("activity");
/**
* Returns a reference to a service with the given name.
*
* @param name the name of the service to get
* @return a reference to the service, or null
if the service doesn't exist
*/
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
从上面可以知道getContextObject返回了一个指向地城ServiceManager的Native BinderProxy对象,并且在JAVA层封装 起来给JAVA调用,如下:
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
*/
//其中obj就是上面传进来指向Native BinderProxy对象的地址。
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);
}
上面ServiceManagerProxy对象就是封装了在BinderInternal拿到的Native对象的。
下面通过分析getService方法,分析客户端发送请求过程:
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
//其中mRemote就是BinderInternal. getContextObjectd的navtive对象。
也就是说,将数据封装成Parcel对象,然后通过native binder发起请求。
上面是客户端的请求。
ActivityManagerService.java:
@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;
}
上面是AMS实现的接受到客户端请求的实现方法。
我们知道AMS是继承Binder,当底层收到请求是,最终会调用Binder.java对应的方法:
// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
try {
res = onTransact(code, data, reply, flags);
}
其中onTransact是一个抽象方法,其中AMS上面实现了该方法,完成请求。
流程如图:
后记:JAVA中搭建了一整套框架,如IBinder接口,Binder类,和BiindeProxy(如ServiceManagerProxy)其中本质就是向binder驱动发送请求或者接受回复。
即使不使用JAVA的框架,也是可以实现,比如ServiceManager作为Binder的一个核心程序,就是直接读取/dev/binder设备。