简介:
Android系统当中的Binder消息传递无处不在,从运行一个新应用到发送一个常见的TIME PICK广播,再到注册一个ContentObserver去监听短信数据的变化,这些功能都需要使用到Binder通信。正如”凡人必有一死”,system_server进程虽然只要手机保持开机状态就会存在,但是普通应用无论优先级多么高,当系统内存匮乏、用户手动杀死应用进程又或者是应用出现不能解决的BUG直接Force Close了。这时,作为进程通信服务端的应用既然死亡了,那么对应的客户端相应的服务端之前保存下来的数据就没有必要保存了。否则的话,应用生老病死之间,如果手机一直不关机,system_server一直在存活期间也不清除死亡进程的遗留信息,那么这样的手机系统使用起来会造成内存泄露,系统资源会慢慢被耗尽直至用户能察觉到的系统卡顿出现。
所以Binder进程通信必然需要一种死亡回调的机制,当通信服务端死亡后可以通知客户端们来进行相关的清理工作。Android已经实现好了一套DeathRecipient机制,客户端只要实现死亡回调binderDied方法并且调用linkToDeath方法,当服务端死亡时binderDied将会被调用。
framework示例
linkToDeath的源码大部分都是c++代码,晦涩难懂。所以在讲解源码之前,我会给出尽量多的framework实例
ContentService
上一周我写了一篇关于ContentService如何实现数据变化监听的分析,有兴趣的可以看看,这里我只着重讲ContentService与应用端的死亡回调
ContentService.java
private class ObserverEntry implements IBinder.DeathRecipient {
…
public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
int _uid, int _pid, int _userHandle) {
…
try {
// 在ObserverEntry实例化时调用了linkToDeath接口
observer.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
binderDied();
}
}
public void binderDied() {
synchronized (observersLock) {
removeObserverLocked(observer);
}
}
…
}
private void addObserverLocked(Uri uri, int index, IContentObserver observer,
boolean notifyForDescendants, Object observersLock,
int uid, int pid, int userHandle) {
if (index == countUriSegments(uri)) {
// 新建一个ObserverEntry的实例并保存仅mObservers链表中
mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
uid, pid, userHandle));
return;
}
…
}
ObserverService将会在ObserverEntry实例被插入mObservers链表中注册死亡回调接口。ObserverEntry实现了DeathRecipient接口,当应用端进程死亡时,binderDied将会被调用,从而调用removeObserverLocked来清除进程保存在mObservers的数据。需要注意的是,ContentService这时担任着进程通信时客户端的角色,当它调用linkToDeath时,实际上调用的时Binder Proxy的方法。
BroadcastReceiver
我一直在看BroadcastReceiver的源码,对这块比较熟悉。这里我主要讲讲当注册完广播后,如果注册应用进程死亡后AMS将如何调用死亡回调
ActivityManagerService.java
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
…
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
// 动态注册的广播新建ReceiverList后,调用linkToDeath方法
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
…
}
ReceiverList.java
// 广播的死亡回调接口在ReceiverList中实现
final class ReceiverList extends ArrayList<BroadcastFilter>
implements IBinder.DeathRecipient {
final ActivityManagerService owner;
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
…
}
…
public void binderDied() {
linkedToDeath = false;
// 应用进程死亡后,AMS将会调用反注册广播接口
owner.unregisterReceiver(receiver);
}
…
}
AudioManager
AudioManager这块有些生僻,稍微讲讲
MediaFocusControl.java
protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags) {
AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb);
…
try {
// 在这里注册死亡回掉
cb.linkToDeath(afdh, 0);
} catch (RemoteException e) {
// client has already died!
Log.w(TAG, “AudioFocus requestAudioFocus() could not link to “+cb+” binder death”);
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
…
protected class AudioFocusDeathHandler implements IBinder.DeathRecipient {
private IBinder mCb; // To be notified of client’s death
AudioFocusDeathHandler(IBinder cb) {
mCb = cb;
}
public void binderDied() {
synchronized(mAudioFocusLock) {
Log.w(TAG, “ AudioFocus audio focus client died”);
// 清除死亡进程的数据
removeFocusStackEntryForClient(mCb);
}
}
public IBinder getBinder() {
return mCb;
}
}
小问题
上面三个framework实例有这样的表现:
ContentService: 同应用调用registerContentObserver注册同一个ContentObserver传入的IContentObserver实例相同,每次都会重新注册一个死亡回调实例
ActivityManagerService: 同应用调用registerReceiver注册同一个Receiver传入的IIntentReceiver实例相同,每次不会重新注册一个死亡回调
AudioService: 同应用调用requestAudioFocus注册同一个OnAudioFocusChangeListener传入的mICallback实例相同,每次都会重新注册一个死亡回调实例
可以看到,AMS的广播注册与死亡回掉注册是正常的,同一个receiver只会注册一次死亡回调;但是ContentService和AudioService就不正常了,重复的ConentObserver还是会重复注册不同的死亡回调实例,这是有问题的。C++层维护了一个map用来保存死亡回调的信息,这个map超过一定的值会导致安卓系统死机重启,如果重复的Bp也重复去注册同一个回调的话,这个空间就会很快被消耗完,容易造成手机重启。
源码分析:注册死亡通知
Framework层:Binder.java
先从最顶层的JAVA代码开始看起:
public class Binder implements IBinder {
…
// native 端并不需要监听死亡回调,所以是空实现
public void linkToDeath(DeathRecipient recipient, int flags) {
}
/**
* Local implementation is a no-op.
*/
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return true;
}
…
final class BinderProxy implements IBinder {
…
// proxy 端直接通过JNI调用c++方法
public native void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
…
}
Native层:android_util_Binder.cpp
…
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL) = 0;
…
static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
jobject recipient, jint flags) // throws RemoteException
{
// 回调实例如果为空直接抛出异常返回
if (recipient == NULL) {
jniThrowNullPointerException(env, NULL);
return;
}
// 获取Bp Binder
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
if (target == NULL) {
ALOGW(“Binder has been finalized when calling linkToDeath() with recip=%p)\n”, recipient);
assert(false);
}
LOGDEATH(“linkToDeath: binder=%p recipient=%p\n”, target, recipient);
// 只有Bp才能进行回调注册
if (!target->localBinder()) {
// 获取死亡回调的记录链表
DeathRecipientList* list = (DeathRecipientList*)
env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
// 在c++层进行死亡回调注册
status_t err = target->linkToDeath(jdr, NULL, flags);
if (err != NO_ERROR) {
// Failure adding the death recipient, so clear its reference
// now.
jdr->clearReference();
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
}
}
}
class JavaDeathRecipient : public IBinder::DeathRecipient
{
public:
JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
mObjectWeak(NULL), mList(list)
{
// These objects manage their own lifetimes so are responsible for final bookkeeping.
// The list holds a strong reference to this object.
LOGDEATH(“Adding JDR %p to DRL %p”, this, list.get());
// 将这个对象加入到回调记录链表中
list->add(this);
android_atomic_inc(&gNumDeathRefs);
incRefsCreated(env);
}
}
static void incRefsCreated(JNIEnv* env)
{
int old = android_atomic_inc(&gNumRefsCreated);
// 每增加到200则执行一次force GC
if (old == 200) {
android_atomic_and(0, &gNumRefsCreated);
env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
gBinderInternalOffsets.mForceGc);
} else {
ALOGV(“Now have %d binder ops”, old);
}
}
BpBinder.cpp
status_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) {
if (!mObituaries) {
// 一个Bp可以注册多个死亡回调
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();
}
ssize_t res = mObituaries->add(ob);
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
}
}
return DEAD_OBJECT;
}
IPCThreadState.cpp
status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy)
{
// 对binder驱动发出命令
mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION);
mOut.writeInt32((int32_t)handle);
mOut.writePointer((uintptr_t)proxy);
return NO_ERROR;
}
void IPCThreadState::flushCommands()
{
if (mProcess->mDriverFD <= 0)
return;
talkWithDriver(false);
}
Kernel层:binder.c
int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
void __user *buffer, int size, signed long *consumed)
{
uint32_t cmd;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error == BR_OK) {
// 获取命令,此处为BC_REQUEST_DEATH_NOTIFICATION
if (get_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
…
switch (cmd) {
…
case BC_REQUEST_DEATH_NOTIFICATION:
case BC_CLEAR_DEATH_NOTIFICATION: {
uint32_t target;
void __user *cookie;
struct binder_ref *ref;
struct binder_ref_death *death;
// 取出handle值
if (get_user(target, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (get_user(cookie, (void __user * __user *)ptr))
return -EFAULT;
ptr += sizeof(void *);
// 通过 handle 值取 ref
ref = binder_get_ref(proc, target);
…
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
// 上面好像 Bp 可以注册多个,但是在kernel里面只能注册一个咧
if (ref->death) {
break;
}
// 这个 binder_ref_death 是kernel中保存死亡通知回调的结构
death = kzalloc(sizeof(*death), GFP_KERNEL);
if (death == NULL) {
thread->return_error = BR_ERROR;
break;
}
binder_stats_created(BINDER_STAT_DEATH);
// 初始化的工作队列列表
INIT_LIST_HEAD(&death->work.entry);
// 把用户空间传过来的那个指针保存起来
death->cookie = cookie;
// 每一个 ref 保存有一个 binder_ref_death
ref->death = death;
// 如果 ref 对应的 node 的 进程已经挂了,这里直接就发通知了
if (ref->node->proc == NULL) {
ref->death->work.type = BINDER_WORK_DEAD_BINDER;
if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
list_add_tail(&ref->death->work.entry, &thread->todo);
} else {
list_add_tail(&ref->death->work.entry, &proc->todo);
wake_up_interruptible(&proc->wait);
}
}
} else {
…
}
} break;
…
default:
printk(KERN_ERR “binder: %d:%d unknown command %d\n”,
proc->pid, thread->pid, cmd);
return -EINVAL;
}
*consumed = ptr - buffer;
}
return 0;
}
数据结构
struct binder_work {
struct list_head entry;
…
};
struct binder_ref_death {
struct binder_work work;
void __user *cookie;
};
struct binder_ref {
int debug_id;
struct rb_node rb_node_desc;
struct rb_node rb_node_node;
struct hlist_node node_entry;
struct binder_proc *proc;
struct binder_node *node;
uint32_t desc;
int strong;
int weak;
// 注册了的死亡通知结构
struct binder_ref_death *death;
};
源码分析:触发死亡通知
注册操作是从framework上层传到kernel下层的,对应的触发操作是从kernel下层传到framework上层的
kernel层:binder.c
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
static int binder_release(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc = filp->private_data;
debugfs_remove(proc->debugfs_entry);
// 定义了一个 kernel 的工作队列
binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
return 0;
}
static void
binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
{
mutex_lock(&binder_deferred_lock);
// 设置进程工作的类型
proc->deferred_work |= defer;
// 判断这个进程是不是已经加到工作队列里去了
if (hlist_unhashed(&proc->deferred_work_node)) {
// 还没有的话把这个进程的工作节点加到全局的工作队列里
hlist_add_head(&proc->deferred_work_node,
&binder_deferred_list);
// 这里是加到 kernel 的工作队列中
queue_work(binder_deferred_workqueue, &binder_deferred_work);
}
mutex_unlock(&binder_deferred_lock);
}
static struct workqueue_struct *binder_deferred_workqueue;
static int __init binder_init(void)
{
int ret;
//创建了名叫“binder”的工作队列
binder_deferred_workqueue = create_singlethread_workqueue(“binder”);
if (!binder_deferred_workqueue)
return -ENOMEM;
…
}
device_initcall(binder_init);
binder_deferred_func
static void binder_deferred_func(struct work_struct *work)
{
struct binder_proc *proc;
struct files_struct *files;
int defer;
do {
mutex_lock(&binder_lock);
mutex_lock(&binder_deferred_lock);
if (!hlist_empty(&binder_deferred_list)) {
// 在全局的工作队列中取最靠前的那个
proc = hlist_entry(binder_deferred_list.first,
struct binder_proc, deferred_work_node);
// 取出来后,从全局工作队列中删除
hlist_del_init(&proc->deferred_work_node);
// 取之前 binder_defer_work 设置的变量,
// 就是那个 BINDER_DEFERRED_RELEASE
defer = proc->deferred_work;
proc->deferred_work = 0;
} else {
proc = NULL;
defer = 0;
}
mutex_unlock(&binder_deferred_lock);
files = NULL;
if (defer & BINDER_DEFERRED_PUT_FILES) {
files = proc->files;
if (files)
proc->files = NULL;
}
if (defer & BINDER_DEFERRED_FLUSH)
binder_deferred_flush(proc);
if (defer & BINDER_DEFERRED_RELEASE)
binder_deferred_release(proc);
mutex_unlock(&binder_lock);
if (files)
put_files_struct(files);
} while (proc);
}
binder_deferred_release
static void binder_deferred_release(struct binder_proc *proc)
{
struct hlist_node *pos;
struct binder_transaction *t;
struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
…
hlist_del(&proc->proc_node);
if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
binder_context_mgr_node = NULL;
}
threads = 0;
active_transactions = 0;
// 这里是释放之前申请的 thread 相关的变量的内存吧
while ((n = rb_first(&proc->threads))) {
struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
threads++;
active_transactions += binder_free_thread(proc, thread);
}
nodes = 0;
incoming_refs = 0;
// 这里是遍历进程的每一个 node
while ((n = rb_first(&proc->nodes))) {
struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
nodes++;
rb_erase(&node->rb_node, &proc->nodes);
list_del_init(&node->work.entry);
if (hlist_empty(&node->refs)) {
// 如果这个 node 没有 ref 的话,可以直接删除
kfree(node);
binder_stats_deleted(BINDER_STAT_NODE);
} else {
struct binder_ref *ref;
int death = 0;
node->proc = NULL;
node->local_strong_refs = 0;
node->local_weak_refs = 0;
hlist_add_head(&node->dead_node, &binder_dead_nodes);
// 否则得看看 ref 里面是否设置了死亡通知回调
hlist_for_each_entry(ref, pos, &node->refs, node_entry) {
incoming_refs++;
if (ref->death) {
death++;
// 如果有设置的话,要发送死亡通知回调
if (list_empty(&ref->death->work.entry)) {
// 没发送的话,就把死亡回调的工作状态设置一下
ref->death->work.type = BINDER_WORK_DEAD_BINDER;
// 然后把这个 work 添加到 ref 的进程的 todo list
list_add_tail(&ref->death->work.entry, &ref->proc->todo);
wake_up_interruptible(&ref->proc->wait);
} else
BUG();
}
}
}
}
// 后面就是 binder_proc 结构的清理,
…
kfree(proc);
}
源码分析:触发死亡回调
binder_thread_read
static int binder_thread_read(struct binder_proc *proc,
struct binder_thread *thread,
void __user *buffer, int size,
signed long *consumed, int non_block)
{
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
…
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
if (!list_empty(&thread->todo))
w = list_first_entry(&thread->todo, struct binder_work, entry);
else if (!list_empty(&proc->todo) && wait_for_proc_work)
w = list_first_entry(&proc->todo, struct binder_work, entry);
else {
if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
goto retry;
break;
}
if (end - ptr < sizeof(tr) + 4)
break;
switch (w->type) {
…
// 刚刚前面发过来的 work type 是 BINDER_WORK_DEAD_BINDER
case BINDER_WORK_DEAD_BINDER:
case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
struct binder_ref_death *death;
uint32_t cmd;
// 从发过来的 work 中取 death 结构
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
else
// 这里返回给用户的是 BR_DEAD_BINDER
cmd = BR_DEAD_BINDER;
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
// 把用户空间注册过来时传过来的那个指针,原封不动的传回去
if (put_user(death->cookie, (void * __user *)ptr))
return -EFAULT;
ptr += sizeof(void *);
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
“binder: %d:%d %s %p\n”,
proc->pid, thread->pid,
cmd == BR_DEAD_BINDER ?
“BR_DEAD_BINDER” :
“BR_CLEAR_DEATH_NOTIFICATION_DONE”,
death->cookie);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
// 如果是清除死亡通知的话,可以释放之前申请的death结构的内存
list_del(&w->entry);
kfree(death);
binder_stats_deleted(BINDER_STAT_DEATH);
} else
// 这里不是清除,是触发通知,
// 把这个 work 队列放到该进程的 delivered_death 队列中
list_move(&w->entry, &proc->delivered_death);
if (cmd == BR_DEAD_BINDER)
// 这个很省事,直接就完工了,下面的处理都不用跑了
// 看注释是说发送死亡通知可以中断传输
goto done; /* DEAD_BINDER notifications can cause transactions */
} break;
}
… …
}
done:
*consumed = ptr - buffer;
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) {
proc->requested_threads++;
binder_debug(BINDER_DEBUG_THREADS,
“binder: %d:%d BR_SPAWN_LOOPER\n”,
proc->pid, thread->pid);
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
}
return 0;
}
executeCommand
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
result = executeCommand(cmd);
set_sched_policy(mMyThreadId, SP_FOREGROUND);
}
return result;
}
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
… …
case BR_DEAD_BINDER:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
// 然后调用 Bp 的发送仆告的函数
proxy->sendObituary();
// 然后对 kernel 发 BC_DEAD_BINDER_DONE 通知放送完成的命令
mOut.writeInt32(BC_DEAD_BINDER_DONE);
// 把 Bp 的 handle 写进入刚刚的命名包里
mOut.writeInt32((int32_t)proxy);
} break;
… …
default:
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
sendObituary
void BpBinder::sendObituary()
{
…
mAlive = 0;
if (mObitsSent) return;
mLock.lock();
// 取前面注册保存的回调
Vector<Obituary>* obits = mObituaries;
if(obits != NULL) {
// 这里发通知前先把已经注册了通知清理掉
IPCThreadState* self = IPCThreadState::self();
self->clearDeathNotification(mHandle, this);
// 马上对 kernel 发清理命令
self->flushCommands();
mObituaries = NULL;
}
// 设置当前通知已经发送
mObitsSent = 1;
mLock.unlock();
if (obits != NULL) {
const size_t N = obits->size();
for (size_t i=0; i<N; i++) {
// 发送通知
reportOneDeath(obits->itemAt(i));
}
delete obits;
}
}
status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy)
{
mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION);
mOut.writeInt32((int32_t)handle);
mOut.writeInt32((int32_t)proxy);
return NO_ERROR;
}
BC_REQUEST_DEATH_NOTIFICATION
// 上面取用户空间写的 Bp 的 handle,然后可以取得到 ref
// 然后那个 cookie 就是用户空间传过来那个指针
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
// 这里是上面处理注册回调的
… …
} else {
// 这里是清理回调的
// 如果 ref 的 death 没有,要是没注册,要么是已经清理过了
if (ref->death == NULL) {
binder_user_error(“binder: %d:%”
“d BC_CLEAR_DEATH_NOTIFI”
“CATION death notificat”
“ion not active\n”,
proc->pid, thread->pid);
break;
}
death = ref->death;
// 这里拿传过来那个指针做下验证
if (death->cookie != cookie) {
binder_user_error(“binder: %d:%”
“d BC_CLEAR_DEATH_NOTIFI”
“CATION death notificat”
“ion cookie mismatch “
“%p != %p\n”,
proc->pid, thread->pid,
death->cookie, cookie);
break;
}
// 把 ref 的回调设置为空
ref->death = NULL;
// 这里一般这个死亡通知回调的 work 列队是空的
// 前面触发了通知后,把这个队列移到 proc->delivered_death 去了
if (list_empty(&death->work.entry)) {
death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
// 这里是改变那个 work 状态,然后根据这个线程的情况
if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
list_add_tail(&death->work.entry, &thread->todo);
} else {
list_add_tail(&death->work.entry, &proc->todo);
wake_up_interruptible(&proc->wait);
}
} else {
BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
}
}
void BpBinder::reportOneDeath(const Obituary& obit)
{
sp<DeathRecipient> recipient = obit.recipient.promote();
ALOGV(“Reporting death to recipient: %p\n”, recipient.get());
if (recipient == NULL) return;
// 调用死亡通知的回调函数了,参数就是 Bp 自己的指针
recipient->binderDied(this);
}
case BC_DEAD_BINDER_DONE: {
struct binder_work *w;
void __user *cookie;
struct binder_ref_death *death = NULL;
// 注册的时候写的用户空间那个指针
if (get_user(cookie, (void __user * __user *)ptr))
return -EFAULT;
ptr += sizeof(void *);
// 前面在触发通知的时候,death 的work移动到了delivered_death了
// 这里在 delivered_death 中通过那个指针找到对应的 death
list_for_each_entry(w, &proc->delivered_death, entry) {
struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
if (tmp_death->cookie == cookie) {
death = tmp_death;
break;
}
}
if (death == NULL) {
break;
}
// 删除 death 中 work 队列
list_del_init(&death->work.entry);
// 最后把 work 的 type 设置一下,最后还要发送到 read 去处理下,
// 看样子最后还要清理一下,申请的 death 结构还没释放
if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
list_add_tail(&death->work.entry, &thread->todo);
} else {
list_add_tail(&death->work.entry, &proc->todo);
wake_up_interruptible(&proc->wait);
}
}
} break;
附一张binder close回调流程图: