当前位置:   article > 正文

Binder系列11 死亡通知机制_uncaught exception from death notification

uncaught exception from death notification

死亡通知机制概述   

如果在 binder 通信已经建立的情况下,出现 binder 服务端的进程意外挂掉,这个挂掉的原因可能是因为进程本身内部发生的错误,也有可能是其它情况导致进程被系统强制结束,总之这个服务端进程是存在意外挂掉的可能的,如果出现这种情况,而 binder 代理端不知道的话,那么代理端继续调用不存在的服务端时肯定会出错.这个时候就需要有一种机制来通知到依赖这个服务的 binder 代理端,好让代理端作出相应的操作,以保证代理端进程不会因为 binder 服务端进程的意外挂掉而出错。这个机制就是 binder 提供的死亡通知机制。

在这种死亡通知机制中,首先是 Binder 代理对象(BpBinder)通过发送命令 BC_REQUEST_DEATH_NOTIFICATION 到驱动,告诉 Binder 驱动这个 Binder 代理对象要注册一个死亡接收通知,注册完成之后,驱动就会在对应 binder_ref 的 death 中做好标记.如果对应的 Binder 服务端的进程因为意外发生挂掉,Binder 驱动会释放掉这个服务端进程对应的 binder_proc 中 nodes 树的所有 binder_node 节点,在释放 binder_node 节点的过程中,会遍历所有引用这个节点的引用树 refs,其中 binder 代理对象在驱动中的表示 binder 引用 binder_ref 就链接在这个引用树中,这样驱动就会找到这个 binder_ref,并检查这个 binder 引用的 death 值是否为空,如果不为空则说明已经注册了死亡通知,如果为空,则说明没有注册死亡通知,这样驱动就根据 binder_ref 的 death 值来决定是否向其发送死亡通知,这个就是大体流程。

当然,如果一个 Binder 代理对象(BpBinder)不需要接收它所引用的 Binder 本地对象(BBinder)的死亡通知时,它也可以注销之前所注册的死亡接受通知。

下面我们从死亡通知的注册,注销,触发和处理四个方面分别阐述其过程,以了解其原理。最后分析下 java 层如何通过 JNI 和 native 进行通信以及使用例子。

相关代码路徑:

  1. frameworks/base/core/java/android/os/Binder.java
  2. frameworks/base/core/jni/android_util_Binder.cpp
  3. frameworks/native/libs/binder/BpBinder.cpp

一 死亡通知的注册

Binder 代理对象(BpBinder)通过 linkToDeath 函数实现对死亡通知的注册,代码如下:

BpBinder.cpp

  1. status_t BpBinder::linkToDeath(
  2. const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
  3. {
  4. Obituary ob;
  5. ob.recipient = recipient;// 具体的死亡接收通知
  6. ob.cookie = cookie; // 这个参数一般为 null
  7. ob.flags = flags; // 生成一个新的 Obituary,并赋值
  8. LOG_ALWAYS_FATAL_IF(recipient == NULL,
  9. "linkToDeath(): recipient must be non-NULL");
  10. {
  11. AutoMutex _l(mLock);
  12. //驱动是否已经发送过死亡通知,如果没有发送过则执行注册操作
  13. if (!mObitsSent) { 
  14. if (!mObituaries) {//向量表不存在的话,生成新的向量表,
  15. // 并向驱动发送注册请求,如果向量表存在的话,就不需要向驱动发送请求
  16. // 直接把 Obituary 添加到 mObituaries 向量表中既可
  17. mObituaries = new Vector<Obituary>;
  18. if (!mObituaries) {
  19. return NO_MEMORY;
  20. }
  21. ALOGV("Requesting death notification: %p handle %d\n",
  22. this, mHandle);
  23. getWeakRefs()->incWeak(this);
  24. IPCThreadState* self = IPCThreadState::self();
  25. // 向mOut写入注册死亡通知的命令
  26. self->requestDeathNotification(mHandle, this);
  27. self->flushCommands();
  28. }
  29. //把新生成的Obituary放入向量表中
  30. ssize_t res = mObituaries->add(ob);
  31. return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
  32. }
  33. }
  34. return DEAD_OBJECT;
  35. }

以上死亡通知的注册函数有以下几个关键变量需要注意:

mObituaries 是一个向量表,里边是 Obituary 的集合,而 Obituary 是封装了死亡接收通知 DeathRecipient 的一个对象,我们可以认为,每一个 Obituary 就代表注册了一个死亡接收通知,从代码中可以看出一个 Binder 代理对象可以注册多个死亡接收通知 Obituary,并把这些注册好的 Obituary 放到向量表 mObituaries 中。

mObitsSent 这个变量代表 Binder 驱动是否已经向 binder 代理发送了死亡通知,如果已经发送了则为1,否则为 0,如果已经发送了,则就不需要注册了,直接返回 DEAD_OBJECT。

从以上代码中还可以看到负责注册死亡通知的函数 requestDeathNotification 只会在第一次创建 mObituaries 的时候会被执行.其它情况下只需要把死亡接收通知 Obituary 直接添加到 mObituaries 中既可,不需要多次注册.也就是不管 binder 代理端调用 linkToDeath 函数多少次,实际上只会向驱动请求一次,并且是第一次的时候向驱动请求。

只向驱动请求一次的原因是 Binder 代理注册死亡通知后,驱动就已经知道了,如果服务端进程挂掉,那么我就要通知这个 Binder 代理,当 binder 代理收到死亡通知后,只需要遍历 mObituaries 向量表中的 Obituary,分别回调其中的 DeathRecipient 的 binderDied 方法既可,所以就不需要多次向 Binder 驱动重复请求了.

IPCThreadState.cpp

  1. status_t IPCThreadState::requestDeathNotification(int32_t handle,
  2. BpBinder* proxy)
  3. {
  4. mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION);
  5. mOut.writeInt32((int32_t)handle);
  6. mOut.writePointer((uintptr_t)proxy);
  7. return NO_ERROR;
  8. }

