进入recovery模式分析
frameworks/base/services/java/com/android/server/SystemServer.java305 /**306 * The main entry point from zygote.307 */308 public static void main(String[] args) { 309 new SystemServer().run(); //SystemServer启动开始310 }run方法中执行了java446 try {447 traceBeginAndSlog("StartServices");448 startBootstrapServices(); //启动startBootstrapServices449 startCoreServices();450 startOtherServices();451 SystemServerInitThreadPool.shutdown();452 } catch (Throwable ex) {453 Slog.e("System", "******************************************");454 Slog.e("System", "************ Failure starting system services", ex);455 throw ex;456 } finally {457 traceEnd();458 }
private void startBootstrapServices() {...603 // Now that we have the bare essentials of the OS up and running, take604 // note that we just booted, which might send out a rescue party if605 // we're stuck in a runtime restart loop.606 RescueParty.noteBoot(mSystemContext);//注释解释:操作系统刚刚启动,现在救援机制已经随时待命,如果遇到接下来发生的特殊情况的话。...}
最终会到 这是第一个会造成触救援发机制的原因,
frameworks/base/services/core/java/com/android/server/RescueParty.java
102 /**
103 * Take note of a boot event. If we notice too many of these events
104 * happening in rapid succession, we'll send out a rescue party.
105 */
106 public static void noteBoot(Context context) {107 if (isDisabled()) return;
108 if (sBoot.incrementAndTest()) {109 sBoot.reset();
110 incrementRescueLevel(sBoot.uid);
111 executeRescueLevel(context);
112 }
113 }
另外一个是本次触发救援机制的原因即APPCrash导致。
115 /**
116 * Take note of a persistent app crash. If we notice too many of these
117 * events happening in rapid succession, we'll send out a rescue party.
118 */
119 public static void notePersistentAppCrash(Context context, int uid) {120 if (isDisabled()) return;
121 Threshold t = sApps.get(uid);
122 if (t == null) {123 t = new AppThreshold(uid);
124 sApps.put(uid, t);
125 }
126 if (t.incrementAndTest()) {127 t.reset();
128 incrementRescueLevel(t.uid);
129 executeRescueLevel(context);
130 }
131 }
这两个即https://blog.csdn.net/weixin_33841722/article/details/94650416这篇博客提到的1.system_server 在 5 分钟内重启 5 次以上。2.永久性系统应用在 30 秒内崩溃 5 次以上。下面重点分析第2种 永久性系统应用在 30 秒内崩溃 5 次以上。首先 找到进入该方法的入口
frameworks/base/services/core/java/com/android/server/am/AppErrors.java +:445:442 // If a persistent app is stuck in a crash loop, the device isn't very443 // usable, so we want to consider sending out a rescue party.444 if (r != null && r.persistent) {445 RescueParty.notePersistentAppCrash(mContext, r.uid);//解释为如果一个持久性的应用程序陷入了崩溃循环,那么这个设备就不能很好地使用了,所以我们想考虑派出一个救援队。446 }447
那么何为persistent?源码解释为200 boolean persistent; // always keep this application running?在这里我们可以解释为系统常驻应用,比如systemui,当然还有一些人为增加的保持常驻的应用。到现在可以进入到RescueParty.java本身开始看问题。if (isDisabled()) return; isDisabled()的几种条件。(1) persist.sys.enable_rescue 本身系统没有设值,默认false ,所以得看下面的判断。(2) eng版本默认return true,不会触发救援机制。(3) userdebug 版本并且插入usb状态 return true,不会触发救援机制。(4) persist.sys.disable_rescue 这个值默认也为false ,所以最后return false ,更改这个值为true ,即可关闭触发救援机制。
121 Threshold t = sApps.get(uid);
122 if (t == null) {123 t = new AppThreshold(uid);
124 sApps.put(uid, t);
125 }```java
126 if (t.incrementAndTest()) {127 t.reset();
128 incrementRescueLevel(t.uid);
129 executeRescueLevel(context);
130 }
接下来分别介绍4个方法
1. t.incrementAndTest()
250 /**
251 * @return if this threshold has been triggered
252 */
253 public boolean incrementAndTest() {254 final long now = SystemClock.elapsedRealtime();
255 final long window = now - getStart();
256 if (window > triggerWindow) {257 setCount(1);
258 setStart(now);
259 return false;//持续的时间大于触发窗口的时间即被认定为正常情况
260 } else {261 int count = getCount() + 1; //出现异常情况在上一次事件+1
262 setCount(count); //将事件数量保存在sys.rescue_boot_count ,读也读这个值
263 EventLogTags.writeRescueNote(uid, count, window);
264 Slog.w(TAG, "Noticed " + count + " events for UID " + uid + " in last "
265 + (window / 1000) + " sec");
266 return (count >= triggerCount);//上面我们有提到triggerCount这个值为5 ,在构造函数中固定了这个值,所以当事件累积到5次时会return true
267 }
268 }
269 }
Log:
Line 97942: S02FC4B 08-31 11:33:37.445 3934 11449 W RescueParty: Noticed 2 events for UID 10016 in last 1 sec
Line 99210: S0300DB 08-31 11:33:39.086 3934 4382 W RescueParty: Noticed 3 events for UID 10016 in last 3 sec
Line 100288: S0304D2 08-31 11:33:40.942 3934 6769 W RescueParty: Noticed 4 events for UID 10016 in last 5 sec
Line 102030: S030AAD 08-31 11:33:43.772 3934 11186 W RescueParty: Noticed 5 events for UID 10016 in last 8 secLine 104296: S0312F7 08-31 11:33:47.373 3934 4382 W RescueParty: Noticed 2 events for UID 10016 in last 1 sec
Line 106359: S031AE5 08-31 11:33:49.264 3934 12091 W RescueParty: Noticed 3 events for UID 10016 in last 3 sec
Line 107860: S032093 08-31 11:33:51.229 3934 9042 W RescueParty: Noticed 4 events for UID 10016 in last 5 sec
Line 109329: S0325B6 08-31 11:33:53.377 3934 7285 W RescueParty: Noticed 5 events for UID 10016 in last 7 secLine 111998: S032F58 08-31 11:33:57.584 3934 11501 W RescueParty: Noticed 2 events for UID 10016 in last 2 sec
Line 113602: S0334E6 08-31 11:33:59.478 3934 7285 W RescueParty: Noticed 3 events for UID 10016 in last 4 sec
Line 115201: S033A87 08-31 11:34:02.461 3934 11501 W RescueParty: Noticed 4 events for UID 10016 in last 7 sec
Line 116883: S034098 08-31 11:34:05.734 3934 4106 W RescueParty: Noticed 5 events for UID 10016 in last 10 secLine 119206: S03491B 08-31 11:34:09.965 3934 4906 W RescueParty: Noticed 2 events for UID 10016 in last 1 sec
Line 120468: S034DA1 08-31 11:34:11.946 3934 3945 W RescueParty: Noticed 3 events for UID 10016 in last 3 sec
Line 121787: S03527D 08-31 11:34:13.810 3934 6769 W RescueParty: Noticed 4 events for UID 10016 in last 5 sec
Line 123441: S03584C 08-31 11:34:16.216 3934 4106 W RescueParty: Noticed 5 events for UID 10016 in last 8 sec
2. t.reset();
245 public void reset() {246 setCount(0);//之前累积的释放掉,重置为0
247 setStart(0);
248 }
3. incrementRescueLevel(t.uid);140 /**
141 * Escalate to the next rescue level. After incrementing the level you'll
142 * probably want to call {@link #executeRescueLevel(Context)}.
143 */
144 private static void incrementRescueLevel(int triggerUid) {145 final int level = MathUtils.constrain(
146 SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE) + 1,
147 LEVEL_NONE, LEVEL_FACTORY_RESET);//第一次走进来的时候为1,level 也为1 最多为4 为LEVEL_FACTORY_RESET这个值
148 SystemProperties.set(PROP_RESCUE_LEVEL, Integer.toString(level));//保存level
149
150 EventLogTags.writeRescueLevel(level, triggerUid);
151 logCriticalInfo(Log.WARN, "Incremented rescue level to "
152 + levelToString(level) + " triggered by UID " + triggerUid);
153 }
154 35 public static int constrain(int amount, int low, int high) {36 return amount < low ? low : (amount > high ? high : amount);37 }38
Log:Line 102032: S030AAF 08-31 11:33:43.772 3934 11186 W PackageManager: Incremented rescue level to RESET_SETTINGS_UNTRUSTED_DEFAULTS triggered by UID 10016Line 102033: E030AB0 08-31 11:33:43.772 3934 11186 I pm_critical_info: Incremented rescue level to RESET_SETTINGS_UNTRUSTED_DEFAULTS triggered by UID 10016Line 109332: S0325B9 08-31 11:33:53.379 3934 7285 W PackageManager: Incremented rescue level to RESET_SETTINGS_UNTRUSTED_CHANGES triggered by UID 10016Line 109333: E0325BA 08-31 11:33:53.379 3934 7285 I pm_critical_info: Incremented rescue level to RESET_SETTINGS_UNTRUSTED_CHANGES triggered by UID 10016Line 116885: S03409A 08-31 11:34:05.735 3934 4106 W PackageManager: Incremented rescue level to RESET_SETTINGS_TRUSTED_DEFAULTS triggered by UID 10016Line 116886: E03409B 08-31 11:34:05.735 3934 4106 I pm_critical_info: Incremented rescue level to RESET_SETTINGS_TRUSTED_DEFAULTS triggered by UID 10016Line 123443: S03584E 08-31 11:34:16.217 3934 4106 W PackageManager: Incremented rescue level to FACTORY_RESET triggered by UID 10016Line 123444: E03584F 08-31 11:34:16.217 3934 4106 I pm_critical_info: Incremented rescue level to FACTORY_RESET triggered by UID 10016
4. executeRescueLevel(context);163 private static void executeRescueLevel(Context context) {164 final int level = SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE);
165 if (level == LEVEL_NONE) return;
166
167 Slog.w(TAG, "Attempting rescue level " + levelToString(level));
168 try {169 executeRescueLevelInternal(context, level);//接下来走这个方法
170 EventLogTags.writeRescueSuccess(level);
171 logCriticalInfo(Log.DEBUG,
172 "Finished rescue level " + levelToString(level));
173 } catch (Throwable t) {174 final String msg = ExceptionUtils.getCompleteMessage(t);
175 EventLogTags.writeRescueFailure(level, msg);
176 logCriticalInfo(Log.ERROR,
177 "Failed rescue level " + levelToString(level) + ": " + msg);
178 }
179 }
Log: Line 102038: S030AB5 08-31 11:33:43.774 3934 11186 W RescueParty: Attempting rescue level RESET_SETTINGS_UNTRUSTED_DEFAULTSLine 109334: S0325BB 08-31 11:33:53.380 3934 7285 W RescueParty: Attempting rescue level RESET_SETTINGS_UNTRUSTED_CHANGESLine 116887: S03409C 08-31 11:34:05.736 3934 4106 W RescueParty: Attempting rescue level RESET_SETTINGS_TRUSTED_DEFAULTSLine 123445: S035850 08-31 11:34:16.217 3934 4106 W RescueParty: Attempting rescue level FACTORY_RESETLine 102049: S030AC0 08-31 11:33:43.775 3934 11186 D PackageManager: Finished rescue level RESET_SETTINGS_UNTRUSTED_DEFAULTSLine 102050: E030AC1 08-31 11:33:43.775 3934 11186 I pm_critical_info: Finished rescue level RESET_SETTINGS_UNTRUSTED_DEFAULTSLine 109337: S0325BE 08-31 11:33:53.381 3934 7285 D PackageManager: Finished rescue level RESET_SETTINGS_UNTRUSTED_CHANGESLine 109338: E0325BF 08-31 11:33:53.381 3934 7285 I pm_critical_info: Finished rescue level RESET_SETTINGS_UNTRUSTED_CHANGESLine 116894: S0340A3 08-31 11:34:05.747 3934 4106 D PackageManager: Finished rescue level RESET_SETTINGS_TRUSTED_DEFAULTSLine 116895: E0340A4 08-31 11:34:05.747 3934 4106 I pm_critical_info: Finished rescue level RESET_SETTINGS_TRUSTED_DEFAULTS
180
181 private static void executeRescueLevelInternal(Context context, int level) throws Exception {182 switch (level) {183 case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
184 resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS);//重置数据
185 break;
186 case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
187 resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES);
188 break;
189 case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
190 resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS);
191 break;
192 case LEVEL_FACTORY_RESET:
193 //bug917816 debug system_server/zygote manay times restart question.
194 if (Build.IS_USERDEBUG){195 Slog.w(TAG, "[SPRD_DBG]RescueParty ERROR system again and again reboot!!!");
196 }else{197 RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
198 }
199 break;
200 }
201 }
202
总结:第一次常驻应用发生crash,累积5次会从原来的LEVEL_NONE到LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS (0->1)并且系统做了resetAllSettings,重置了部分数据。第二次常驻应用发生crash,累积5次会从原来的LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS到LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES(1->2)并且系统仍然尝试重置部分数据。第三次常驻应用发生crash,累积5次会从原来的LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES到LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS(2->3)并且系统仍然尝试重置部分数据。第四次常驻应用发生crash,累积5次会从原来的LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS到LEVEL_FACTORY_RESET(3->4)会再次判断是否为userdebug软件,然后进入recovery模式。
进入recovery模式分析相关推荐
- android 系统(154)----OTA制作及升级过程
OTA制作及升级过程 1.概述 1.1 文档概要 前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理解和防止以后遗忘,所以写这篇文档进行一个总结和梳理,以便日后查阅回顾.文 ...
- OTA制作及升级过程笔记
1.概述 1.1 文档概要 前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理解和防止以后遗忘,所以写这篇文档进行一个总结和梳理,以便日后查阅回顾.文档主要包括两部分,第一 ...
- OTA制作及升级过程
OTA制作及升级过程 1.概述 1.1 文档概要 前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理解和防止以后遗忘,所以写这篇文档进行一个总结和梳理,以便日后查阅回顾.文档主 ...
- OTA制作及升级过程笔记【转】
本文转载自:http://www.it610.com/article/5752570.htm 1.概述 1.1 文档概要 前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(一)
这篇及以后的篇幅将通过分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.我们先从update.zip包的制作开始,然后是And ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(一)---update.zip包的制作【转】...
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7399822 这篇及以后的篇幅将通过分析update.zip包在具体Android系统升级的过 ...
- android 4.0 安全模式分析
前言 Android系统中具备6个模式,分别为一般启动模式(normal mode).安全模式(safe mode).恢复模式(recovery mode).引导模式(bootloader mode) ...
- innodb force recovery
innodb force recovery的6种设置: 1.innodb force recovery=1,即使发现了损坏页面也继续让服务器继续运行,这个选项对于备份或者转存当前数据尤为有用 2.in ...
- oracle block media recovery,Oracle非归档模式Media Recovery错误之--ORA-26040
11.转储对应的logfile 14:35:48 SYS@ prod>alter system dump logfile '/dsk1/oradata/prod/redo01a.log': Sy ...
最新文章
- TableView/CollectionView 滑动顶部效果优化
- python读取文件多行内容-Python读取文件、大文件和指定行内容的几种方法
- 继承机制中的构造器和析构器 - C++快速入门17
- 程序员在未来会变成廉价劳动力(农民工)吗?
- CentOS Tomcat6 修改默认端口8080为80
- 百度分享--分享按钮的实现
- 断今天日期和指定日期相等和两者的时间差为两年的sql
- ubuntu mysql 内存满了_Ubuntu mysql可以把data防止到内存盘中
- JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!
- 我发现了一个价值8500美元的 HackerOne 平台漏洞
- MyBaties入门
- android Holo UI框架,Holo风格的开源中国Android客户端——持续更新(2)
- 计算机怎样用PS抠婚纱图,用PS应该怎样抠出透明婚纱照片
- JAVA_调用方法_用户输入姓名打印出欢迎词
- 解决方案:rabbitmq使用场景-超时未支付订单处理
- 樊登读书分享ppt_樊登读书《干法》学习分享
- Centos yum和pip下载离线安装包
- 骁龙855+4800万像素+五大配件,魅族16s开售
- 内存 profile (zz)
- 银行春招:六大行薪资待遇知多少?(下)
热门文章
- 体内有湿气是什么原因?常吃这3种食物,或能帮你祛湿
- (Tekla Structures二次开发)同一图纸中,不同视图中的局部坐标系也不一样
- 蓝湖导出android代码,蓝湖一键生成整页代码,帮开发留住头发
- [4G5G专题-24]:架构-5G接入网协议栈规范
- 2022 IoTDB Summit:阿里白渐《迈向物联网时代大数据计算平台——MaxCompute 基于IoTDB构建解决方案》...
- 不成问题的问题:一个英伟达与另一个英伟达
- 用PyQt实现简单的图片浏览器
- 【国庆篇】用html5简单制作一个国旗
- C4D这10个惊人超实用的功能分享,来学习一下吧
- Python 爬取诗词分析古人最喜欢用的诗词