Android面试

【ActivityManagerService】Android

2020-08-19  本文已影响0人  TonyBuilder

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

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

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

broadcast.png

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

2. AMS对隐式广播的限制

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

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

上一篇下一篇

猜你喜欢

热点阅读