从以上代码中可以看到 requestDeathNotification 就是把 BC_REQUEST_DEATH_NOTIFICATION 命令发送到 Binder 驱动端,其中的参数是 binder 代理对象的句柄 handle,还有 binder 代理对象的地址 proxy,把这些数据填充到 mOut 中,然后整理成 binder_write_read 数据,通过 ioctl 的 BINDER_WRITE_READ 协议写入到 Binder 驱动中。其中的 BC_REQUEST_DEATH_NOTIFICATION 就是向 Binder 驱动注册死亡接收通知的命令。

接着看 binder 驱动端如何处理 BC_REQUEST_DEATH_NOTIFICATION 命令,代码如下:

  1. static int binder_thread_write(struct binder_proc *proc,
  2. struct binder_thread *thread,
  3. binder_uintptr_t binder_buffer, size_t size,
  4. binder_size_t *consumed)
  5. {
  6. uint32_t cmd;
  7. struct binder_context *context = proc->context;
  8. void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
  9. void __user *ptr = buffer + *consumed;
  10. void __user *end = buffer + size;
  11. while (ptr < end && thread->return_error.cmd == BR_OK) {
  12. int ret;
  13. if (get_user(cmd, (uint32_t __user *)ptr))
  14. return -EFAULT;
  15. ptr += sizeof(uint32_t);
  16. trace_binder_command(cmd);
  17. if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
  18. atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]);
  19. atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]);
  20. atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]);
  21. }
  22. switch (cmd) {
  23. case BC_INCREFS:
  24. case BC_ACQUIRE:
  25. case BC_RELEASE:
  26.     .................
  27.          case BC_REQUEST_DEATH_NOTIFICATION:
  28. case BC_CLEAR_DEATH_NOTIFICATION: {
  29. // BpBinder对应的句柄值,用来找到驱动端对应的 binder_ref
  30. uint32_t target; 
  31. // 代理对象 BpBinder 的地址
  32. binder_uintptr_t cookie;
  33. struct binder_ref *ref;
  34. // binder_ref 对应的死亡通知
  35. struct binder_ref_death *death = NULL;
  36. // 从用户空间获取代理对象的句柄值
  37. if (get_user(target, (uint32_t __user *)ptr)) 
  38. return -EFAULT;
  39. ptr += sizeof(uint32_t);
  40. // 获取代理对象的地址
  41. if (get_user(cookie, (binder_uintptr_t __user *)ptr))
  42. return -EFAULT;
  43. ptr += sizeof(binder_uintptr_t);
  44. if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
  45. /*
  46. * Allocate memory for death notification
  47. * before taking lock
  48. */
  49. // 给 binder_ref_death 分配地址空间
  50. death = kzalloc(sizeof(*death), GFP_KERNEL);
  51. if (death == NULL) {
  52. WARN_ON(thread->return_error.cmd !=
  53. BR_OK);
  54. thread->return_error.cmd = BR_ERROR;
  55. binder_enqueue_thread_work(
  56. thread,
  57. &thread->return_error.work);
  58. binder_debug(
  59. BINDER_DEBUG_FAILED_TRANSACTION,
  60. "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
  61. proc->pid, thread->pid);
  62. break;
  63. }
  64. }
  65. binder_proc_lock(proc);
  66. // 根据句柄获得对应的 binder_ref
  67. ref = binder_get_ref_olocked(proc, target, false);
  68. if (ref == NULL) {
  69. binder_user_error("%d:%d %s invalid ref %d\n",
  70. proc->pid, thread->pid,
  71. cmd == BC_REQUEST_DEATH_NOTIFICATION ?
  72. "BC_REQUEST_DEATH_NOTIFICATION" :
  73. "BC_CLEAR_DEATH_NOTIFICATION",
  74. target);
  75. binder_proc_unlock(proc);
  76. kfree(death);
  77. break;
  78. }
  79. .......................
  80. binder_node_lock(ref->node);
  81. if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
  82. if (ref->death) {
  83. binder_user_error(
  84. "%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
  85. proc->pid, thread->pid);
  86. binder_node_unlock(ref->node);
  87. binder_proc_unlock(proc);
  88. kfree(death);
  89. break;
  90. }
  91. binder_stats_created(BINDER_STAT_DEATH);
  92. // 初始化 binder_ref_death 的 work
  93. INIT_LIST_HEAD(&death->work.entry);
  94. // 把代理对象地址赋值给 death 的 cookie
  95. death->cookie = cookie;
  96. // 把 binder_ref_death 赋值给 binder_ref 的 death,完成死亡通知的注册
  97. ref->death = death;
  98. // 代理对象对应的服务端进程已经死亡(异常情况)
  99. if (ref->node->proc == NULL) {
  100. // 修改 work type,这个代表死亡通知
  101. ref->death->work.type = BINDER_WORK_DEAD_BINDER;
  102. binder_inner_proc_lock(proc);
  103. // 把 binder_ref_death 的 work 添加到代理端进程的等待队列 todo 中
  104. binder_enqueue_work_ilocked(
  105. &ref->death->work, &proc->todo);
  106. // 唤醒代理端进程来处理死亡通知
  107. binder_wakeup_proc_ilocked(proc);
  108. binder_inner_proc_unlock(proc);
  109. }
  110. } else {
  111. ......................
  112. }
  113. binder_node_unlock(ref->node);
  114. binder_proc_unlock(proc);
  115. } break;

从以上代码可以看到向 Binder 驱动注册死亡接收通知非常简单,其实就是新建一个 binder_ref_death 对象,把代表 Binder 代理对象的 cookie 赋值给 binder_ref_death 的 cookie,并初始化其中的 wrok,然后把 binder_ref_death 对象赋值给代理对象对应的 binder_ref 的 death 就可以了.以后 binder 驱动会根据 binder_ref 的 death 是否存在来决定是否向其发送死亡通知。

