美文网首页Android面试
【ActivityManagerService】Android

【ActivityManagerService】Android

作者: TonyBuilder | 来源:发表于2020-08-19 22:40 被阅读0次

      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增加打点监控。

    相关文章

      网友评论

        本文标题:【ActivityManagerService】Android

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