Android的自救---RescueParty

前言

不知道你有沒有遇過,就是有時系統開機異常,會直接進入到一個機器人的error界面。我這邊就遇到,在OTA升級後,開機後會自動重啓,且進入到機器人error界面。經查找,是因爲有一個進程在系統開機的時候,不斷重啓,觸發了RescueParty機制,今天在這帶你們稍微瞭解下這個機制。java

RescueParty

目前市場上的消費者包括小白用戶,當他們的手機出現無限循環啓動的異常時,用戶沒有辦法修復異常只能經過設備商售後處理。android

Google在Android 8.0加入該新功能,稱之爲rescue party救援程序。shell

主要監控系統核心程序出現循環崩潰的時候,會啓動該程序,根據不一樣的救援級別作出一系列操做,看是否可恢復設備,最嚴重的時候則是經過進入recovery而後提供用戶清空用戶數據恢復出廠設置解決。api

代碼路徑

frameworks\base\services\core\java\com\android\server\RescueParty.java
複製代碼

救援級別

private static final int LEVEL_NONE = 0;

private static final intLEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1; //主要針對非系統進程的屬性設置進行重置

private static final intLEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2;//針對非系統進程屬性,來自系統默認的屬性重置,其餘刪除

private static final intLEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;//全部進程系統默認的屬性重置,其餘刪除

private static final intLEVEL_FACTORY_RESET = 4; //嘗試恢復出廠設置
複製代碼

觸發場景

(1)system_server 在 5 分鐘內重啓 5 次以上調整一次級別。

(2)永久性系統應用在 30 秒內崩潰 5 次以上調整一次級別。
複製代碼

救援程序的禁用場景

(1)PROP_ENABLE_RESCUE屬性值爲false,而且PROP_DISABLE_RESCUE爲true

(2)eng版本下

(3)手機鏈接usb模式
複製代碼

對外接口

在AppErrors.java的crashApplicationInner方法中加上了RescueParty監控,具體代碼以下:app

void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
int callingPid, int callingUid) {
    ...
	// If a persistent app is stuck in a crash loop, the device isn't very
	// usable, so we want to consider sending out a rescue party.
	if (r != null && r.persistent) {
		RescueParty.notePersistentAppCrash(mContext, r.uid);
	}
	
	AppErrorResult result = new AppErrorResult();
	TaskRecord task;
 	...
}
複製代碼

這裏調用了 RescueParty的notePersistentAppCrash方法,並傳入了Context和進程uid.如今咱們進入方法內部看看:ide

/**
* Take note of a persistent app crash. If we notice too many of these
* events happening in rapid succession, we'll send out a rescue party.
*/
public static void notePersistentAppCrash(Context context, int uid) {
	if (isDisabled()) return;
	Threshold t = sApps.get(uid);
	if (t == null) {
		t = new AppThreshold(uid);
		sApps.put(uid, t);
	}
	if (t.incrementAndTest()) {
		t.reset();
		incrementRescueLevel(t.uid);
		executeRescueLevel(context);
	}
}
複製代碼

番外

當設備具備有效的 USB 數據鏈接時,系統會中止全部救援事件,由於這是一個較強的信號,表示有人正在調試設備。oop

要中止此類抑制行爲,請運行:ui

adb shell setprop persist.sys.enable_rescue 1
複製代碼

查看源碼,可發現,在判斷該機制是否生效的方法中,該屬性被放在最前面,即優先判斷該屬性。spa

在此處,您能夠觸發系統或界面崩潰循環。debug

要觸發低級 system_server 崩潰循環,請運行:

adb shell setprop debug.crash_system 1
複製代碼

要觸發中級 SystemUI 崩潰循環,請運行:

adb shell setprop debug.crash_sysui 1
複製代碼

這兩個崩潰循環都會啓動救援邏輯。全部的救援操做也都會記錄到存儲在 /data/system/uiderrors.txt 中的永久性的 PackageManager 日誌中,以供往後進行檢查和調試。 此外,「軟件包警告消息」部分下的每一個錯誤報告中也會包含這些永久性的日誌。

相關文章
相關標籤/搜索