从代码中可以看到对 binder_ref 的 death 赋值完毕后,会有一个 ref->node->proc 是否为空的判断,也就是在刚注册完死亡通知后,驱动程序会立马判断服务端进程是否已经挂掉,如果已经挂掉了,那么把这个 death 的 work 赋值为 BINDER_WORK_DEAD_BINDER 并添加到代理端进程的等待队列 todo 中,并唤醒代理端进程,处理 BINDER_WORK_DEAD_BINDER 任务,这个就是处理死亡通知的事情了,后面会介绍.其中发送的 BINDER_WORK_DEAD_BINDER 就是发送死亡通知了.这个情况也是考虑到在注册死亡通知的时候,服务端进程其实已经挂掉了,虽然概率很低,但是如果不检查的话,那么注册后,后续 Binder 代理是收不到死亡通知的,这个需要注意。

  1. struct binder_ref_death {
  2. /**
  3. * @work: worklist element for death notifications
  4. * (protected by inner_lock of the proc that
  5. * this ref belongs to)
  6. */
  7. struct binder_work work;
  8. binder_uintptr_t cookie;
  9. };

死亡接收通知的注册已经讲完了,说白了就是对 Binder 代理对象驱动层对应的 binder_ref 的 death 赋值,只要有了这个 death 值,驱动就知道这个 binder 引用 binder_ref 已经注册了死亡接收通知。这样一旦服务端进程意外挂掉的话,binder 驱动就会遍历服务端进程 binder_proc 中的 nodes 树中所有的 binder_node 节点,并对每个 binder_node 节点的 refs 链表做遍历操作,找出其中的每个依赖此 binder_node 节点的 binder_ref,然后检查 binder_ref 的 death 值,如果不为空,则就向其发送死亡通知。

二 死亡通知的注销

Binder 代理对象(BpBinder)通过 unlinkToDeath 函数实现对死亡通知的注销的,代码如下:

BpBinder.cpp

  1. status_t BpBinder::unlinkToDeath(
  2. const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
  3. wp<DeathRecipient>* outRecipient)
  4. {
  5. AutoMutex _l(mLock);
  6. if (mObitsSent) { // 已经发送过死亡通知了直接返回
  7. return DEAD_OBJECT;
  8. }
  9. const size_t N = mObituaries ? mObituaries->size() : 0;
  10. // 遍历 mObituaries 查找匹配的已经注册过的 DeathRecipient
  11. for (size_t i=0; i<N; i++) {
  12. const Obituary& obit = mObituaries->itemAt(i);
  13. if ((obit.recipient == recipient
  14. || (recipient == NULL && obit.cookie == cookie))
  15. && obit.flags == flags) {
  16. // 匹配成功,找到之前已经注册过的 DeathRecipient
  17. if (outRecipient != NULL) {
  18. *outRecipient = mObituaries->itemAt(i).recipient;
  19. }
  20. mObituaries->removeAt(i); // 执行移除操作
  21. if (mObituaries->size() == 0) {
  22. // 全部移除完毕了,才会向驱动发送清除死亡消息的命令
  23. ALOGV("Clearing death notification: %p handle %d\n",
  24. this, mHandle);
  25. IPCThreadState* self = IPCThreadState::self();
  26. self->clearDeathNotification(mHandle, this);
  27. self->flushCommands();
  28. delete mObituaries;
  29. mObituaries = NULL;
  30. }
  31. return NO_ERROR;
  32. }
  33. }
  34. return NAME_NOT_FOUND;
  35. }

从以上代码可以看到 Binder 代理通过 unlinkToDeath 函数来注销注册过的死亡接收通知,每次执行一次注销操作,都会遍历 mObituaries 向量表,找出之前注册过的 Obituary,找到并匹配成功后,从 mObituaries 表中移除即可.当注册过的死亡通知全部被移除后,才会向 Binder 驱动发送注销死亡接收通知的命令,同注册时候一样,注销也是只向驱动发送一次注销命令.原因相同。

IPCThreadState.cpp

  1. status_t IPCThreadState::clearDeathNotification(int32_t handle,
  2. BpBinder* proxy)
  3. {
  4. mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION);
  5. mOut.writeInt32((int32_t)handle);
  6. mOut.writePointer((uintptr_t)proxy);
  7. return NO_ERROR;
  8. }

把 BC_CLEAR_DEATH_NOTIFICATION 命令 附带 binder 代理对象的句柄 handle 和 binder 代理对象的地址 proxy 添加到 mOut 中,然后发送给 binder 驱动,下面看驱动如何处理:

  1. static int binder_thread_write(struct binder_proc *proc,
  2. struct binder_thread *thread,
  3. binder_uintptr_t binder_buffer, size_t size,
  4. binder_size_t *consumed)
  5. {
  6. uint32_t cmd;
  7. struct binder_context *context = proc->context;
  8. void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
  9. void __user *ptr = buffer + *consumed;
  10. void __user *end = buffer + size;
  11. while (ptr < end && thread->return_error.cmd == BR_OK) {
  12. int ret;
  13. if (get_user(cmd, (uint32_t __user *)ptr))
  14. return -EFAULT;
  15. ptr += sizeof(uint32_t);
  16. trace_binder_command(cmd);
  17. if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
  18. atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]);
  19. atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]);
  20. atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]);
  21. }
  22. switch (cmd) {
  23. case BC_INCREFS:
  24. case BC_ACQUIRE:
  25. case BC_RELEASE:
  26.     .................
  27.          case BC_REQUEST_DEATH_NOTIFICATION:
  28. case BC_CLEAR_DEATH_NOTIFICATION: {
  29. uint32_t target;// binder 代理对象的句柄值
  30. binder_uintptr_t cookie; // binder 代理对象的地址
  31. struct binder_ref *ref;
  32. struct binder_ref_death *death = NULL;
  33. if (get_user(target, (uint32_t __user *)ptr))
  34. return -EFAULT;
  35. ptr += sizeof(uint32_t);
  36. if (get_user(cookie, (binder_uintptr_t __user *)ptr))
  37. return -EFAULT;
  38. ptr += sizeof(binder_uintptr_t);
  39. .................
  40. binder_proc_lock(proc);
  41. // 获取对应的 binder_ref
  42. ref = binder_get_ref_olocked(proc, target, false);
  43. if (ref == NULL) {
  44. ......
  45. }
  46. .............................
  47. binder_node_lock(ref->node);
  48. if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
  49. .......................
  50. } else { // 走入 BC_CLEAR_DEATH_NOTIFICATION 分支
  51. if (ref->death == NULL) {
  52. binder_user_error(
  53. "%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
  54. proc->pid, thread->pid);
  55. binder_node_unlock(ref->node);
  56. binder_proc_unlock(proc);
  57. break;
  58. }
  59. death = ref->death;
  60. if (death->cookie != cookie) {
  61. ......
  62. }
  63. // 把 binder_ref 的 death 赋值为 null,实现对死亡接收通知的注销操作
  64. ref->death = NULL;
  65. binder_inner_proc_lock(proc);
  66. if (list_empty(&death->work.entry)) {
  67. death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
  68. if (thread->looper &
  69. (BINDER_LOOPER_STATE_REGISTERED |
  70. BINDER_LOOPER_STATE_ENTERED))
  71. // 当前线程为 binder 线程,则直接添加到当前线程的 todo 队列
  72. binder_enqueue_thread_work_ilocked(
  73. thread,
  74. &death->work);
  75. else {
  76. // 否则添加到进程的 todo 队列
  77. binder_enqueue_work_ilocked(
  78. &death->work,
  79. &proc->todo);
  80. binder_wakeup_proc_ilocked(
  81. proc);
  82. }
  83. } else {
  84. // 如果&death->work.entry 不为空,说明服务端进程已经死亡了,并且已经添加
  85. // work 到进程或线程的 todo 队列了,直接修改 work type 为
  86. // BINDER_WORK_DEAD_BINDER_AND_CLEAR 既可,不需要执行再次添加 work
  87. // 到相关 todo 队列的操作了
  88. BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
  89. death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
  90. }
  91. binder_inner_proc_unlock(proc);
  92. }
  93. binder_node_unlock(ref->node);
  94. binder_proc_unlock(proc);
  95. } break;

