Android logFgsBackgroundStart源码分析

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. 不重复记录启动信息。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容