Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 520|回复: 0

解决Android手机循环重启问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-13 04:18:28 | 显示全部楼层 |阅读模式

    个人原创,转载请注明出处

     

    自毕业以来已经从事两年Android Framewok开发,到如今才积累一点点能够拿出来分享的东西,今天记录一篇关于手机循环重启问题的分析和解决过程。 

    问题描述:

      一部被退回返修的手机,搭载Android N OS,手机开机到出现systemui界面即立刻重启,如此循环往复直至电量耗尽。

    对问题进行合理猜测:

      手机重启一般可以分两大类,

        1 上层重要进程crash,比如system_server进程挂掉,watchdog重启,或者其他进程crash把system_server进程带挂了。

        2 kernel 导致的重启,比如空指针,非法地址等。

      既然能够开机到systemui显示,大体可以先判断为system_server发生了Crash导致手机重启。

      抓log观察一下,这里有必要介绍一点adb shell dumpsys的知识,

      dumpsys activity //查询AMS服务相关信息

      dumpsys window //查询WMS服务相关信息

      dumpsys cpuinfo //查询CPU情况

      dumpsys meminfo //查询内存情况

      比如我经常使用的两个dumpsys命令是:

      adb shell dumpsys activity top 和 adb shell pm path "packageName"

      adb shell dumpsys activity top 命令可以查看当前手机最上层窗口显示界面所属的应用的包名,拿到报名之后就可以通过adb shell pm path "packageName"拿到它的安装目录。

      好了,言归正传,分析手机循环重启问题我们需要用到另一个dumpsys 命令:adb shell dumpsys dropbox -p

      Android dropbox提供了一种保存日志的机制,支持将内核、Native、Java多种日志保存在"/data/system/dropbox"目录中。用以上命令就可以将这种日志提取出来,当然也可以用adb pull /data/system/dropbox提取。此处我们用grep过滤一下log

      adb shell dumpsys dropbox -p | tee log1.txt | grep FATAL

      06-19 09:15:14.858 E/AndroidRuntime( 1170): *** FATAL EXCEPTION IN SYSTEM PROCESS: notification-sqlite-log

      此处注意 "FATAL EXCEPTION IN SYSTEM PROCESS: notification-sqlite-log"

     

      那么打开log1.txt,搜索"FATAL EXCEPTION IN SYSTEM PROCESS: notification-sqlite-log"

    06-19 09:15:14.845 E/SQLiteLog( 1170): (2570) os_unix.c:32626: (13) unlink(/data/system/notification_log.db-journal) -
    06-19 09:15:14.845 E/SQLiteLog( 1170): (2570) disk I/O error
    06-19 09:15:14.830 W/notification-sq( 1396): type=1400 audit(0.0:76): avc: denied { write } for name="system" dev="mmcblk0p27" ino=360449 scontext=u:r:system_server:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0
    06-19 09:15:14.848 D/WifiService( 1170): onReceive, action:android.net.wifi.WIFI_STATE_CHANGED
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): Failed to open database '/data/system/notification_log.db'.
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 2570): , while compiling: PRAGMA journal_mode
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:898)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:643)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:325)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:299)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:220)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:838)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:823)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:716)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:664)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog.writeEvent(NotificationUsageStats.java:1212)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog.-wrap0(NotificationUsageStats.java)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog$1.handleMessage(NotificationUsageStats.java:1065)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.os.Handler.dispatchMessage(Handler.java:110)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.os.Looper.loop(Looper.java:203)
    06-19 09:15:14.857 E/SQLiteDatabase( 1170): at android.os.HandlerThread.run(HandlerThread.java:61)

    06-19 09:15:14.858 E/AndroidRuntime( 1170): *** FATAL EXCEPTION IN SYSTEM PROCESS: notification-sqlite-log
    06-19 09:15:14.858 E/AndroidRuntime( 1170): android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 2570): , while compiling: PRAGMA journal_mode
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:898)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:643)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:325)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:299)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:220)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:838)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:823)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:716)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:664)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog.writeEvent(NotificationUsageStats.java:1212)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog.-wrap0(NotificationUsageStats.java)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at com.android.server.notification.NotificationUsageStats$SQLiteLog$1.handleMessage(NotificationUsageStats.java:1065)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.os.Handler.dispatchMessage(Handler.java:110)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.os.Looper.loop(Looper.java:203)
    06-19 09:15:14.858 E/AndroidRuntime( 1170): at android.os.HandlerThread.run(HandlerThread.java:61)

    注意到进程pid:1170,FATAL EXCEPTION IN SYSTEM PROCESS: notification-sqlite-log,system_server进程在此处Crash了,这也就导致手机循环重启直至电量耗尽。

    再往前看一点,就会发现真正挂掉的原因是Failed to open database '/data/system/notification_log.db'.notification_log.db出现了问题拖死了system_server。

    继续看android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 2570): , while compiling: PRAGMA journal_mode,error code是非常重要的信息,查询一下这个错误码:

    (2570) SQLITE_IOERR_DELETE

    The SQLITE_IOERR_UNLOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error within xDelete method on the sqlite3_vfs object.

    这个error code就证明是文件格式被损坏了,Sqlite在解析数据库文件的时候出现了致命错误。如何证明这个判断呢?我们可以注意到数据库文件所处的路径在/data/system/notification_log.db-journal,也就是本博文贴出的log的第一行:

    06-19 09:15:14.845 E/SQLiteLog( 1170): (2570) os_unix.c:32626: (13) unlink(/data/system/notification_log.db-journal) - 

    我们用正常的文件去替换掉该路径的notification_log.db和notification_log.db-journal就可以证明我的判断,果然是文件损坏,替换文件之后手机就恢复正常了,但是与这个问题相关的代码是谷歌的源码,并且在数据库并发方面做了加锁保护,又是用户退机,没办法找出文件被损坏的根本原因。但是我们可以针对文件损坏做一些保护机制,比如在发生这种循坏重启时五次之后就进入恢复出厂设置模式,或者每隔一段时间对文件进行备份,当出现这种情况是就进行文件替换,将正常的文件拷贝到该目录。

    再多说一点.db-journal文件,这个文件主要用于sqlite事务回滚机制,在事务开始时产生,在事务结束时删除;当程序发生崩溃或者系统断电时该文件将留在磁盘上,以便下次程序运行时进行事务回滚。本身就是一个保护机制,但是不幸的是这个文件格式损坏导致了手机循环重启。至此问题分析总结完毕,真实的分析过程并没有博客中的来的顺利。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-15 10:49 , Processed in 0.063622 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表