以上驱动对死亡接收通知的注销操作主要做了两件事情:

一)把 binder 代理对象对应的 binder 引用的 binder_ref 的 death 对象赋值为 null。这样驱动就不会再向其发送死亡通知了

二)注销后还需要把相关的消息反馈到 binder 代理端(通过添加 work 到代理端进程或线程的 todo 队列的方式),代理端需要执行一些操作,比如减少引用等操作

在把 binder_ref_death 的 work 提交到代理端进程或线程的 todo 队列的过程中,会对这个 work 进行判断,如果 work 的 entry 为空,则说明驱动还没有发送死亡通知,直接发送 BINDER_WORK_CLEAR_DEATH_NOTIFICATION 即可,如果 work 的 entry 不为空,则说明驱动已经发送死亡通知了,并且已经把 work 添加到 binder 代理端的进程或线程的 todo 队列中了,这个时候只需要修改 work type 为 BINDER_WORK_DEAD_BINDER_AND_CLEAR 即可,不需要在执行 todo 队列入队操作.正常的注销操作应该是 work 的 entry 为空,并且发送 BINDER_WORK_CLEAR_DEATH_NOTIFICATION。

接下来看代理端的 read 操作

  1. static int binder_thread_read(struct binder_proc *proc,
  2. struct binder_thread *thread,
  3. binder_uintptr_t binder_buffer, size_t size,
  4. binder_size_t *consumed, int non_block)
  5. {
  6. void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
  7. void __user *ptr = buffer + *consumed;
  8. void __user *end = buffer + size;
  9. int ret = 0;
  10. int wait_for_proc_work;
  11. if (*consumed == 0) {
  12. if (put_user(BR_NOOP, (uint32_t __user *)ptr))
  13. return -EFAULT;
  14. ptr += sizeof(uint32_t);
  15. }
  16. .....................
  17.      case BINDER_WORK_DEAD_BINDER:
  18. case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
  19. case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
  20. struct binder_ref_death *death;
  21. uint32_t cmd;
  22. binder_uintptr_t cookie;
  23. // 根据 work 找到对应的 binder_ref_death
  24. death = container_of(w, struct binder_ref_death, work);
  25. if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
  26. // 如果是单纯的 clear 操作,则向代理端发送 BR_CLEAR_DEATH_NOTIFICATION_DONE
  27. // 命令,完成引用减少操作即可
  28. cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
  29. else
  30. // 如果不是单纯的 clear,则发送 BR_DEAD_BINDER,代理端执行发送死亡通知
  31. cmd = BR_DEAD_BINDER;
  32. // death 中存储的代理端的代理对象地址,赋值给 cookie
  33. cookie = death->cookie;
  34. ......
  35. if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
  36. binder_inner_proc_unlock(proc);
  37. kfree(death);// 在驱动端 free 掉 death
  38. binder_stats_deleted(BINDER_STAT_DEATH);
  39. } else {
  40. // 添加 work 到 delivered_death 中,在代理端发送死亡通知后,然后向驱动发送
  41. // BC_DEAD_BINDER_DONE 命令,再这个命令中处理
  42. binder_enqueue_work_ilocked(
  43. w, &proc->delivered_death);/
  44. binder_inner_proc_unlock(proc);
  45. }
  46. if (put_user(cmd, (uint32_t __user *)ptr)) // 写命令到用户空间
  47. return -EFAULT;
  48. ptr += sizeof(uint32_t);
  49. if (put_user(cookie,
  50. (binder_uintptr_t __user *)ptr))
  51. // 写 cookie 到用户空间,这个代表 binder 代理对象的地址
  52. return -EFAULT;
  53. ptr += sizeof(binder_uintptr_t);
  54. binder_stat_br(proc, thread, cmd);
  55. if (cmd == BR_DEAD_BINDER)
  56. goto done;
  57. /* DEAD_BINDER notifications can cause transactions */
  58. } break;
  59. ..............................

从以上代码可以看到先定位到 BINDER_WORK_CLEAR_DEATH_NOTIFICATION 命令,这个命令就是正常的注销操作,驱动端读取这个命令后,先设置 cmd 为BR_CLEAR_DEATH_NOTIFICATION_DONE,然后 free 掉这个 death,做后把命令和参数反馈到用户空间.接下来看用户空间对 BR_CLEAR_DEATH_NOTIFICATION_DONE 的处理过程

