Mark Xu 的博客

记录精彩的程序人生

记一次小米 note3 开机黑屏处理过程

从第一次购买小米的蓝牙音箱,到后面自己以及推荐家人购买小米、红米手机,再到购买路由器、智能摄像头、耳机这些周边产品,自己也慢慢成为了一个米粉。今天下班后,女朋友说她的小米 note3 黑屏死机了,重启无效。顿时对小米略感失望,两千块钱的手机刚用半年而已。想到送到售后八九不离十又是给刷机处理,自己又不想丢失手机内的数据,所以决定自己尝试解决,经过半个多小时成功解决。

症状

首先,说明下手机的症状:开机后显示正常,操作大约 1 分钟左右,黑屏。虚拟按键有效,回到桌面壁纸丢失,显示黑色,桌面触摸无效。

解决

说下解决思路:通过系统 log 定位原因,根据具体原因进行解决。

解决过程:

  • 重启手机,在手机屏幕失灵前,快速操作打开开发者模式、USB 调试开关,方便使用 adb 命令操作手机及查看 log
  • 第一个想到的是系统桌面出现错误,导致触摸失效,之前在原生系统下遇到过类似情况。使用 adb 命令安装第三方桌面并启用后,发现问题依旧存在
  • 既然不是桌面问题,那就看看系统 log 吧。adb 连接电脑后,查看控制台输出,FATAL EXCEPTION 竟然一直在刷,定位到了问题所在。log 如下:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.systemui, PID: 9647
java.lang.RuntimeException: Unable to create service com.android.systemui.SystemUIService: java.lang.IllegalArgumentException: Bad file path: /data/system_ce/0/recent_images/99900699_activity_icon_1536401283653.png passed for userId 999
// 此处省略一些 log
// ...
Caused by: java.lang.IllegalArgumentException: Bad file path: /data/system_ce/0/recent_images/99900699_activity_icon_1536401283653.png passed for userId 999
// 此处省略一些 log
// ...
E/Launcher: 连接Service 失败
// ...

问题很清晰了,systemui 这个进程抛出的运行时异常,导致问题出现。具体下去是由于 /data/system_ce/0/recent_images/99900699_activity_icon_1536401283653.png 这个图片已损坏,这个图片是做什么用的呢?

RecentsActivity

关于 RecentsActivity 的源码分析,可以参考 Android 7.1.2(Android N) SystemUI--Recents Task 加载显示流程 ,以下部分内容摘自该文章。

  • RecentsActivity 是 SystemUI 用于显示最近使用的应用列表,当用户点击 Switch 按键时会启动 RecentsActivity。
  • RecentsActivity 的启动之前有一个 Task 数据的预加载过程,包括 task 的获取、应用缩略图的获取,具体实现在 preloadRecents() 方法中实现。
  • Android 7.0 中,系统会按 userid 保存最近打开应用的 Tasks、Image、Activity-Icon,路径示例如下:
    • 用户 id 为 0 的 Tasks:/data/system_ce/0/recent_tasks/12_task.xml
    • 用户 id 为 0 的 Image:
    • /data/system_ce/0/recent_images/12_task_thumbnail.png
    • 用户 id 为 0 的 Activity-Icon:
    • /data/system_ce/0/recent_images/12_activity_icon_18213511xxxx.png
    • 用户 id 为 0 的所有 tasks-id:/data/system_de/0/persisted_taskIds.txt

因为 Task 的相关信息是保存在 xml 文件中的,所以我们在系统重启后,最近任务中仍可以看到最近打开应用。

  • 其中的 image 缩略图是在 Activity 的 onPause 之后进行截图的

到这里,就明白了原来刚才那个已损坏的图片是最近应用的存储的 Activity-Icon。那么,我们把该应用从最近应用栏移除,不让 RecentsActivity 去加载那个已损坏的图标,问题不就迎刃而解了吗。

再次重启手机,在手机失去控制前,快速划掉所有的最近应用程序,手机不会崩溃了,问题顺利解决。这个问题通过刷机当然也可以解决,但是感觉有些大动干戈,找到问题所在,对症下药,不是更合适吗?

留下你的脚步