Binder监测连接状态,以及断开后的重连
一、监测连接状态
1. binder对象死亡通知机制
1.1. 注册死亡通知
client和server通过binder通信,且binder提供一个方法,即传入死亡代理binder.linkToDeath(IBinder.DeathRecipient) ,当client于server断开的时候,client收到DeathRecipient的binderDied()方法回调 ,从而知道连接断开,以下为binder源码:
BBinder::linkToDeath ()
1
2
3
4
5
6status_t BBinder::linkToDeath(
const sp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
uint32_t /*flags*/)
{
return INVALID_OPERATION; // 返回无效操作
}server端的linkToDeath只返回无效操作
BpBinder::linkToDeath ()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
Obituary ob;
ob.recipient = recipient;
ob.cookie = cookie; //标识死亡接收者
ob.flags = flags; //
LOG_ALWAYS_FATAL_IF(recipient == NULL,
"linkToDeath(): recipient must be non-NULL");
{
AutoMutex _l(mLock);
if (!mObitsSent) { //mObitsSent用来表示Binder驱动程序是否已经向它发送过死亡通知,如果是,直接返回DEAD_OBJECT
if (!mObituaries) { //第一次注册
mObituaries = new Vector<Obituary>; //死亡通知对象列表
if (!mObituaries) {
return NO_MEMORY;
}
ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
getWeakRefs()->incWeak(this); //增加了弱引用计数
IPCThreadState* self = IPCThreadState::self();
self->requestDeathNotification(mHandle, this); // 记录对象
self->flushCommands(); //促使当前线程马上通过IO控制命令BINDER_WRITE_READ进入到Binder驱动程序中,以便可以执行注册死亡接受通知的操作
}
ssize_t res = mObituaries->add(ob); //非第一个注册
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
}
}
return DEAD_OBJECT;
}Binder代理对象内部的成员变量mObitsSent用来表示Binder驱动程序是否已经向它发送过死亡通知
- 若是,表示Binder本地对象已经死亡,返回DEAD_OBJECT
- 若否,
- 若第一次注册,记录Binder代理对象的地址,并立马调用Binder Driver执行注册死亡通知
- 非第一次注册,直接加入死亡通知对象列表mObituaries
binderDied()
1
2
3
4
5
6
7
8
9
10
11
12class IBinder : public virtual RefBase
{
public:
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;//重写父类DeathRecipient的成员函数binderDied
};
......
};自定义的死亡通知接受者必须要重写父类DeathRecipient的成员函数binderDied。当Binder驱动程序通知一个Binder代理对象它所引用的Binder本地对象已经死亡时,就会调用它所指定的死亡通知接受者的成员函数binderDied
简述流程
- Binder代理对象将一个死亡接收通知注册到Binder驱动程序中
- 当Binder驱动程序监控到它所引用的Binder本地对象死亡时,Binder驱动程序就会向Binder代理对象发送一个死亡通知
由BBinder::linkToDeath ()和BpBinder::linkToDeath ()代码可见
- server进程死亡时,运行在其里的Binder对象就死亡,通过比较Binder代理存在,本地对象为空可知server端死亡,会通知到client代理对象,pmcs模块中即为BnPmcsProxy对象
- client进程死亡时,没有通知任何对象。这时候Binder驱动程序就应该向那些引用了它的Binder代理对象发送死亡接受通知,以便它们可以知道自己引用了一个无效的Binder本地对象
一句话总结
client可以知道连接断开,server不知道什么时候断开,只有通过连接它的client来获得连接状态
1.2. 发送死亡接收通知
暂略
2. client检测连接状态
由 binder对象死亡通知机制 可知,client端(PmcsProxy )可通过binder.linkToDeath(IBinder.DeathRecipient)获得连接状态,即server挂掉,通知Binder代理对象
1 | bool PmcsProxy::attachServer() |
3. server检测连接状态
由 binder对象死亡通知机制 可知,server自身无法检测连接状态,只能通过与server端连接的client端来获取连接状态,即通过client端(PmcsProxy )的binder.linkToDeath(IBinder.DeathRecipient),那么server端只要获取到client对象就可以检测连接状态
- server如何获取和区分client?两种方法
- server端给每个连接上的client端一个标识token
- client类增加一个token属性
- 当创建一个client时,server给其分配一个token标识
- 利用Binder的static方法,Binder.getCallingPid()来拿到client端的pid
- server端给每个连接上的client端一个标识token
二、连接断开后的重连
由上文 监测连接状态 可知,在重写binderDied函数时,再次连接就好了
- client检测到server断开,client重启server
- server检测到client断开,server重创建一个client