美文网首页
Android logFgsBackgroundStart源码分

Android logFgsBackgroundStart源码分

作者: 付凯强 | 来源:发表于2024-05-12 21:11 被阅读0次

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被允许或者不被允许从后台启动的相关信息已经被记录过。

mInfoAllowStartForeground

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

存储被拒绝和被允许的相关信息

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;

预留10-49状态码,用于标记允许后台启动前台Service的进程状态。

/* 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;

预留50-99状态码,用于标记允许后台启动前台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是否是从后台启动的。如果参数code不等于REASON_PROC_STATE_PERSISTENT、不等于REASON_PROC_STATE_PERSISTENT_UI、不等于REASON_PROC_STATE_TOP、不等于REASON_UID_VISIBLE,就认为是从后台启动的。

// 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的区别有两个地方:

  1. wtfQuiet是往system日志缓冲区中写,wtf是往main日志缓冲区中写。
  2. 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%

默认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%

默认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。后续算法有点繁杂,就不在这里分析了。

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. 如果前台Service从后台启动的,则将相关信息输出到日志。
  2. 输出到日志的内容有两类,一类是wtf,一类是普通的日志。
  3. 不重复记录启动信息。

相关文章

网友评论

      本文标题:Android logFgsBackgroundStart源码分

      本文链接:https://www.haomeiwen.com/subject/adiufjtx.html