IPCThreadState.cpp

  1. status_t IPCThreadState::executeCommand(int32_t cmd)
  2. {
  3. BBinder* obj;
  4. RefBase::weakref_type* refs;
  5. status_t result = NO_ERROR;
  6. switch ((uint32_t)cmd) {
  7. case BR_ERROR:
  8. result = mIn.readInt32();
  9. break;
  10. case BR_OK:
  11. break;
  12. .......................
  13.   case BR_CLEAR_DEATH_NOTIFICATION_DONE:
  14. {
  15. BpBinder *proxy = (BpBinder*)mIn.readPointer();
  16. proxy->getWeakRefs()->decWeak(proxy);
  17. } break;
  18. ...............

很简单,就是通过读取从内核空间传过来的参数 cookie,获取 binder 代理对象 proxy,并对引用做 decWea 操作。

以上就是死亡通知的注销流程,简单总结就是 binder 代理端的 binder 代理对象发送 BC_CLEAR_DEATH_NOTIFICATION 命令,在驱动端先把 binder_ref 的 death 保存起来,然后把binder_ref 的 death 置为 null,最后把保存起来的这个 death 的 work type 修改为 BINDER_WORK_CLEAR_DEATH_NOTIFICATION,并且把这个 death 的 work 添加到代理端进程或线程的 todo 队列中。

当代理端接收到这个 work 后,会先把命令 cmd 赋值为 BR_CLEAR_DEATH_NOTIFICATION_DONE,然后 free 掉这个 binder_ref_death,最后向 binder 代理端返回,代理端在接收到这个命令后,执行对代理对象的引用做减少操作。

三 死亡通知的触发

当 Binder 服务所在的进程死亡后,会释放掉进程相关的资源,Binder 也是一种资源,也需要释放。

Binder 驱动将设备文件 /dev/binder 的释放操作方法设置为函数 binder_release,也就是释放 binder 驱动设备的时候,会回调到 binder_release 方法,这个是正常死亡的时候,然而如果是非正常死亡呢,即它没有正常关闭设备文件 /dev/binder,那么内核就会负责关闭它,这个时候也会触发函数 binder_release 的调用。因此,Binder 驱动程序只要在函数 binder_release 中释放相关 binder 资源就可以了,在释放 binder 资源的过程中,如果发现有对应的 binder_ref 引用其中的 binder_node,那么查看是否有 death 值,如果有则向其发送死亡通知,下面看详细过程

  1. static const struct file_operations binder_fops = {
  2. .owner = THIS_MODULE,
  3. .poll = binder_poll,
  4. .unlocked_ioctl = binder_ioctl,
  5. .compat_ioctl = binder_ioctl,
  6. .mmap = binder_mmap,
  7. .open = binder_open,
  8. .flush = binder_flush,
  9. .release = binder_release,
  10. };

接着调用 binder_release

  1. static int binder_release(struct inode *nodp, struct file *filp)
  2. {
  3. struct binder_proc *proc = filp->private_data;
  4. debugfs_remove(proc->debugfs_entry);
  5. binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
  6. return 0;
  7. }

 binder_defer_work

  1. static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
  2. static void
  3. binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
  4. {
  5. mutex_lock(&binder_deferred_lock);
  6. proc->deferred_work |= defer;
  7. if (hlist_unhashed(&proc->deferred_work_node)) {
  8. hlist_add_head(&proc->deferred_work_node,
  9. &binder_deferred_list);
  10. schedule_work(&binder_deferred_work);
  11. }
  12. mutex_unlock(&binder_deferred_lock);
  13. }

主要操作为:把 proc 中的 deferred_work 赋值为 BINDER_DEFERRED_RELEASE,然后检查 proc 的 deferred_work_node 是否已经添加到哈希链表 binder_deferred_list 中,如果没有添加,则做添加操作,然后调用声明的 binder_deferred_func 函数执行 binder_deferred_work 工作队列

  1. static void binder_deferred_func(struct work_struct *work)
  2. {
  3. struct binder_proc *proc;
  4. int defer;
  5. do {
  6. mutex_lock(&binder_deferred_lock);
  7. if (!hlist_empty(&binder_deferred_list)) {
  8. proc = hlist_entry(binder_deferred_list.first,
  9. struct binder_proc, deferred_work_node);
  10. hlist_del_init(&proc->deferred_work_node);
  11. defer = proc->deferred_work;
  12. proc->deferred_work = 0;
  13. } else {
  14. proc = NULL;
  15. defer = 0;
  16. }
  17. mutex_unlock(&binder_deferred_lock);
  18. if (defer & BINDER_DEFERRED_FLUSH)
  19. binder_deferred_flush(proc);
  20. if (defer & BINDER_DEFERRED_RELEASE)
  21. binder_deferred_release(proc); /* frees proc */
  22. } while (proc);
  23. }

从 binder_deferred_func 函数可以看到,会从 binder_deferred_list 中找到上面添加到头部的 deferred_work_node,然后根据 deferred_work_node 找到对应的 proc,最后调用 binder_deferred_release 方法进行释放资源操作

  1. static void binder_deferred_release(struct binder_proc *proc)
  2. {
  3. struct binder_context *context = proc->context;
  4. struct rb_node *n;
  5. int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
  6. mutex_lock(&binder_procs_lock);
  7. hlist_del(&proc->proc_node); // 把 proc 从进程链表 procs 中删除
  8. mutex_unlock(&binder_procs_lock);
  9. mutex_lock(&context->context_mgr_node_lock);
  10. if (context->binder_context_mgr_node &&
  11. context->binder_context_mgr_node->proc == proc) {
  12. binder_debug(BINDER_DEBUG_DEAD_BINDER,
  13. "%s: %d context_mgr_node gone\n",
  14. __func__, proc->pid);
  15. // 如果是 servicemanager 进程挂掉,则对相应的 binder_node 置为null
  16. context->binder_context_mgr_node = NULL;
  17. }
  18. mutex_unlock(&context->context_mgr_node_lock);
  19. binder_inner_proc_lock(proc);
  20. /*
  21. * Make sure proc stays alive after we
  22. * remove all the threads
  23. */
  24. proc->tmp_ref++;
  25. proc->is_dead = true; // 进程标记为 dead
  26. threads = 0;
  27. active_transactions = 0;
  28. while ((n = rb_first(&proc->threads))) {
  29. // 遍历进程的线程树,找到每一个相关线程
  30. struct binder_thread *thread;
  31. thread = rb_entry(n, struct binder_thread, rb_node);
  32. binder_inner_proc_unlock(proc);
  33. threads++;
  34. // 释放线程
  35. active_transactions += binder_thread_release(proc, thread);
  36. binder_inner_proc_lock(proc);
  37. }
  38. nodes = 0;
  39. incoming_refs = 0;
  40. while ((n = rb_first(&proc->nodes))) {
  41. // 遍历进程的节点树,找到每一个相关节点
  42. struct binder_node *node;
  43. node = rb_entry(n, struct binder_node, rb_node);
  44. nodes++;
  45. /*
  46. * take a temporary ref on the node before
  47. * calling binder_node_release() which will either
  48. * kfree() the node or call binder_put_node()
  49. */
  50. binder_inc_node_tmpref_ilocked(node);
  51. rb_erase(&node->rb_node, &proc->nodes);
  52. binder_inner_proc_unlock(proc);
  53. // 释放节点
  54. incoming_refs = binder_node_release(node, incoming_refs);
  55. binder_inner_proc_lock(proc);
  56. }
  57. binder_inner_proc_unlock(proc);
  58. outgoing_refs = 0;
  59. binder_proc_lock(proc);
  60. while ((n = rb_first(&proc->refs_by_desc))) {
  61. // 遍历进程的引用树,找到每一个相关引用
  62. struct binder_ref *ref;
  63. ref = rb_entry(n, struct binder_ref, rb_node_desc);
  64. outgoing_refs++;
  65. binder_cleanup_ref_olocked(ref);
  66. binder_proc_unlock(proc);
  67. // 释放引用
  68. binder_free_ref(ref);
  69. binder_proc_lock(proc);
  70. }
  71. binder_proc_unlock(proc);
  72. // 释放进程的等待队列 todo
  73. binder_release_work(proc, &proc->todo);
  74. // 释放进程的 delivered_death
  75. binder_release_work(proc, &proc->delivered_death);
  76. ......
  77. binder_proc_dec_tmpref(proc);
  78. }

此处的参数 proc 就是死亡的服务端进程,因为我们关注的是死亡通知的发送,所以我们重点关注 binder_node_release 函数,如下:

  1. static int binder_node_release(struct binder_node *node, int refs)
  2. {
  3. struct binder_ref *ref;
  4. int death = 0;
  5. struct binder_proc *proc = node->proc;
  6. binder_release_work(proc, &node->async_todo);
  7. binder_node_lock(node);
  8. binder_inner_proc_lock(proc);
  9. binder_dequeue_work_ilocked(&node->work);
  10. /*
  11. * The caller must have taken a temporary ref on the node,
  12. */
  13. BUG_ON(!node->tmp_refs);
  14. if (hlist_empty(&node->refs) && node->tmp_refs == 1) {
  15. binder_inner_proc_unlock(proc);
  16. binder_node_unlock(node);
  17. binder_free_node(node);
  18. return refs;
  19. }
  20. node->proc = NULL;
  21. node->local_strong_refs = 0;
  22. node->local_weak_refs = 0;
  23. binder_inner_proc_unlock(proc);
  24. spin_lock(&binder_dead_nodes_lock);
  25. hlist_add_head(&node->dead_node, &binder_dead_nodes);
  26. spin_unlock(&binder_dead_nodes_lock);
  27. hlist_for_each_entry(ref, &node->refs, node_entry) {
  28. // 遍历 node 的引用链表 refs
  29. refs++;
  30. /*
  31. * Need the node lock to synchronize
  32. * with new notification requests and the
  33. * inner lock to synchronize with queued
  34. * death notifications.
  35. */
  36. binder_inner_proc_lock(ref->proc);
  37. if (!ref->death) {
  38. // 如果对应的 binder_ref 的 death 为空,则跳出本次循环继续遍历
  39. binder_inner_proc_unlock(ref->proc);
  40. continue;
  41. }
  42. death++;
  43. BUG_ON(!list_empty(&ref->death->work.entry));
  44. ref->death->work.type = BINDER_WORK_DEAD_BINDER;
  45. // death 不为空,则修改 work type,发送死亡通知
  46. // 并把 work 添加到代理端进程的 todo 队列中
  47. binder_enqueue_work_ilocked(&ref->death->work,
  48. &ref->proc->todo);
  49. // 唤醒代理端进程
  50. binder_wakeup_proc_ilocked(ref->proc);
  51. binder_inner_proc_unlock(ref->proc);
  52. }
  53. binder_debug(BINDER_DEBUG_DEAD_BINDER,
  54. "node %d now dead, refs %d, death %d\n",
  55. node->debug_id, refs, death);
  56. binder_node_unlock(node);
  57. binder_put_node(node);
  58. return refs;
  59. }

该方法会遍历依赖该 binder_node 的所有 binder_ref, 并检查对应的 binder_ref 是否注册过死亡通知,如果注册过,这里表现为 binder_ref 的 death 不为空,则向相应的 binder_ref 所在进程的 todo 队列添加 BINDER_WORK_DEAD_BINDER 事务并唤醒代理端进程执行这个事务。

这个就是死亡通知的触发过程。

四 死亡通知的处理

在前面发送死亡通知后,数据来到了 binder 代理端驱动层的 read 线程中

  1. static int binder_thread_read(struct binder_proc *proc,
  2. struct binder_thread *thread,
  3. binder_uintptr_t binder_buffer, size_t size,
  4. binder_size_t *consumed, int non_block)
  5. {
  6. void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
  7. void __user *ptr = buffer + *consumed;
  8. void __user *end = buffer + size;
  9. int ret = 0;
  10. int wait_for_proc_work;
  11. if (*consumed == 0) {
  12. if (put_user(BR_NOOP, (uint32_t __user *)ptr))
  13. return -EFAULT;
  14. ptr += sizeof(uint32_t);
  15. }
  16. ......
  17.      case BINDER_WORK_DEAD_BINDER:
  18. case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
  19. case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
  20. struct binder_ref_death *death;
  21. uint32_t cmd;
  22. binder_uintptr_t cookie;
  23. // 根据 work 找到对应的 binder_ref_death
  24. death = container_of(w, struct binder_ref_death, work);
  25. if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
  26. cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
  27. else
  28. cmd = BR_DEAD_BINDER; // 添加死亡命令
  29. cookie = death->cookie;
  30. ......
  31. if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
  32. binder_inner_proc_unlock(proc);
  33. kfree(death);
  34. binder_stats_deleted(BINDER_STAT_DEATH);
  35. } else {
  36. // 把 work 添加到 proc 中的 delivered_death 中
  37. binder_enqueue_work_ilocked(
  38. w, &proc->delivered_death);
  39. binder_inner_proc_unlock(proc);
  40. }
  41. // 命令返回到用户空间
  42. if (put_user(cmd, (uint32_t __user *)ptr))
  43. return -EFAULT;
  44. ptr += sizeof(uint32_t);
  45. // 代理对象的地址返回到用户空间
  46. if (put_user(cookie,
  47. (binder_uintptr_t __user *)ptr))
  48. return -EFAULT;
  49. ptr += sizeof(binder_uintptr_t);
  50. binder_stat_br(proc, thread, cmd);
  51. if (cmd == BR_DEAD_BINDER)
  52. goto done;
  53. } break;

数据传递到用户空间处理如下:

  1. status_t IPCThreadState::executeCommand(int32_t cmd)
  2. {
  3. BBinder* obj;
  4. RefBase::weakref_type* refs;
  5. status_t result = NO_ERROR;
  6. switch ((uint32_t)cmd) {
  7. case BR_ERROR:
  8. result = mIn.readInt32();
  9. break;
  10. case BR_OK:
  11. break;
  12. ......
  13.   case BR_DEAD_BINDER:
  14. {
  15. BpBinder *proxy = (BpBinder*)mIn.readPointer();
  16. proxy->sendObituary();
  17. mOut.writeInt32(BC_DEAD_BINDER_DONE);
  18. mOut.writePointer((uintptr_t)proxy);
  19. } break;

从以上代码中可以看到获取 binder 代理对象 proxy 后,然后调用 binder 代理对象的 sendObituary 方法

  1. void BpBinder::sendObituary()
  2. {
  3. ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
  4. this, mHandle, mObitsSent ? "true" : "false");
  5. mAlive = 0;
  6. if (mObitsSent) return; // 驱动已经发送过死亡通知,直接返回
  7. mLock.lock();
  8. Vector<Obituary>* obits = mObituaries;
  9. if(obits != NULL) {
  10. IPCThreadState* self = IPCThreadState::self();
  11. self->clearDeathNotification(mHandle, this); // 注销死亡通知
  12. self->flushCommands();
  13. mObituaries = NULL;
  14. }
  15. mObitsSent = 1; // 标记已经发送过死亡通知
  16. mLock.unlock();
  17. ALOGV("Reporting death of proxy %p for %zu recipients\n",
  18. this, obits ? obits->size() : 0U);
  19. if (obits != NULL) {
  20. const size_t N = obits->size();
  21. for (size_t i=0; i<N; i++) {
  22. // 遍历 mObituaries 中的每个死亡接收通知对象,
  23. // 然后回调该对象的 binderDied 方法
  24. reportOneDeath(obits->itemAt(i));
  25. }
  26. delete obits;
  27. }
  28. }

以上 sendObituary 方法,先检查 mObituaries 是否为空,如果不为空那么注销死亡通知,这个流程在第二部分死亡通知的注销流程一样,然后把 mObitsSent 设置为1,标记驱动已经发送过死亡通知了。最后遍历 mObituaries,对其中的每个对象 Obituary 的 recipient 回调 binderDied 函数,这个函数最终会在代理端实现,作出一些操作,避免发生异常错误

  1. void BpBinder::reportOneDeath(const Obituary& obit)
  2. {
  3. sp<DeathRecipient> recipient = obit.recipient.promote();
  4. ALOGV("Reporting death to recipient: %p\n", recipient.get());
  5. if (recipient == NULL) return;
  6. recipient->binderDied(this);
  7. }

以上就是死亡通知注册,注销,触发和处理的流程

下面讨论下 java 端如何注册使用死亡通知,以及数据是如何传递到 navie 端的。

先看 java 端对应的 Binder 和 BinderProxy 中对死亡通知的注册和注销接口,如下:

  1. public class Binder implements IBinder {
  2. public void linkToDeath(DeathRecipient recipient, int flags) {
  3. }
  4. public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
  5. return true;
  6. }
  7. }
  8. final class BinderProxy implements IBinder {
  9. public native void linkToDeath(DeathRecipient recipient, int flags)
  10. throws RemoteException;
  11. public native boolean unlinkToDeath(DeathRecipient recipient,
  12. int flags);
  13. }

当作为 Binder 服务端,则相应的两个方法实现为空,没有实现具体功能

当作为 BinderProxy 代理端,则调用 native 方法来实现相应功能,这里真正实现了注册和注销的操作。

原因也很好理解,因为注册死亡通知就是 binder 代理端的事情,和 binder 服务端没有关系。

接着看位于 ActivityManagerService 中的 AppDeathRecipient 类,这个类实现了 IBinder 的 DeathRecipient 接口,实现了其中最重要的 binderDied 方法,这个方法最终会被回调

  1. private final class AppDeathRecipient implements IBinder.DeathRecipient {
  2. final ProcessRecord mApp;
  3. final int mPid;
  4. final IApplicationThread mAppThread;
  5. AppDeathRecipient(ProcessRecord app, int pid,
  6. IApplicationThread thread) {
  7. if (DEBUG_ALL) Slog.v(
  8. TAG, "New death recipient " + this
  9. + " for thread " + thread.asBinder());
  10. mApp = app;
  11. mPid = pid;
  12. mAppThread = thread;
  13. }
  14. @Override
  15. public void binderDied() {
  16. if (DEBUG_ALL) Slog.v(
  17. TAG, "Death received in " + this
  18. + " for thread " + mAppThread.asBinder());
  19. synchronized(ActivityManagerService.this) {
  20. appDiedLocked(mApp, mPid, mAppThread, true);
  21. }
  22. }
  23. }

再看 AppDeathRecipient 的注册

  1.     try {
  2. AppDeathRecipient adr = new AppDeathRecipient(
  3. app, pid, thread);
  4. thread.asBinder().linkToDeath(adr, 0);
  5. app.deathRecipient = adr;
  6. } catch (RemoteException e) {
  7. app.resetPackageList(mProcessStats);
  8. startProcessLocked(app, "link fail", processName);
  9. return false;
  10. }

可以看到 new 了一个 AppDeathRecipient,然后通过 binder 代理的 linkToDeath 方法实现对 DeathRecipient 的注册。

这个最终会调用到 jni 层

  1. static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
  2. jobject recipient, jint flags) // throws RemoteException
  3. {
  4. if (recipient == NULL) {
  5. jniThrowNullPointerException(env, NULL);
  6. return;
  7. }
  8. IBinder* target = (IBinder*)
  9. env->GetLongField(obj, gBinderProxyOffsets.mObject);
  10. if (target == NULL) {
  11. ......
  12. assert(false);
  13. }
  14. LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
  15. if (!target->localBinder()) {
  16. DeathRecipientList* list = (DeathRecipientList*)
  17. env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
  18. sp<JavaDeathRecipient> jdr =
  19. new JavaDeathRecipient(env, recipient, list);
  20. // 这个 target 就是 BpBinder 对象
  21. status_t err = target->linkToDeath(jdr, NULL, flags);
  22. if (err != NO_ERROR) {
  23. // Failure adding the death recipient, so clear its reference
  24. // now.
  25. jdr->clearReference();
  26. signalExceptionForError(env,
  27. obj, err, true /*canThrowRemoteException*/);
  28. }
  29. }
  30. }

