Android logFgsBackgroundStart源碼分析

mAllowStartForeground

是否允許后臺(tái)啟動(dòng)前臺(tái)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;

是否相同的前臺(tái)Service被允許或者不被允許從后臺(tái)啟動(dòng)的相關(guān)信息已經(jīng)被記錄過(guò)。

mInfoAllowStartForeground

// Debug info why mAllowStartForeground is allowed or denied.
String mInfoAllowStartForeground;

存儲(chǔ)被拒絕和被允許的相關(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)記允許后臺(tái)啟動(dòng)前臺(tái)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)記允許后臺(tái)啟動(dòng)前臺(tái)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,顧名思義,即前臺(tái)Service是否是從后臺(tái)啟動(dòng)的。如果參數(shù)code不等于REASON_PROC_STATE_PERSISTENT、不等于REASON_PROC_STATE_PERSISTENT_UI、不等于REASON_PROC_STATE_TOP、不等于REASON_UID_VISIBLE,就認(rèn)為是從后臺(tái)啟動(dòng)的。

// Only log if FGS is started from background.
if (!isFgsBgStart(r.mAllowStartForeground)) {
    return;
}

前臺(tái)Service從后臺(tái)啟動(dòng)的時(shí)候,才打印日志信息。

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ū)別有兩個(gè)地方:

  1. wtfQuiet是往system日志緩沖區(qū)中寫,wtf是往main日志緩沖區(qū)中寫。
  2. wtfQuiet不會(huì)輸出wtf的日志,wtf會(huì)輸出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;

前臺(tái)Service被允許從后臺(tái)啟動(dòng)這一事件會(huì)被寫到wtf中,mFgsStartAllowedLogSampleRate管控寫入速度。如果值為0.1,就意味著10%會(huì)被記錄。

private static final float DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE = 0.25f; // 25%

默認(rèn)25%的wtf會(huì)被記錄。

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;

前臺(tái)Service不被允許從后臺(tái)啟動(dòng)這一事件會(huì)被寫到wtf中,mFgsStartDeniedLogSampleRate管控寫入速度。如果值為0.1,就意味著10%會(huì)被記錄。

private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%

默認(rèn)100%的wtf會(huì)被記錄。

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,則一定會(huì)輸出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;
    }
}
  1. 如果前臺(tái)Service從后臺(tái)啟動(dòng)的,則將相關(guān)信息輸出到日志。
  2. 輸出到日志的內(nèi)容有兩類,一類是wtf,一類是普通的日志。
  3. 不重復(fù)記錄啟動(dòng)信息。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容