mAllowStartForeground
是否允許后臺啟動前臺Service
// allow the service becomes foreground service? Service started from background may not be
// allowed to become a foreground service.
@PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED;
mAllowStartForeground不等于REASON_DENIED,即被允許
((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ")
mLoggedInfoAllowStartForeground
// Is the same mInfoAllowStartForeground string has been logged before? Used for dedup.
boolean mLoggedInfoAllowStartForeground;
是否相同的前臺Service被允許或者不被允許從后臺啟動的相關(guān)信息已經(jīng)被記錄過尤蒿。
mInfoAllowStartForeground
// Debug info why mAllowStartForeground is allowed or denied.
String mInfoAllowStartForeground;
存儲被拒絕和被允許的相關(guān)信息
isFgsBgStart
/* Reason code range 10-49 are reserved for BG-FGS-launch allowed proc states */
/** @hide */
public static final int REASON_PROC_STATE_PERSISTENT = 10;
/** @hide */
public static final int REASON_PROC_STATE_PERSISTENT_UI = 11;
/** @hide */
public static final int REASON_PROC_STATE_TOP = 12;
/** @hide */
public static final int REASON_PROC_STATE_BTOP = 13;
/** @hide */
public static final int REASON_PROC_STATE_FGS = 14;
/** @hide */
public static final int REASON_PROC_STATE_BFGS = 15;
預(yù)留10-49狀態(tài)碼颅夺,用于標(biāo)記允許后臺啟動前臺Service的進(jìn)程狀態(tài)。
/* Reason code range 50-99 are reserved for BG-FGS-launch allowed reasons */
/** @hide */
public static final int REASON_UID_VISIBLE = 50;
/** @hide */
public static final int REASON_SYSTEM_UID = 51;
/** @hide */
public static final int REASON_ACTIVITY_STARTER = 52;
/** @hide */
public static final int REASON_START_ACTIVITY_FLAG = 53;
/** @hide */
public static final int REASON_FGS_BINDING = 54;
/** @hide */
public static final int REASON_DEVICE_OWNER = 55;
/** @hide */
public static final int REASON_PROFILE_OWNER = 56;
/** @hide */
public static final int REASON_COMPANION_DEVICE_MANAGER = 57;
/**
* START_ACTIVITIES_FROM_BACKGROUND permission.
* @hide
*/
public static final int REASON_BACKGROUND_ACTIVITY_PERMISSION = 58;
/**
* START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
* @hide
*/
public static final int REASON_BACKGROUND_FGS_PERMISSION = 59;
預(yù)留50-99狀態(tài)碼,用于標(biāo)記允許后臺啟動前臺Service的原因。
private static boolean isFgsBgStart(@ReasonCode int code) {
return code != REASON_PROC_STATE_PERSISTENT
&& code != REASON_PROC_STATE_PERSISTENT_UI
&& code != REASON_PROC_STATE_TOP
&& code != REASON_UID_VISIBLE;
}
isFgsBgStart涮瞻,顧名思義,即前臺Service是否是從后臺啟動的假褪。如果參數(shù)code不等于REASON_PROC_STATE_PERSISTENT署咽、不等于REASON_PROC_STATE_PERSISTENT_UI、不等于REASON_PROC_STATE_TOP嗜价、不等于REASON_UID_VISIBLE艇抠,就認(rèn)為是從后臺啟動的。
// Only log if FGS is started from background.
if (!isFgsBgStart(r.mAllowStartForeground)) {
return;
}
前臺Service從后臺啟動的時候久锥,才打印日志信息家淤。
Slog.wtfQuiet
/**
* Similar to {@link #wtf(String, String)}, but does not output anything to the log.
*/
public static void wtfQuiet(@Nullable String tag, @NonNull String msg) {
Log.wtfQuiet(Log.LOG_ID_SYSTEM, tag, msg, true);
}
wtfQuiet與wtf的區(qū)別有兩個地方:
- wtfQuiet是往system日志緩沖區(qū)中寫,wtf是往main日志緩沖區(qū)中寫瑟由。
- wtfQuiet不會輸出wtf的日志絮重,wtf會輸出wtf的日志。
mFgsStartAllowedLogSampleRate
/**
* Sample rate for the allowed FGS start WTF logs.
*
* If the value is 0.1, 10% of the logs would be sampled.
*/
volatile float mFgsStartAllowedLogSampleRate = DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE;
前臺Service被允許從后臺啟動這一事件會被寫到wtf中歹苦,mFgsStartAllowedLogSampleRate管控寫入速度青伤。如果值為0.1,就意味著10%會被記錄殴瘦。
private static final float DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE = 0.25f; // 25%
默認(rèn)25%的wtf會被記錄狠角。
mFgsStartDeniedLogSampleRate
/**
* Sample rate for the denied FGS start WTF logs.
*
* If the value is 0.1, 10% of the logs would be sampled.
*/
volatile float mFgsStartDeniedLogSampleRate = DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE;
前臺Service不被允許從后臺啟動這一事件會被寫到wtf中,mFgsStartDeniedLogSampleRate管控寫入速度蚪腋。如果值為0.1丰歌,就意味著10%會被記錄。
private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%
默認(rèn)100%的wtf會被記錄屉凯。
shouldSamplePackageForAtom
/**
* @return whether a package should be logged, using a random value based on the ANDROID_ID,
* with a given sampling rate.
*/
public static boolean shouldSamplePackageForAtom(String packageName, float rate) {
if (rate <= 0) {
return false;
}
if (rate >= 1) {
return true;
}
final int hash = getUnsignedHashCached(packageName) ^ getAndroidIdHash();
return (((double) hash) / Integer.MAX_VALUE) <= rate;
}
rate如果小于0立帖,則不輸出wtf,如果大于等于1悠砚,則一定會輸出wtf晓勇。后續(xù)算法有點(diǎn)繁雜,就不在這里分析了灌旧。
logFgsBackgroundStart
private void logFgsBackgroundStart(ServiceRecord r) {
// Only log if FGS is started from background.
if (!isFgsBgStart(r.mAllowStartForeground)) {
return;
}
if (!r.mLoggedInfoAllowStartForeground) {
final String msg = "Background started FGS: "
+ ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ")
+ r.mInfoAllowStartForeground;
if (r.mAllowStartForeground != REASON_DENIED) {
if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName,
mAm.mConstants.mFgsStartAllowedLogSampleRate)) {
Slog.wtfQuiet(TAG, msg);
}
Slog.i(TAG, msg);
} else {
if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName,
mAm.mConstants.mFgsStartDeniedLogSampleRate)) {
Slog.wtfQuiet(TAG, msg);
}
Slog.w(TAG, msg);
}
r.mLoggedInfoAllowStartForeground = true;
}
}
- 如果前臺Service從后臺啟動的绑咱,則將相關(guān)信息輸出到日志。
- 輸出到日志的內(nèi)容有兩類枢泰,一類是wtf羡玛,一類是普通的日志。
- 不重復(fù)記錄啟動信息宗苍。