以上代码中有个 JavaDeathRecipient 对象被注册到 BpBinder 中,从我们之前了解到的,这个应该是一个 DeathRecipient 对象,下面看定义:

  1. class JavaDeathRecipient : public IBinder::DeathRecipient
  2. {
  3. public:
  4. JavaDeathRecipient(JNIEnv* env, jobject object,
  5. const sp<DeathRecipientList>& list)
  6. : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
  7. mObjectWeak(NULL), mList(list)
  8. {
  9. // These objects manage their own lifetimes so are responsible
  10. // for final bookkeeping.
  11. // The list holds a strong reference to this object.
  12. LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
  13. list->add(this);// 将当前对象 sp 添加到列表 DeathRecipientList
  14. android_atomic_inc(&gNumDeathRefs);
  15. incRefsCreated(env);
  16. }
  17. void binderDied(const wp<IBinder>& who)
  18. {
  19. LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
  20. if (mObject != NULL) {
  21. JNIEnv* env = javavm_to_jnienv(mVM);
  22. // 调用 BinderProxy 的 sendDeathNotice 方法
  23. env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
  24. gBinderProxyOffsets.mSendDeathNotice, mObject);
  25. if (env->ExceptionCheck()) {
  26. jthrowable excep = env->ExceptionOccurred();
  27. report_exception(
  28. env, excep,
  29. "*** Uncaught exception returned from death notification!");
  30. }
  31. // Serialize with our containing DeathRecipientList so that we can't
  32. // delete the global ref on mObject while the list is being iterated.
  33. sp<DeathRecipientList> list = mList.promote();
  34. if (list != NULL) {
  35. AutoMutex _l(list->lock());
  36. // Demote from strong ref to weak after binderDied()
  37. // has been delivered, to allow the DeathRecipient and
  38. // BinderProxy to be GC'd if no longer needed.
  39. mObjectWeak = env->NewWeakGlobalRef(mObject);
  40. env->DeleteGlobalRef(mObject);
  41. mObject = NULL;
  42. }
  43. }
  44. }
  45. }

