zoukankan      html  css  js  c++  java
  • Broadcast 源码笔记

    Note

    所有涉及到多用户操作的代码,我们都假设系统只有一个用户,就是 SYSTEM用户,对应的 UserID == USER_SYSTEM ==0

    注册广播

    APP registerReceiver

    时序图如下:

    registerReceiver时序图

    IIntentReceiver是什么?它的作用是啥?如何被构建出来的?

    Broadcast

    IIntentReceiver是一个Binder对象,通过AM@registerReceiver将其注册到AMS中,这样AMS就持有一个IIntentReceiver的代理Binder对象,当有应用发送广播时,就会调用其performReceive方法。进而完成广播传递的过程。

    注册过程,代码如下:

    //frameworks/base/core/java/android/app/ContextImpl.java
    
    // 注册一个广播接收器
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }
    
    // scheduler 表示指定一个Handler执行 onReceiver 方法。
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler/*null*/) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext(), 0);
    }
    
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler, int flags /*0*/) {
        return registerReceiverInternal(receiver, getUserId(),
                 filter, broadcastPermission, scheduler, getOuterContext(), flags);
    }
    
    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission /*null*/,
            Handler scheduler /*null*/, Context context, int flags/*0*/) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    //[1]  registerReceiver 注册的 BroadcastReceiver 默认运行在 UI线程
                    scheduler = mMainThread.getHandler();
                }
                //[2] 获取IIntentReceiver对象
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                // 什么时候会执行到这里呢???
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
            // 注册到AMS
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        }
    }
    

    rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler,mMainThread.getInstrumentation(), true);对应的流程如下:

    1. LoadedApk@getReceiverDispatcher

      public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
              Context context, Handler handler,
              Instrumentation instrumentation, boolean registered) {
          synchronized (mReceivers) {
              LoadedApk.ReceiverDispatcher rd = null;
              ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
              if (registered) {
                  //首先根据 context 找到对应的 map
                  map = mReceivers.get(context);
                  if (map != null) {
                      // 第二次注册时,直接获取已有的ReceiverDispatcher
                      rd = map.get(r);
                  }
              }
              if (rd == null) {
                  // 首次注册,创建一个新的  ReceiverDispatcher
                  rd = new ReceiverDispatcher(r, context, handler,
                          instrumentation, registered);
                  if (registered) {
                      if (map == null) {
                          // 首次注册
                          map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                          mReceivers.put(context, map);
                      }
                      map.put(r, rd);
                  }
              } else {
                  rd.validate(context, handler);
              }
              rd.mForgotten = false;
              // IntentReceiver是 ReceiverDispatcher的 static nested class, 其构造在  ReceiverDispatcher的 的构造函数中完成。
              return rd.getIIntentReceiver();
          }
      }
      
    2. new ReceiverDispatcher

      ReceiverDispatcher(BroadcastReceiver receiver, Context context,
              Handler activityThread, Instrumentation instrumentation,
              boolean registered) {
      	// 在这里构建
          mIIntentReceiver = new InnerReceiver(this, !registered);
          mReceiver = receiver;
          mContext = context;
          mActivityThread = activityThread;		// UI线程
          mInstrumentation = instrumentation;
          mRegistered = registered;
          mLocation = new IntentReceiverLeaked(null);
          mLocation.fillInStackTrace();
      }
      
    3. InnerReceiver

      InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
          mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
          mStrongRef = strong ? rd : null;
      }
      

      strong == false,所以InnerReceiver内部持有了ReceiverDispatcher的一个弱引用。

    AMS registerReceiver

    注册流程

    注册广播的逻辑比较简单,主要流程就时将IIntentReceiverReceiverList添加到AMS@mRegisteredReceivers中。此外还对粘性广播进行了处理,Sticky Broadcast已经被安卓Deprecated,所以这里不做分析,只在代码里注释一下。

    registerBroadcast

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) 
        ArrayList<Intent> stickyIntents = null;
        synchronized(this) {
            // 获取 注册端 IntentFilter 中的 Action
            Iterator<String> actions = filter.actionsIterator();
            if (actions == null) {
                ArrayList<String> noAction = new ArrayList<String>(1);
                noAction.add(null);
                actions = noAction.iterator();
            }
    
            // Collect stickies of users
            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
            while (actions.hasNext()) {
                String action = actions.next();
                for (int id : userIds) {
                    // mStickyBroadcasts 记录了系统中的 所有粘性广播,
                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                    if (stickies != null) {
                        ArrayList<Intent> intents = stickies.get(action);
                        if (intents != null) {
                            if (stickyIntents == null) {
                                stickyIntents = new ArrayList<Intent>();
                            }
                            stickyIntents.addAll(intents);
                        }
                    }
                }
            }
        }
    
        ArrayList<Intent> allSticky = null;
        if (stickyIntents != null) {
            final ContentResolver resolver = mContext.getContentResolver();
            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                Intent intent = stickyIntents.get(i);
                // 粘性广播和当前注册的接收器匹配,就加入到  allSticky 中,
                if (filter.match(resolver, intent, true, TAG) >= 0) {
                    if (allSticky == null) {
                        allSticky = new ArrayList<Intent>();
                    }
                    allSticky.add(intent);
                }
            }
        }
    
        // The first sticky in the list is returned directly back to the client.
        Intent sticky = allSticky != null ? allSticky.get(0) : null;
        if (receiver == null) {
            return sticky;
        }
    
        synchronized (this) {
            // 首次注册,必定为null
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                // 创建一个 ReceiverList
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    // APP 注册的接收器限制
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
                    rl.app.receivers.add(rl);
                } else {
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                //系统所有的 接收器都保存在mRegisteredReceivers里面
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
            
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
                Slog.w(TAG, "Receiver with filter " + filter
                        + " already registered for pid " + rl.pid
                        + ", callerPackage is " + callerPackage);
            } else {
                // ReceiverList 继承了ArrayList,一个receiver可以对应多个 filter,
                // 这里ArrayList 就保存了 于receiver 对应的多个 filter
                rl.add(bf);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
                
                // 暂时不清楚,,,
                mReceiverResolver.addFilter(bf);
            }
    		// 到这里,注册流程基本上就走完了。。。。
            
            // Enqueue broadcasts for all existing stickies that match
            // this filter.
            if (allSticky != null) {  // 有粘性广播需要发送
                ArrayList receivers = new ArrayList();
                receivers.add(bf);
    
                final int stickyCount = allSticky.size();
                for (int i = 0; i < stickyCount; i++) {
                    Intent intent = allSticky.get(i);
                    // 获取 intent 对应的 BroadcastQueue
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                            null, -1, -1, false, null, null, OP_NONE, null, receivers,
                            null, 0, null, null, false, true, true, -1, false,
                            false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
                    // 加入到无序广播队列中,
                    queue.enqueueParallelBroadcastLocked(r);
                    // 异步执行广播发送操作,对应的操作线程是 ServiceThread。
                    queue.scheduleBroadcastsLocked();
                }
            }
    
            return sticky;
        }
    }
    

    总结

    1. 使用registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 注册的BroadcastReceiver默认运行在UI线程中。

    2. ProcessRecord中记录这当前进程已经注册的广播接收器的数量,每个进程的都有接收器的数量限制,大小是MAX_RECEIVERS_ALLOWED_PER_APP

      //frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
      // Maximum number of receivers an app can register.
      private static final int MAX_RECEIVERS_ALLOWED_PER_APP = 1000;
      
    3. registerReceiver的返回值时注册时匹配的一个粘性广播对应的Intent,如果没有粘性广播,就返回null

    4. 关键类关键成员变量

    发送广播

    APP snedBroadcast

    ContextImpl中,有多个发送广播的方法:

    public void sendBroadcast(Intent intent);
    public void sendOrderedBroadcast(Intent intent, String receiverPermission);
    @Deprecated
    public void sendStickyBroadcast(Intent intent);
    

    这里省略了大量的不同参数的发送方法,归根节点,不管是无序广播、有序广播还是粘性广播最终都是调用到AMS@broadcastIntent中。

    // frameworks/base/core/java/android/app/IActivityManager.aidl
    @UnsupportedAppUsage
    int broadcastIntent(in IApplicationThread caller, in Intent intent,
                in String resolvedType, in IIntentReceiver resultTo, int resultCode,
                in String resultData, in Bundle map, in String[] requiredPermissions,
                int appOp, in Bundle options, boolean serialized, boolean sticky, int userId);
    

    三种广播的类型由serializedsticky共同决定:

    方法 serialized sticky
    sendBroadcast false false
    sendOrderedBroadcast true false
    sendStickyBroadcast false true

    AMS broadcastIntentLocked

    AMS 处理广播的流程大概如下图

    sendBroadcast

    主要工作包括:

    1. 处理系统广播
    2. 针对不同类型(粘性广播、有序广播和无序广播)的广播进行处理。

    发送流程

    1. 细节处理
    1. Instant APP 不能接收到广播。

    2. 为每一个Intnet默认加上 FLAG_EXCLUDE_STOPPED_PACKAGES,防止流氓应用通过监听系统广播自启动。

    3. 系统处于开关机过程中时,只允许动态注册的接收器接收广播。

    4. BroadcastOptions

    5. 受限广播只允许 系统应用发送。

      所谓受限广播,即系统应用在 AndroidManifest.xml中使用 protected-broadcast声明的广播。

      参考

    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    final int broadcastIntentLocked(...) {
        intent = new Intent(intent);
    	// [1]
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        if (callerInstantApp) {
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }
    	// [2]
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
    
        //[3]
        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        }
    	
    	// [4] 暂时不清楚其作用
        final String action = intent.getAction();
        BroadcastOptions brOptions = null;
        if (bOptions != null) {
            brOptions = new BroadcastOptions(bOptions);
            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
                
                if (checkComponentPermission(
                        android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Permission Denial: " + intent.getAction()
                            + " broadcast from " + callerPackage + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires "
                            + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                }
            }
            if (brOptions.isDontSendToRestrictedApps()
                    && !isUidActiveLocked(callingUid)
                    && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
                Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
                        + " has background restrictions");
                return ActivityManager.START_CANCELED;
            }
            if (brOptions.allowsBackgroundActivityStarts()) {
                
                if (checkComponentPermission(
                        android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Permission Denial: " + intent.getAction()
                            + " broadcast from " + callerPackage + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires "
                            + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                } else {
                    allowBackgroundActivityStarts = true;
                }
            }
        }
    
        // [5] 
        final boolean isProtectedBroadcast;
        try {
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", e);
            return ActivityManager.BROADCAST_SUCCESS;
        }
    
        final boolean isCallerSystem;
        switch (UserHandle.getAppId(callingUid)) {
            case ROOT_UID:
            case SYSTEM_UID:
            case PHONE_UID:
            case BLUETOOTH_UID:
            case NFC_UID:
            case SE_UID:
            case NETWORK_STACK_UID:
                isCallerSystem = true;
                break;
            default:
                isCallerSystem = (callerApp != null) && callerApp.isPersistent();
                break;
        }
    
        // First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
        if (!isCallerSystem) {
            // 非系统用户不允许发送受限广播
            if (isProtectedBroadcast) {
                String msg = "Permission Denial: not allowed to send broadcast "
                        + action + " from pid="
                        + callingPid + ", uid=" + callingUid;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
    		// 其余广播也有两个特例,不允许被非系统用户调用。作用不晓得。
            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
                if (callerPackage == null) {
                    String msg = "Permission Denial: not allowed to send broadcast "
                            + action + " from unknown caller.";
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                } else if (intent.getComponent() != null) {
                    if (!intent.getComponent().getPackageName().equals(
                            callerPackage)) {
                        String msg = "Permission Denial: not allowed to send broadcast "
                                + action + " to "
                                + intent.getComponent().getPackageName() + " from "
                                + callerPackage;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                } else {
                    // Limit broadcast to their own package.
                    intent.setPackage(callerPackage);
                }
            }
        }
        ...
    }
    
    2. 隐式广播处理

    隐式广播

    1. 针对于静态注册的广播接收器
    2. 没有明确指定 包名或者一些关键信息的广播

    就是我们在platform.xml中,使用allow-implicit-broadcast声明的广播。这样的广播能够被隐式静态注册的接收器接收。

    // 通过pms 获取 隐式广播s
    if (getBackgroundLaunchBroadcasts().contains(action)) {
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
    }
    
    3. 处理系统广播
    switch (action) {
                case Intent.ACTION_UID_REMOVED:
                case Intent.ACTION_PACKAGE_REMOVED:
                case Intent.ACTION_PACKAGE_CHANGED:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
                case Intent.ACTION_PACKAGES_SUSPENDED:
                case Intent.ACTION_PACKAGES_UNSUSPENDED:
    	...
    }
    
    4. 处理粘性广播
    • 受限判断进程是否有权限发送粘性广播
    • 将广播添加到粘性广播队列mStickyBroadcasts中。
    // Add to the sticky list if requested.
    if (sticky) {
        if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
                callingPid, callingUid)
                != PackageManager.PERMISSION_GRANTED) {
            String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
                    + callingPid + ", uid=" + callingUid
                    + " requires " + android.Manifest.permission.BROADCAST_STICKY;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        if (requiredPermissions != null && requiredPermissions.length > 0) {
            return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
        }
        if (intent.getComponent() != null) {
            throw new SecurityException(
                    "Sticky broadcasts can't target a specific component");
        }
        if (userId != UserHandle.USER_ALL) {
            // 不允许和USER_ALL 对应的重复
            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                    UserHandle.USER_ALL);
            if (stickies != null) {
                ArrayList<Intent> list = stickies.get(intent.getAction());
                if (list != null) {
                    int N = list.size();
                    int i;
                    for (i=0; i<N; i++) {
                        if (intent.filterEquals(list.get(i))) {
                            throw new IllegalArgumentException(
                                    "Sticky broadcast " + intent + " for user "
                                    + userId + " conflicts with existing global broadcast");
                        }
                    }
                }
            }
        }
        // 添加
        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
        if (stickies == null) {
            stickies = new ArrayMap<>();
            mStickyBroadcasts.put(userId, stickies);
        }
        ArrayList<Intent> list = stickies.get(intent.getAction());
        if (list == null) {
            list = new ArrayList<>();
            stickies.put(intent.getAction(), list);
        }
        final int stickiesCount = list.size();
        int i;
        for (i = 0; i < stickiesCount; i++) {
            if (intent.filterEquals(list.get(i))) {
                // This sticky already exists, replace it.
                list.set(i, new Intent(intent));
                break;
            }
        }
        if (i >= stickiesCount) {
            list.add(new Intent(intent));
        }
    }
    
    5. 获取广播接收器

    这里的广播接收器是指 其IntentFilter 和 Intent 匹配上了的

    • 获取动态注册的广播接收器保存在 registeredReceivers
    • 获取静态注册的广播接收器保存在receivers
    // Figure out who all will receive this broadcast.
    List receivers = null;  // 静态注册
    List<BroadcastFilter> registeredReceivers = null;
    // Need to resolve the intent to interested receivers...
    if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
             == 0) { // 获取静态注册的广播接收器
        receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
    }
    if (intent.getComponent() == null) {
        if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
            // Query one target user at a time, excluding shell-restricted users
            for (int i = 0; i < users.length; i++) {
                if (mUserController.hasUserRestriction(
                        UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                    continue;
                }
                List<BroadcastFilter> registeredReceiversForUser =
                        mReceiverResolver.queryIntent(intent,
                                resolvedType, false /*defaultOnly*/, users[i]);
                if (registeredReceivers == null) {
                    registeredReceivers = registeredReceiversForUser;
                } else if (registeredReceiversForUser != null) {
                    registeredReceivers.addAll(registeredReceiversForUser);
                }
            }
        } else {  // userId == 0
            // 动态注册的,前面通过registerReceiver 注册的接收器都保存一份在  mReceiverResolver中。
            registeredReceivers = mReceiverResolver.queryIntent(intent,
                    resolvedType, false /*defaultOnly*/, userId);
        }
    }
    

    collectReceiverComponents从PMS 获取 相关信息,这里暂时忽略。

    6. 处理无序广播

    这里,将无序广播先发送给期望接收该广播的动态注册的广播接收器。需要注意的就是进入这段代码后,NR == 0

    // 替换已经存在还没有发送的广播?
    final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    if (!ordered && NR > 0) {
        // If we are not serializing this broadcast, then send the
        // registered receivers separately so they don't wait for the
        // components to be launched.
        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, registeredReceivers);
        }
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                allowBackgroundActivityStarts, timeoutExempt);
        
        final boolean replaced = replacePending
                && (queue.replaceParallelBroadcastLocked(r) != null);
        // Note: We assume resultTo is null for non-ordered broadcasts.
        if (!replaced) {
            queue.enqueueParallelBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }
    
    7. 处理有序广播

    如果是有序广播,就将满足的广播接收器合并,合并过程中同时按照优先级大小排序。

    // Merge into one list.
    int ir = 0;
    if (receivers != null) {
        String skipPackages[] = null;
        if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
            Uri data = intent.getData();
            if (data != null) {
                String pkgName = data.getSchemeSpecificPart();
                if (pkgName != null) {
                    skipPackages = new String[] { pkgName };
                }
            }
        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
            skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
        }
        if (skipPackages != null && (skipPackages.length > 0)) {
            for (String skipPackage : skipPackages) {
                if (skipPackage != null) {
                    int NT = receivers.size();
                    for (int it=0; it<NT; it++) {
                        ResolveInfo curt = (ResolveInfo)receivers.get(it);
                        if (curt.activityInfo.packageName.equals(skipPackage)) {
                            receivers.remove(it);
                            it--;
                            NT--;
                        }
                    }
                }
            }
        }
    
        int NT = receivers != null ? receivers.size() : 0;
        int it = 0;
        ResolveInfo curt = null;
        BroadcastFilter curr = null;
        while (it < NT && ir < NR) {
            if (curt == null) {
                curt = (ResolveInfo)receivers.get(it);
            }
            if (curr == null) {
                curr = registeredReceivers.get(ir);
            }
            if (curr.getPriority() >= curt.priority) {
                // Insert this broadcast record into the final list.
                receivers.add(it, curr);
                ir++;
                curr = null;
                it++;
                NT++;
            } else {
                // Skip to the next ResolveInfo in the final list.
                it++;
                curt = null;
            }
        }
    }
    
    8. 发送广播

    和第六步相似,都是将BroadcastRecord放入到对应得BroadcastQueue中。

    一个疑问,无序广播前面只转发给静态注册的广播接收器,走到下面的代码,都通过enqueueOrderedBroadcastLocked放到了有序队列中???

    // 无序广播 NR = 0
    // 有序广播 ir < NR 说明 registeredReceivers中海 NR - ir个没有合并。
    while (ir < NR) {
            if (receivers == null) {
                receivers = new ArrayList();
            }
            receivers.add(registeredReceivers.get(ir));
            ir++;
        }
    
        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, receivers);
        }
    
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, timeoutExempt);
    
            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);
    
                    }
                }
            } else {
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // There was nobody interested in the broadcast, but we still want to record
            // that it happened.
            if (intent.getComponent() == null && intent.getPackage() == null
                    && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
            }
        }
    
        return ActivityManager.BROADCAST_SUCCESS;
    }
    

    整个流程比较简单,就是逻辑有点多,接下来分析的重点有如下几个:

    1. broadcastQueueForIntent
    2. BroadcastQueue.performReceiveLocked
    3. BroadcastQueue@enqueueOrderedBroadcastLocked && BroadcastQueue@enqueueParallelBroadcastLocked
    4. BroadcastQueue@scheduleBroadcastsLocked

    总结

    1. AMS默认会为每一个广播加上Intent.FLAG_EXCLUDE_STOPPED_PACKAGES标志,防止流氓应用通过监听系统广播实现自启动。

    BroadcastQueue -- 实际的分发操作

    frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

    初始化

    AMS中持有两个广播对列(foreground 和 background),这两个广播对列在 AMS 的构造函数中完成初始化操作。

    对应 Intent.FLAG_RECEIVER_FOREGROUND . 广播包含该标记就放入到 mFgBroadcastQueue中,否则放入到mBgBroadcastQueue中。

    BroadcastQueue broadcastQueueForIntent(Intent intent) {
        final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
        return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
    }
    
    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    static final int BROADCAST_FG_TIMEOUT = 10*1000;
    static final int BROADCAST_BG_TIMEOUT = 60*1000;
    
    BroadcastQueue mFgBroadcastQueue;    
    BroadcastQueue mBgBroadcastQueue;
    
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", BROADCAST_BG_TIMEOUT, true);
    

    其中,mHandler对应的就是 AMS 的 ServiceThread

    // frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
    BroadcastQueue(ActivityManagerService service, Handler handler,
            String name, long timeoutPeriod, boolean allowDelayBehindServices) {
        mService = service;
        mHandler = new BroadcastHandler(handler.getLooper());
        mQueueName = name;
        mTimeoutPeriod = timeoutPeriod;
        mDelayBehindServices = allowDelayBehindServices;
    }
    

    1. enqueueParallelBroadcastLocked && enqueueParallelBroadcastLocked

    BroadcastQueue内部存在两个广播ArrayList,一个用于记录 无序广播(使用enqueueParallelBroadcastLocked ),一个用于记录有序广播(使用enqueueParallelBroadcastLocked)。

    /**
     * Lists of all active broadcasts that are to be executed immediately
     * (without waiting for another broadcast to finish).  Currently this only
     * contains broadcasts to registered receivers, to avoid spinning up
     * a bunch of processes to execute IntentReceiver components.  Background-
     * and foreground-priority broadcasts are queued separately.
     */
    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
    
    /**
     * List of all active broadcasts that are to be executed one at a time.
     * The object at the top of the list is the currently activity broadcasts;
     * those after it are waiting for the top to finish.  As with parallel
     * broadcasts, separate background- and foreground-priority queues are
     * maintained.
     */
    final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
    
    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        mParallelBroadcasts.add(r);
        /*调试用*/
        enqueueBroadcastHelper(r);
    }
    
    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        mOrderedBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }
    

    2. scheduleBroadcastsLocked

    在将广播放入到队列后,会执行scheduleBroadcastsLocked函数。

    public void scheduleBroadcastsLocked() {
        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }
    

    前面说过了,mHandler对应的执行线程就是AMS@ServiceThread。所以我们要保证对BROADCAST_INTENT_MSG的处理不能超时。

    private final class BroadcastHandler extends Handler {
        public BroadcastHandler(Looper looper) {
            super(looper, null, true);
        }
    
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }
    

    关键点就是 processNextBroadcast了。

    3. processNextBroadcast

    分几种情况:

    1. 无序广播的发送
    2. 有序广播的发送
    3. 对于含有FLAG_INCLUDE_STOPPED_PACKAGES标记广播的特殊处理。

    无序广播发送

    遍历mParallelBroadcasts,逐个拿到BroadcastRecord,然后遍历BroadcastRecord里面的接收器BroadcastFilter,最后调用deliverToRegisteredReceiverLocked完成广播交付操作。

    // 交付所有无序广播
    while (mParallelBroadcasts.size() > 0) {
        r = mParallelBroadcasts.remove(0);
        r.dispatchTime = SystemClock.uptimeMillis();
        r.dispatchClockTime = System.currentTimeMillis();
        final int N = r.receivers.size();
       
        for (int i=0; i<N; i++) {
            Object target = r.receivers.get(i);
            deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
        }
        addBroadcastToHistoryLocked(r);
    }
    

    有序广播发送

    有序广播发送逻辑处理比较复杂,应用程序可以在onReceive方法中还是用abortBroadcast终止当前广播的往下一个接收器交付。具体的逻辑流程如下:

    boolean looped = false;
    // 有序广播
    do {
        if (mOrderedBroadcasts.size() == 0) {      
            // No more broadcasts pending, so all done!
            mService.scheduleAppGcsLocked();
            if (looped) {
                mService.updateOomAdjLocked();
            }
             // 所有有序广播都处理了, 直接返回
            return;
        }
        // 获取第一个有序广播,
        r = mOrderedBroadcasts.get(0);              
        boolean forceReceive = false;  
    	// 获取第一个广播对应的接收器的数量
        int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
        if (mService.mProcessesReady && r.dispatchTime > 0) {
            long now = SystemClock.uptimeMillis();
            // 超时时间就是接受的广播器的数量 * 2 * 10
            if ((numReceivers > 0) &&  (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) { 
                broadcastTimeoutLocked(false); // forcibly finish this broadcast
                forceReceive = true;            // 分发超时
                r.state = BroadcastRecord.IDLE;
            }
        }
    	// 不太清楚什么时候会出现该情况
        if (r.state != BroadcastRecord.IDLE) {
            if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
                    "processNextBroadcast("
                    + mQueueName + ") called when not idle (state="
                    + r.state + ")");
            return;
        }
    	
        // 最后一个广播分发结束、 超时、abortBroadcast被调用
        if (r.receivers == null || r.nextReceiver >= numReceivers
                || r.resultAbort || forceReceive) {
            
            // sendOrderBroadcast中可以传入一个 BroadcastReceiver对象,当有序广播 结束分发时(无论正确与否),都会通知广播发送端。
            if (r.resultTo != null) {
                performReceiveLocked(r.callerApp, r.resultTo,
                        new Intent(r.intent), r.resultCode,
                        r.resultData, r.resultExtras, false, false, r.userId);
                r.resultTo = null;
            }
            // ... and on to the next...
            addBroadcastToHistoryLocked(r);
            if (r.intent.getComponent() == null && r.intent.getPackage() == null
                    && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                        r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
            }
            // 第一个已经处理完了,移除
            mOrderedBroadcasts.remove(0);
            r = null;
            looped = true;
            continue;
        }
    } while (r == null);
    
    // Get the next receiver...
    int recIdx = r.nextReceiver++;   
    
    // Keep track of when this receiver started, and make sure there
    // is a timeout message pending to kill it if need be.
    r.receiverTime = SystemClock.uptimeMillis();
    if (recIdx == 0) {
        r.dispatchTime = r.receiverTime;  //记录一个接收器分发时间,改时间需要用于超时判断
        r.dispatchClockTime = System.currentTimeMillis();
    }
    if (! mPendingBroadcastTimeoutMessage) {
        long timeoutTime = r.receiverTime + mTimeoutPeriod;
        setBroadcastTimeoutLocked(timeoutTime);
    }
    
    final BroadcastOptions brOptions = r.options;
    final Object nextReceiver = r.receivers.get(recIdx); // 当前的接收器,按照优先级从大到小
    
    if (nextReceiver instanceof BroadcastFilter) {
        BroadcastFilter filter = (BroadcastFilter)nextReceiver;
        //交付有序广播
        deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
    
        // r.receiver == null 表示 binder RPC过程中出现错误,
        // !r.ordered?
        if (r.receiver == null || !r.ordered) {  // 对端没有正确接收到广播,
            // The receiver has already finished, so schedule to
            // process the next one.
            r.state = BroadcastRecord.IDLE;
            scheduleBroadcastsLocked(); // 重新调用 processNextBroadcast,将广播转发给下一个
        } else {
            // brOptions == null
            if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                scheduleTempWhitelistLocked(filter.owningUid,
                        brOptions.getTemporaryAppWhitelistDuration(), r);
            }
        }
        // 这里直接return 了, 如何将广播转发给下一个接收器?
        return;
    }
    

    上面的代码比较晦涩,processNextBroadcast调用一次会将所有的无序广播分发完毕,但是只会分发一个有序广播到一个接受器。找到了这个就比较好立即上面的代码的一些条件判断的顺序了。

    1. 判断是否存在有序广播。

    2. 判断当前有序广播是不是超时或者分完完成,是就从 有序广播队列中移除。

    3. 分发有序广播,出现错误就重新执行scheduleBroadcastsLocked,这样就会重新进入processNextBroadcast,进而分发下一个广播。

      没有错误就直接返回,然后等待接收器处理后,判断当前广播是否需要继续分发。

    忽略一个重要函数deliverToRegisteredReceiverLocked,它负责将广播交付给接收器对应的进程处理。

    4. deliverToRegisteredReceiverLocked

    该函数在完成交付操作前,还会进行一堆权限校验:

    1. 校验BroadcastFilter@requiredPermission 是否被授予。
    2. 校验BroadcastRecord@requiredPermissions 是否被授予。
    3. 判断 Intent 是否被 IntentFirewall 拦截。
    4. 处理该广播的接收器对应的进程不存在。
    5. IntentApp 是否允许接收广播。
    6. ...

    这些操作的代码就不贴,重点关注分发操作。

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
       
        // 更新状态为 交付
        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
    	
        if (ordered) {
            r.receiver = filter.receiverList.receiver.asBinder();
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                r.curApp = filter.receiverList.app;
                filter.receiverList.app.curReceivers.add(r);
                mService.updateOomAdjLocked(r.curApp, true);
            }
        }
        try {
            // 全备份时不接受广播?
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // Skip delivery if full backup in progress
                // If it's an ordered broadcast, we need to continue to the next receiver.
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
            if (ordered) {
                r.receiver = null;   //出现异常, 置空,对应前面的异常处理
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
                if (filter.receiverList.app != null) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
        }
    }
    

    不管有序广播还是无序广播,都是通过performReceiveLocked完成发送操作的。

    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        if (app != null) {
            if (app.thread != null) {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }
    

    对于已启动的app,通过执行其IApplicationThread@scheduleRegisteredReceiver完成广播分发,对于一些系统应用,注册了静态广播接收器的,如果该app没有起来,就直接执行receiver@performReceive来执行广播接收器。

    接下来分析scheduleRegisteredReceiver

    IApplicationThread@scheduleRegisteredReceiver

    //frameworks/base/core/java/android/app/ActivityThread.java
    public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
            int resultCode, String dataStr, Bundle extras, boolean ordered,
            boolean sticky, int sendingUser, int processState) throws RemoteException {
        updateProcessState(processState, false);
        receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                sticky, sendingUser);
    }
    

    注册广播提到过IIntentReceiver,其实现类时InnerReceiver

    1. IIntentReceiver@performReceive

    // frameworks/base/core/java/android/app/LoadedApk.java
    @Override
    public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        final LoadedApk.ReceiverDispatcher rd;
        if (intent == null) {
            rd = null;
        } else {
            rd = mDispatcher.get();
        }
    	
        if (rd != null) {
            rd.performReceive(intent, resultCode, data, extras,
                    ordered, sticky, sendingUser);
        } else {
            IActivityManager mgr = ActivityManager.getService();
            try {
                if (extras != null) {
                    extras.setAllowFds(false);
                }
                // 通知AMS 当前广播处理结束
                mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
    

    2. ReceiverDispatcher@performReceive

    ReceiverDispatcher注册广播中也提到过, 这里通过其performReceive方法,调用我们的onReceive

    public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        final Args args = new Args(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
        if (intent == null) {
        }
    
        if (intent == null || !mActivityThread.post(args.getRunnable() /*异步执行广播处理*/)) {
            // 有序广播
            if (mRegistered && ordered) {
                // 通知AMS,广播处理完成
                IActivityManager mgr = ActivityManager.getService();
                args.sendFinished(mgr);
            }
        }
    }
    

    3. Args.getRunnbale();

    首先,明确一点,广播接收器不能做耗时操作的原因就是其运行实在UI线程中的。

    public final Runnable getRunnable() {
        return () -> {
            final BroadcastReceiver receiver = mReceiver;
            final boolean ordered = mOrdered;
    
            final IActivityManager mgr = ActivityManager.getService();
            final Intent intent = mCurIntent;
    
            mCurIntent = null;
            mDispatched = true;
    
            ClassLoader cl = mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            //在这里调用到 onReceive。
            receiver.onReceive(mContext, intent);
    
            if (receiver.getPendingResult() != null) {
                finish();
            }
        };
    }
    

    finish实现在BroadcastReceiver@PendingResult中,用于将接收器执行结果返回到AMS中,这是有序广播有序执行的关键操作。

    public final void finish() {
        if (mType == TYPE_COMPONENT) {
            final IActivityManager mgr = ActivityManager.getService();
            if (QueuedWork.hasPendingWork()) {
                QueuedWork.queue(new Runnable() {
                    @Override public void run() {
                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                "Finishing broadcast after work to component " + mToken);
                        sendFinished(mgr);
                    }
                }, false);
            } else {
                sendFinished(mgr);
            }
        } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
            final IActivityManager mgr = ActivityManager.getService();
            sendFinished(mgr);
        }
    }
    

    继续 sendFinished

    public void sendFinished(IActivityManager am) {
        synchronized (this) {
            mFinished = true;
                if (mResultExtras != null) {
                    mResultExtras.setAllowFds(false);
                }
                if (mOrderedHint) {
                    am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                            mAbortBroadcast, mFlags);
                } else {
                    // This broadcast was sent to a component; it is not ordered,
                    // but we still need to tell the activity manager we are done.
                    am.finishReceiver(mToken, 0, null, null, false, mFlags);
                }
        }
    }
    

    AMS@finishReceiver

    public void finishReceiver(IBinder who, int resultCode, String resultData,
            Bundle resultExtras, boolean resultAbort, int flags) {
    
    
        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doNext = false;
            BroadcastRecord r;
    
            synchronized(this) {
                // 判断是否是 前台广播,。
                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
                // 根据 who (实际类型就是 IIntentReceiver对象)
                r = queue.getMatchingOrderedReceiver(who);	//获取到有序对列的 BroadcastRecord。
                if (r != null) {
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                        resultData, resultExtras, resultAbort, true);
                } else {
                    //说明 who对应的是无序广播,不做特殊处理。
                }
            }
    
            if (doNext) {
                r.queue.processNextBroadcast(false);
            }
            trimApplications();
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
    

    finishReceiverLocked返回值表示是否需要继续处理分发广播非下一个广播接收器。

    public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
            String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
        final int state = r.state;
        final ActivityInfo receiver = r.curReceiver;
        r.state = BroadcastRecord.IDLE;
        if (state == BroadcastRecord.IDLE) {
            Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
        }
        r.receiver = null;
        r.intent.setComponent(null);
        if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
            r.curApp.curReceivers.remove(r);
        }
        if (r.curFilter != null) {
            r.curFilter.receiverList.curBroadcast = null;
        }
        r.curFilter = null;
        r.curReceiver = null;
        r.curApp = null;
        mPendingBroadcast = null;
    
        r.resultCode = resultCode;
        r.resultData = resultData;
        r.resultExtras = resultExtras;
        
        // FLAG_RECEIVER_NO_ABORT 表示不允许BroadcastReceiver 中断有序广播的传播。
        if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
            r.resultAbort = resultAbort;
        } else {
            r.resultAbort = false;
        }
    	
        // 这一段作用不清楚。
        if (waitForServices /*true*/ && r.curComponent != null && r.queue.mDelayBehindServices
                && r.queue.mOrderedBroadcasts.size() > 0
                && r.queue.mOrderedBroadcasts.get(0) == r) {
            ActivityInfo nextReceiver;
            if (r.nextReceiver < r.receivers.size()) {
                Object obj = r.receivers.get(r.nextReceiver);
                nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
            } else {
                nextReceiver = null;
            }
            
            // 
            if (receiver == null || nextReceiver == null
                    || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
                    || !receiver.processName.equals(nextReceiver.processName)) {
                
                if (mService.mServices.hasBackgroundServicesLocked(r.userId)) {
                    Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
                    r.state = BroadcastRecord.WAITING_SERVICES;
                    return false;
                }
            }
        }
    
        r.curComponent = null;
        
    	// 有序广播已经被接收器正确处理
        return state == BroadcastRecord.APP_RECEIVE
                || state == BroadcastRecord.CALL_DONE_RECEIVE;
    }
    

    如果doNext == true, 则继续调用processNextBroadcast处理有序广播。

    总结

    1. Foreground 广播超时时间是10s,Background广播超时时间是60s。
    2. 有序广播处理完后,需要调用finishReceiver通知AMS,无序广播无需此操作。
    3. 静态注册的广播接收器是不能接收到隐式广播的,除非我们添加了FLAG_RECEIVER_INCLUDE_BACKGROUND标记。

    问题

    1. registerReceiverscheduler参数是如何工作的。

      LoadedApk@ReceiverDispatcher@Args::getRunnable()返回回一个Runnable对象,由该对象完成 onReceive的调用,默认实在UI线程中执行的。我们可以指定scheduler(Handler),系统会执行Handler@post方法运行前面返回的Runnable对象。

    2. IIntentReceiver@performReceive是没有返回值的,对于有序广播,AMS如何等待其处理完毕。

      BroadcastQueue@processNextBroadcast将有序广播发送给广播接收器后,广播接收器处理完成后,所在进程会执行AMS@finishReceiver,还函数会根据参数决定是否再次调用processNextBroadcast来将有序广播发送给下一个广播接收器。

    3. 进程的Receiver的显示是1000,包不包括静态注册的。

    4. Android禁止应用程序发送隐式广播,send操作没有看到这部分处理,在哪里实现的?

      不是禁止发送隐式广播,而是不允许普通进程静态注册的广播接收器接收隐式广播。

    5. 发送广播时,如果是无序广播,AMS处理时,只将动态注册的广播接收器 加入了ParallelBroadcast中,静态注册的则是加入了OrderedBroadcast中,这是为什么???

      简单的说就是无序广播时不会发送给Mainfest receiver的。那么有序广播就行??? 回到BroadcastQueue@processNextBroadcast中:

      //frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java 
      final void processNextBroadcast(boolean fromMsg) {
      	...
          final Object nextReceiver = r.receivers.get(recIdx);
      	if (nextReceiver instanceof BroadcastFilter) {
              deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
          }
      	...
          // 处理特殊情况 FLAG_RECEIVER_INCLUDE_BACKGROUND 、FLAG_EXCLUDE_STOPPED_PACKAGES等。
      }
      

      可以看到,只有BroadcastFilter实例(动态注册的)的广播接收器才会接收到有序广播。所以,静态广播接收器也不能接收到有序广播。

      如果Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND标志被设置了,静态注册的广播接收器就能接收到广播,不管是有序还是无序的。

      特殊情况的处理有时间再补充。

    6. 系统应用注册静态广播接收器接收开机广播实现自启动的原理。

      待学习了PKMS后再补充。

    附录

    1. 关于IntentFirewall

    Intent 广播相关的 FLAG

    flag 含义
    Intent.FLAG_RECEIVER_NO_ABORT 针对有序广播,该标记位设置后,BroadcastReceiver@onReceive中调用abortBroadcast无法中断广播接下来的发送。
    Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 表示该隐式广播能够被静态注册的广播接收器接收到。我们可以在allow-implicit-broadcast配置是否允许隐式广播被接收。
    Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND 和上面的相反,表示该广播不允许被静态注册的广播接收器接收。
    Intent.FLAG_RECEIVER_REGISTERED_ONLY 表示该广播只能被静态注册的广播接收器接收。
    Intent.FLAG_INCLUDE_STOPPED_PACKAGES 表示能够唤醒已经停止运行的进程来处理该广播。
    Intent.FLAG_EXCLUDE_STOPPED_PACKAGES 和上面的相反。虽然注释中说明FLAG_INCLUDE_STOPPED_PACKAGES是默认行为,但是AMS@broadcastIntentLocked会主动为每个广播Intent 加上FLAG_EXCLUDE_STOPPED_PACKAGES

    还有很多,以后遇到了问题再补充。

    隐式广播

    这个把我绕晕了,我的理解就是, 没有指定 explicit component or package name的就是隐式广播。

    隐式广播只是针对于静态注册的接收器而言的,对于动态注册的没有影响。安卓现在不允许应用之间使用隐式广播。

    As part of the Android 8.0 (API level 26) Background Execution Limits, apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. However, several broadcasts are currently exempted from these limitations. Apps can continue to register listeners for the following broadcasts, no matter what API level the apps target.

    具体参考Implicit Broadcast Exceptions

    比如我们要接收开机广播实现应用自启动,我们可以注册ACTION_LOCKED_BOOT_COMPLETED, ACTION_BOOT_COMPLETED的接收器在我们的manifest文件中,虽然这两个广播属于Background Execution Limits,但是还有两个限制条件:

    1. 我们的应用是系统应用(android:sharedUserId="android.uid.system")。
    2. 应用内置在/system/app目录下(priv-app也可以)。
  • 相关阅读:
    线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
    C#打印图片
    javascript 地址栏写法
    SQLServer获取Excel中所有Sheet
    C#多页打印实现
    clear在CSS中的妙用
    mitmproxy使用总结
    本地回路抓包问题
    博客园界面优化
    CentOS基于MySQL提供的Yum repository安装MySQL5.6
  • 原文地址:https://www.cnblogs.com/liutimo/p/14660536.html
Copyright © 2011-2022 走看看