【ActivityManagerService】Android 广播拉起后台进程那些事

  Android 8.0 版本以后,在Manifest中静态注册的广播基本都被禁用了,第三方应用通过AndroidManifest.xml 监听系统广播拉起自身进程的情况被大大抑制,但依然有例外情况:

  • BOOT_COMPLETE 广播可以拉起应用;
  • TIME_SET 广播可以拉起应用;

  安卓官方提供了隐式广播(Implicit Broadcast)例外情况的列表
  本文主要分析广播如何能拉起应用的流程,以便对第三方应用后台静默启动加以管控。

1. Android 系统发送广播流程分析

broadcast.png

  Android系统发送广播的基本流程如上图所示:

  • 客户端进程通过contenxt.sendBroadCast 接口发送广播;具体实现在ContextImpl中;
  • ContextImpl.sendBroadCast 通过AMS的binder 接口,最终调用broadcastIntentLocked方法发送广播。
  • broadcastIntentLocked 是个上千行的复杂方法,基本任务是要确定广播是发送并行广播还是串行广播,并行和串行对应者BroadcastQueue的两个广播队列。
  • 如果接收端是动态注册的广播,默认走并行广播队列,效率高;
  • 否则走ordered 串行广播队列,判断权限,判断是否需要拉起进程;
  • 需要注意的是,客户端不使用contenxt.sendOrderedBroadCast接口,也可能走BroadcastQueue的Ordered broadcast流程。
  • 如果需要实例化客户端进程,BroadcastQueue通过Ams的startProcessLocked接口拉起第三方进程。

2. AMS对隐式广播的限制

  在上述流程中,在 BroadcastQueue.processNextBroadcast 过程中对隐式广播加以限制:

  • 如果广播包含 Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND,直接拒绝发送;
Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND
  • 如果广播不包含接受者信息,并且没有声明为 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,也拒绝发送。
 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
 (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
        || (r.intent.getComponent() == null
            && r.intent.getPackage() == null
            && ((r.intent.getFlags()
                    & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
            && !isSignaturePerm(r.requiredPermissions))) {
    mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
            component.getPackageName());
    Slog.w(TAG, "Background execution not allowed: receiving "
            + r.intent + " to "
            + component.flattenToShortString());
    skip = true;
}

3. AMS对STOPPED_PACKAGE的限制

  PackageManagerService中,对每一个app维护一个stopped标志位,AMS force-stop 强制关闭的应用也会被标记上stopped,应用启动过以后会清除这个标志位。

adb shell am force-stop com.package.name

  AMS对stopped package 也有接收广播的限制。
  AMS 在 broadcastIntentLocked 调用开始,对每一个Intent都设置了FLAG_EXCLUDE_STOPPED_PACKAGES,只有当 FLAG_INCLUDE_STOPPED_PACKAGES 标志也被设置的时候,Intent状态才能生效。

    /**

     * If set, this intent will not match any components in packages that

     * are currently stopped.  If this is not set, then the default behavior

     * is to include such applications in the result.

     */

    public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010;

    /**

     * If set, this intent will always match any components in packages that

     * are currently stopped.  This is the default behavior when

     * {@link #FLAG_EXCLUDE_STOPPED_PACKAGES} is not set.  

If both of these

     * flags are set, this one wins (it allows overriding of exclude for

     * places where the framework may automatically set the exclude flag).

     */

    public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;

IntentFilter 使用如下方法判断是否需要把stopped package排除在外。

    public boolean isExcludingStopped() {

        return (mFlags & 

(FLAG_EXCLUDE_STOPPED_PACKAGES | FLAG_INCLUDE_STOPPED_PACKAGES ) ) == FLAG_EXCLUDE_STOPPED_PACKAGES;

    }
/**

     * Set whether the given package should be considered stopped, making

     * it not visible to implicit intents that filter out stopped packages.

     */

public void setPackageStoppedState(java.lang.String packageName, boolean stopped, int userId) throws android.os.RemoteException;

4. android.intent.action.TIME_SET 广播的发送流程

  AlarmManagerService中的AlarmThread开机启动监控线程,当系统时间变化时,kernel通知此线程发送TIME_SET 广播:

Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                               |Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                               |Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                               |Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);

Intent.FLAG_RECEIVER_REPLACE_PENDING 替换队列中之前的广播
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT BOOT_COMPLETE 之前也注册的receiver也能收到广播
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 后台应用可以被拉起
Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS INSTANT_APPS 可以被拉起。
所以,起作用的是 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 标志。

5. 拉起进程监控

   如果需要监控哪些应用被隐式广播拉起,可以在BroadcastQueue.processNextBroadbroadcast 打点,监控所有通过广播启动的进程。

if ((r.curApp=mService.startProcessLocked(targetProcess,

                    info.activityInfo.applicationInfo, true,

                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,

                    "broadcast",r.curComponent,

              (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))

可以在BroadcastQueue增加打点监控,或者在AMS startProcessLocked增加打点监控。

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