再看 DeathRecipientList

  1. class DeathRecipientList : public RefBase {
  2. List< sp<JavaDeathRecipient> > mList;
  3. Mutex mLock;
  4. public:
  5. DeathRecipientList();
  6. ~DeathRecipientList();
  7. void add(const sp<JavaDeathRecipient>& recipient);
  8. void remove(const sp<JavaDeathRecipient>& recipient);
  9. sp<JavaDeathRecipient> find(jobject recipient);
  10. Mutex& lock();
  11. // Use with care; specifically for mutual exclusion during binder death
  12. };

DeathRecipientList 中存储的是 JavaDeathRecipient 对象。

再回到 android_os_BinderProxy_linkToDeath 函数可以看到,每调用一次 linkToDeath 函数,都会生成一个新的 JavaDeathRecipient 对象,并且保存到 DeathRecipientList 列表中,然后调用 BpBinder 代理对象的 linkToDeath 函数注册这个 JavaDeathRecipient,这样当对应服务端进程死亡的情况下,最终会调用到 JavaDeathRecipient 的 bindeDied方法,在这个方法中会回调 BinderProxy 的 sendDeathNotice 方法,如下:

  1. private static final void sendDeathNotice(DeathRecipient recipient) {
  2. if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
  3. try {
  4. recipient.binderDied();
  5. }
  6. catch (RuntimeException exc) {
  7. Log.w("BinderNative",
  8. "Uncaught exception from death notification", exc);
  9. }
  10. }

最终调用到 recipient 的 binderDied 方法,这个 recipient 就是前面的 AppDeathRecipient。

至此 binder 的死亡通知机制全部阐述完毕,各位读者如有不同意见望不吝指出,感谢感谢。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号