现象:设备刷机后无法启动,不停重启。
备注:userdebug 版本无问题,user版本才有问题。
分析:
1. user版本无法获取到logcat日志,但是从获取的串口日志如下:
[ 89.217156]|01-01 00:02:50.315 reboot: Restarting system with command 'rescueparty'
可以看到重启原因是 rescueparty
2.需要获取上层日志才能看出原因。但是这时候没有adb,如何获取日志呢?(这个作为遗留问题单独研究)
3.没有日志,这时候只有用最笨的办法:版本切分,看看上层的哪一笔提交引起的呢?
4.最后查到一笔提交,是和三方应用的权限有关,最后确定这笔修改导致了某些三方应用无法启动。
5.从而触发了系统的rescueparty 功能,系统不断重启。
触发条件:
- system_server在5分钟内重启5次以上调整一次救援级别
- 永久性系统应用在30s内崩溃5次以上调整一次级别
相关知识:
这里摘录一下相关rescureparty 功能相关的知识点:
rescueParty功能
rescueParty主要是为了处理当系统无法正常进入系统,当systemserver一直重启 或者 persistent app(守护应用)一直挂掉重启 时,当重启的次数达到一定次数时,rescureParty会发挥作用,rescureParty也分为不同级别,先重置简单设置,如果还是无法正常启动,再重置重要设置,如果还是无法正常启动,最后重启系统进入recovery模式,并且询问用户 是否需要擦除data分区。所有分为4个等级。
rescueParty功能的开启
rescuePart功能的代码路径为:frameworks/base/services/core/java/com/android/server/RescueParty.java
private static boolean isDisabled() { // Check if we're explicitly enabled for testing if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) { return false; } // We're disabled on all engineering devices if (Build.IS_ENG) { Slog.v(TAG, "Disabled because of eng build"); return true; } // We're disabled on userdebug devices connected over USB, since that's // a decent signal that someone is actively trying to debug the device, // or that it's in a lab environment. if (Build.IS_USERDEBUG && isUsbActive()) { Slog.v(TAG, "Disabled because of active USB connection"); return true; } // One last-ditch check if (SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false)) { Slog.v(TAG, "Disabled because of manual property"); return true; } return false; }
1、rescuePart功能的开启 首先要设置 “persist.sys.enable_rescue” 为 true。默认此属性是没有设置的。
2、当编译的是eng版本时,是关闭救援模式的。
3、当编译版本是userdebug,同时插上usb时,是关闭救援模式
4、当设置了 persist.sys.disable_rescue 属性为true时,会关闭救援模式
rescueParty功能的级别
rescueParty 救援模式有分5个级别,每个级别的救援方法不一样:
LEVEL_NONE
LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS
LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES
LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS
LEVEL_FACTORY_RESET
在系统启动时,当systemServer 出现异常,systemServer会重启,systemServer每重启一次,救援级别就会提升一级,每个级别有相对应的救援措施。同样当系统的PersistentApp 挂掉重启时,也是同样救援级别会提升一级。
不同级别的救援措施
不同级别的救援措施
private static void executeRescueLevelInternal(Context context, int level) throws Exception { switch (level) { case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS); break; case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES); break; case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS); break; case LEVEL_FACTORY_RESET: RecoverySystem.rebootPromptAndWipeUserData(context, TAG); break; } }
- 当LEVEL等级 提升1级到LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS时,会调用 resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS) ,会把默认的不信任的Settings的配置重置。
- 当LEVEL等级 提升2级到LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES时,会调用 resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES) ,会把不信任更改了的Settings的配置重置。
- 当LEVEL等级 提升3级到LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS时,会调用 resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS) ,会把默认的信任的Settings的配置重置。
- 当LEVEL等级提升到4级到LEVEL_FACTORY_RESET时,会调用RecoverySystem.rebootPromptAndWipeUserData(context, TAG). 也就是进入Recovery模式。带promptandwipedata命令进入Recovery中,进入后有两个选项供选择,一个立即重启。另一个选项是擦除data分区。可以通过音量上下按键来进行选择。如果是因为data数据导致无法启动,擦除data分区后就可以正常启动了。
总结下,需要进行一些判断是否开启了rescueParty救援模式,如果开启之后,当systerserver或persistentApp 重启时,就是记录一下,同时提升救援等级,每个等级所执行的救援动作不同。最后会进入Recovery模式,用户可以选择擦除data分区来达到救援系统的目的。
部分内容转载自:https://blog.csdn.net/weixin_43215068/article/details/126050825
相关代码分析:https://blog.csdn.net/qq_41818873/article/details/120221844
标签:RESET,rescueParty,救援,LEVEL,UNTRUSTED,context,Android,Settings From: https://www.cnblogs.com/haoran123/p/17769137.html