由一份 log 看 Binder

前言

前段时间调查一个死机重启问题,里面涉及到 Binder 调用的一些比较细节的地方,因此将 binder 调用的整个过程大致缕了一遍,并将所得整理下来。

问题 log

10-17 12:13:02.006  2096  5712 E JavaBinder: *** Uncaught remote exception!  (Exceptions are not yet supported across processes.)
10-17 12:13:02.006  2096  5712 E JavaBinder: java.lang.RuntimeException: Could not copy bitmap to parcel blob.
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.graphics.Bitmap.nativeWriteToParcel(Native Method)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.graphics.Bitmap.writeToParcel(Bitmap.java:1553)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.widget.RemoteViews$BitmapCache.writeBitmapsToParcel(RemoteViews.java:984)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.widget.RemoteViews.writeToParcel(RemoteViews.java:2854)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.app.Notification.writeToParcel(Notification.java:1687)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.service.notification.StatusBarNotification.writeToParcel(StatusBarNotification.java:124)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.service.notification.IStatusBarNotificationHolder$Stub.onTransact(IStatusBarNotificationHolder.java:53)
10-17 12:13:02.006  2096  5712 E JavaBinder:    at android.os.Binder.execTransact(Binder.java:453)
10-17 12:13:02.007  3362 15429 W Binder  : Caught a RuntimeException from the binder stub implementation.
10-17 12:13:02.007  3362 15429 W Binder  : java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.Notification android.service.notification.StatusBarNotification.getNotification()' on a null object reference
10-17 12:13:02.007  3362 15429 W Binder  :  at android.service.notification.NotificationListenerService$INotificationListenerWrapper.onNotificationPosted(NotificationListenerService.java:692)
10-17 12:13:02.007  3362 15429 W Binder  :  at android.service.notification.INotificationListener$Stub.onTransact(INotificationListener.java:71)
10-17 12:13:02.007  3362 15429 W Binder  :  at android.os.Binder.execTransact(Binder.java:453)

下面我们来看一下这段 log 究竟是如何产生的。

一、这样的调用栈是如何产生的?

1. 三个进程

从未贴出的 log 可以看出,这段 log 是在 app 更新或者添加 notification 的过程中产生的,所以我们先看一下更新或添加 notification 的调用流程:
这里写图片描述

点击查看大图

  • 不同的颜色代表不同的进程,红色运行在 app 进程,黑色在 system_server 进程,蓝色在 systemui (也可能是其他注册过的进程)进程
  • 其中涉及到三次跨进程调用,依次为:app 进程调用 system_server 进程的 enqueueNotificationWithTag 方法、system_server 进程调用 systemui 进程的 onNotificationPosted 方法、systemui 进程调用 system_server 进程的 get 方法

第一次跨进程调用很常见,我们就不做讨论了,主要看一下第二、三次跨进程调用是如何实现的。首先,我们需要了解一下 NotificationListener 的注册流程(以 systemui 为例),如下图所示:
这里写图片描述

点击查看大图

  • 其中红色部分运行在 systemui 进程,蓝色部分运行在 system_server 进程
  • StatusBar 的成员 mNotificationListener 是一个 NotificationListenerService 实例,其会调用 registerAsSystemService 方法来进行注册

下面我们来看一下 registerAsSystemService 的实现:

1.1 NotificationListenerService.registerAsSystemService

NotificationListenerService.java


                
Android应用中发生Binder资源不足的情况时,通常会在系统的日志(Logcat)中看到相关的错误信息。这通常表现为`ActivityManager$RunningAppProcessError`异常,提示类似于`Application Not Responding`、`Insufficient memory for binding`等。具体日志可能如下: ``` W/InputDispatcher(459): channel 'com.example.app/com.example.app.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9 E/WindowManager(459): Activity com.example.app.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView@67a34d7 that was originally added here W/System.err(459): android.view.WindowLeaked: Activity com.example.app.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView@67a34d7 that was originally added here W/System.err(459): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:385) W/System.err(459): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299) W/System.err(459): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:92) W/System.err(459): at android.app.Dialog.show(Dialog.java:293) W/System.err(459): at com.example.app.MainActivity.onCreateDialog(MainActivity.java:xxx) W/System.err(459): at com.example.app.MainActivity.onOptionsItemSelected(MainActivity.java:yyy) W/System.err(459): at android.app.Activity.onMenuItemSelected(Activity.java:2969) W/System.err(459): ... 30 more ``` 这种错误通常是因为进程内存不足,导致无法创建新的Binder连接。开发者应该检查是否有大量耗内存的操作,比如持有过多的对象引用、网络请求延迟处理不当、大量的数据库操作等,并及时释放不再需要的资源,优化内存管理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值