初探Android中的binder机制 下载本文

内容发布更新时间 : 2024/5/12 15:45:24星期一 下面是文章的全部内容请认真阅读。

IBinder sm = (IBinder) Reflect.on(\).call(\,\).get();

// 拿到方法编号

int funCode = IBinder.FIRST_CALL_TRANSACTION+21;

// 准备方法参数数据

Parcel data = Parcel.obtain();

// 首先要写入的数据必须是binder服务端的descriptor

data.writeInterfaceToken(\);

// 接下来是方法的参数

data.writeStrongBinder((IBinder)Reflect.on(this).field(\).get());

// 用于接受返回数据

Parcel reply = Parcel.obtain();

// 发起RPC调用,同步调用,直到调用结束,期间一直阻塞

try {

sm.transact(funCode,data,reply,0);

} catch (RemoteException e) {

e.printStackTrace();

}

// 读取返回数据

reply.readException();

// 解析返回数据

ComponentName res = ComponentName.readFromParcel(reply);

// 回收parcle

data.recycle();

reply.recycle();

Log.i(\,\Activity name: \+res.getClassName());

}

}

通过binder代理对象发起RPC操作

对于前面例子中获取调用者的情况,实际开发中都是通过Activiy.getCallingActivity()来获取的:

public ComponentName getCallingActivity() {

try {

return ActivityManagerNative.getDefault().getCallingActivity(mToken);

} catch (RemoteException e) {

returnnull;

}

}

其中ActivityManagerNative.getDefault()返回的是

ActivityManagerProxy对象。

ActivityManagerProxy是AMS的binder代理类。

binder代理对象通过内聚的binder引用对象间接发起RPC操作。对于系统服务来说,它的binder代理对象都是事先定义好的。binder代理对象还要实现服务接口,实际上就是对binder引用对象发起RPC操作的二次封装。

classActivityManagerProxyimplementsIActivityManager{

...............public ComponentName getCallingActivity(IBinder token)

throws RemoteException {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

data.writeInterfaceToken(IActivityManager.descriptor);

data.writeStrongBinder(token);

mRemote.transact(GET_CALLING_ACTIVITY_TRANSACTION, data, reply, 0);

reply.readException();

ComponentName res = ComponentName.readFromParcel(reply);

data.recycle();

reply.recycle();

return res;

}

...............

可以看到代理类中已经帮我们封装好了getCallingActivity()的操作。因为直接通过binder引用发起RPC操作的话,需要开发者知道方法的编号,而方法的编号又是随着Android版本的变化而可能发生改变的。所以一般来说都会为binder服务封装一个binder代理类。这样做还有一个好处是通过一个binder引用对象,可以创建多个binder代理对象。

binder服务分类

分为两大类:

向ServiceManager注册的binder服务

Android系统中自带的绝大多数服务,例如AMS,PMS等都会向ServiceManager注册,注册时会传入一个service名字,例如AMS注册是传入的是“activity”。

客户端可以通过名字向ServiceManager查询对象的binder服务,ServiceManager会返回一个IBinder对象。

至于说返回的IBinder对象究竟是实体bidner呢还是引用binder,按照下面的规则决定:

当binder服务端同进程请求该服务时,返回的是binder实体对象。

当请求者与binder服务端在一个进程时,返回的是引用对象。

没有向ServiceManager注册的的bidner服务,又被称为匿名binder服务