Android系統(tǒng)源碼分析-Broadcast發(fā)送

上一篇分析了Android系統(tǒng)中廣播的注冊和注銷,這一篇我們繼續(xù)分析發(fā)送廣播的源碼流程,廣播的發(fā)送相對來說比較復(fù)雜,所以需要比較長的時(shí)間來看,如果你看懂了流程相對來說再研究流程中的細(xì)節(jié)就比較簡單了。

先看一張時(shí)序圖,因?yàn)槔锩嫔婕暗窖h(huán)過程,代碼中會提到,但是時(shí)序圖沒有繪制,所以需要注意一下。

注冊廣播時(shí)序圖

0、ContextImpl.sendBroadcast

 /**
     * 發(fā)送廣播
     * 步驟:
     * 1.廣播發(fā)送者,即一個(gè)Activity組件或者一個(gè)Service組件,將一個(gè)特定類型的廣播發(fā)送給AMS
     * <p>
     * 2.AMS接收到一個(gè)廣播后,首先找到與這個(gè)廣播對應(yīng)的廣播接收者,然后將它們添加到一個(gè)廣播調(diào)度隊(duì)列中,
     * 最后向AMS所運(yùn)行在的先從的消息隊(duì)列發(fā)送一個(gè)類型為BROADCAST_INTENT_MSG的消息,這時(shí)候?qū)V播發(fā)送
     * 者來說,一個(gè)廣播就發(fā)送完了。
     * <p>
     * 3.當(dāng)發(fā)送到AMS所運(yùn)行在的線程的消息隊(duì)列中的BROADCAST_INTENT_MSG消息被處理時(shí),AMS就會從廣播調(diào)
     * 度隊(duì)列中知道需要接受廣播的接收者,并且將對應(yīng)的廣播發(fā)送給它們所運(yùn)行在的應(yīng)用進(jìn)程。
     * <p>
     * 4.廣播接收者所運(yùn)行的應(yīng)用程序接收到AMS發(fā)送過來的廣播后,并不是直接將接收到的廣播發(fā)送給廣播接收
     * 者來處理,而是將接收到的廣播封裝成一個(gè)消息,并且發(fā)送到主線程的消息隊(duì)列中。當(dāng)找個(gè)消息被處理時(shí),
     * 應(yīng)用程序進(jìn)程才會將它所描述的廣播發(fā)給相應(yīng)的廣播接收者處理
     * <p>
     * 參考:
     * http://blog.csdn.net/houliang120/article/details/51607170
     * http://gityuan.com/2016/06/04/broadcast-receiver/
     * http://blog.csdn.net/windskier/article/details/7251742
     *
     * @param intent The Intent to broadcast; all receivers matching this
     *               Intent will receive the broadcast.
     */
    @Override
    public void sendBroadcast(Intent intent) {
        ...
        try {
            ...
            // 調(diào)用ActivityManagerProxy中的broadcastIntent,然后通過Binder調(diào)用ActivityManagerService
            // 中的broadcastIntent
            ActivityManagerNative.getDefault().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE,
                    null, false, false, getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

之前我們講過調(diào)用ActivityManagerProxy的broadcastIntent方法,然后通過Binder調(diào)用ActivityManagerService中的對應(yīng)方法。

1、ActivityManagerProxy.broadcastIntent

    public int broadcastIntent(IApplicationThread caller,
                               Intent intent, String resolvedType, IIntentReceiver resultTo,
                               int resultCode, String resultData, Bundle map,
                               String[] requiredPermissions, int appOp, Bundle options, boolean serialized,
                               boolean sticky, int userId) throws RemoteException {
        ...
        // 通過Binder對象mRemote向AMS發(fā)送一個(gè)類型為BROADCAST_INTENT_TRANSACTION的進(jìn)程間通信請求
        mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
        ...
        return res;
    }

2、ActivityManagerService.broadcastIntent

    // 發(fā)送廣播
    public final int broadcastIntent(IApplicationThread caller,
                                     Intent intent, String resolvedType, IIntentReceiver resultTo,
                                     int resultCode, String resultData, Bundle resultExtras,
                                     String[] requiredPermissions, int appOp, Bundle bOptions,
                                     boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized (this) {
            // 驗(yàn)證廣播的Intent是否合法,如果這個(gè)時(shí)候系統(tǒng)正在啟動,還會驗(yàn)證intent所描述的廣播是否只發(fā)送
            // 給動態(tài)注冊的廣播接收者。在系統(tǒng)的啟動過程中,PMS可能還未啟動,這種情況下,AMS是無法獲取靜態(tài)
            // 注冊廣播接收者的,因此,就禁止發(fā)送廣播給靜態(tài)注冊的廣播接收者
            intent = verifyBroadcastLocked(intent);
            // 根據(jù)caller從緩存mLruProcesses中獲取進(jìn)程對象ProcessRecord
            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            ...
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

3、ActivityManagerService.broadcastIntentLocked

    final int broadcastIntentLocked(ProcessRecord callerApp,
                                    String callerPackage, Intent intent, String resolvedType,
                                    IIntentReceiver resultTo, int resultCode, String resultData,
                                    Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                                    boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        intent = new Intent(intent);

        // By default broadcasts do not go to stopped apps.
        // 增加下面flag,默認(rèn)不發(fā)送廣播到已經(jīng)停止的app
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        // If we have not finished booting, don't allow this to launch new processes.
        // 如果該進(jìn)程還沒有完成啟動,并且不是發(fā)送給啟動升級的廣播,則添只發(fā)送給已注冊的廣播接收者標(biāo)簽
        if (!mProcessesReady && (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);// 只發(fā)給注冊的receiver
        }

        ...

        // 獲取當(dāng)前發(fā)送廣播應(yīng)用所在用戶的userId
        // 解釋:
        // 7.1.1系統(tǒng)有多用戶登錄,就像電腦上的主用戶和訪客模式一樣,可以設(shè)置多個(gè)用戶,每個(gè)用戶有一個(gè)id,
        // 有些廣播需要多個(gè)用戶都要接收,比如時(shí)區(qū)變化這些,是同步的,每個(gè)用戶都要變化。這里一般是我們
        // 當(dāng)前登錄的用戶id
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_NON_FULL, "broadcast", callerPackage);

        // Make sure that the user who is receiving this broadcast is running.
        // If not, we will just skip it. Make an exception for shutdown broadcasts
        // and upgrade steps.
        if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
                return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
            }
        }

        ...

        // Verify that protected broadcasts are only being sent by system code,
        // and that system code is only sending protected broadcasts.
        final String action = intent.getAction();
        final boolean isProtectedBroadcast;
        try {
            // 驗(yàn)證是不是受保護(hù)的廣播(是不是系統(tǒng)廣播)
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            ...
            return ActivityManager.BROADCAST_SUCCESS;
        }

        // 檢查是不是系統(tǒng)調(diào)用
        final boolean isCallerSystem;
        switch (UserHandle.getAppId(callingUid)) {
            case Process.ROOT_UID:
            case Process.SYSTEM_UID:
            case Process.PHONE_UID:
            case Process.BLUETOOTH_UID:
            case Process.NFC_UID:
                isCallerSystem = true;
                break;
            default:
                isCallerSystem = (callerApp != null) && callerApp.persistent;
                break;
        }

        // First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
        if (!isCallerSystem) {// 不是系統(tǒng)發(fā)送的廣播
            if (isProtectedBroadcast) {// 非系統(tǒng)進(jìn)程發(fā)送受保護(hù)廣播拋出異常
                throw new SecurityException(msg);
            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
                // 如果是配置小部件或者升級小部件的廣播
                // Special case for compatibility: we don't want apps to send this,
                // but historically it has not been protected and apps may be using it
                // to poke their own app widget.  So, instead of making it protected,
                // just limit it to the caller.
                if (callerPackage == null) {
                    throw new SecurityException(msg);
                } else if (intent.getComponent() != null) {
                    // They are good enough to send to an explicit component...  verify
                    // it is being sent to the calling app.
                    if (!intent.getComponent().getPackageName().equals(
                            callerPackage)) {
                        throw new SecurityException(msg);
                    }
                } else {
                    // Limit broadcast to their own package.
                    // 限制發(fā)送廣播給自己包里
                    intent.setPackage(callerPackage);
                }
            }
        }

        // 下面主要是針對系統(tǒng)廣播的處理
        if (action != null) {
            switch (action) {
                case Intent.ACTION_UID_REMOVED:// 移除uid
                case Intent.ACTION_PACKAGE_REMOVED:// 卸載應(yīng)用
                case Intent.ACTION_PACKAGE_CHANGED:// 應(yīng)用更改,比如:停用,啟動等
                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部應(yīng)用不可用,比如安裝到sd卡的應(yīng)用,卸載了sd卡
                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部應(yīng)用可用
                case Intent.ACTION_PACKAGES_SUSPENDED:// 暫停應(yīng)用
                case Intent.ACTION_PACKAGES_UNSUSPENDED:// 應(yīng)用可用
                    switch (action) {
                        case Intent.ACTION_UID_REMOVED:// 移除系統(tǒng)userId(刪除一個(gè)用戶)
                            ...
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部應(yīng)用不可用,一般是卸載SD卡
                            ...
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部應(yīng)用可用,一般是插入SD卡
                            ...
                            break;
                        case Intent.ACTION_PACKAGE_REMOVED:// 卸載
                        case Intent.ACTION_PACKAGE_CHANGED:// 更新
                            ...
                            break;
                        case Intent.ACTION_PACKAGES_SUSPENDED:
                        case Intent.ACTION_PACKAGES_UNSUSPENDED:
                            ...
                            break;
                    }
                    break;
                case Intent.ACTION_PACKAGE_REPLACED: {// 升級應(yīng)用
                    ...
                    break;
                }
                case Intent.ACTION_PACKAGE_ADDED: {// 安裝應(yīng)用
                    ...
                    break;
                }
                case Intent.ACTION_PACKAGE_DATA_CLEARED: {// 清理應(yīng)用數(shù)據(jù)
                    ...
                    break;
                }
                case Intent.ACTION_TIMEZONE_CHANGED:// 時(shí)區(qū)改變
                    ...
                    break;
                case Intent.ACTION_TIME_CHANGED:// 時(shí)間改變
                    ...
                    break;
                case Intent.ACTION_CLEAR_DNS_CACHE:// 清理DNS緩存
                    ...
                    break;
                case Proxy.PROXY_CHANGE_ACTION:// 代理改變
                    ...
                    break;
                case android.hardware.Camera.ACTION_NEW_PICTURE:// 新照片
                case android.hardware.Camera.ACTION_NEW_VIDEO:// 新視頻
                    ...
                    return ActivityManager.BROADCAST_SUCCESS;
            }
        }

        // Add to the sticky list if requested.
        if (sticky) {// 判斷是否是粘性廣播,如果是,AMS就需要保存這個(gè)廣播,以便后面注冊要接收此類型廣播的接收者可以獲得這個(gè)廣播
            // 檢查粘性廣播是否申請了權(quán)限
            ...
            if (requiredPermissions != null && requiredPermissions.length > 0) {
                ...
                return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
            }
            // sticky廣播不能指定目標(biāo)組件
            ...
            // We use userId directly here, since the "all" target is maintained(維護(hù))
            // as a separate set of sticky broadcasts.
            if (userId != UserHandle.USER_ALL) {// 不是發(fā)送給所有用戶的廣播
                // But first, if this is not a broadcast to all users, then
                // make sure it doesn't conflict(沖突) with an existing broadcast to
                // all users.
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                        UserHandle.USER_ALL);
                ...// 檢查是否和存在的發(fā)給所有用戶的粘性廣播一樣的廣播
            }
            // 在AMS中所有的粘性廣播都保存在一個(gè)列表中,這些列表最終保存在AMS的成員變量mStickyBroadcasts
            // 所描述的一個(gè)HashMap中,并且以它們的廣播類型為關(guān)鍵字
            // 首先檢查mStickyBroadcasts是否有改用戶的粘性廣播列表
            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
            // 該廣播列表中沒有該用戶的stick廣播列表
            if (stickies == null) {
                stickies = new ArrayMap<>();
                mStickyBroadcasts.put(userId, stickies);
            }
            // 獲取注冊廣播的Action對應(yīng)的粘性廣播的Intent列表
            ArrayList<Intent> list = stickies.get(intent.getAction());
            if (list == null) {// 如果為空
                list = new ArrayList<>();// 創(chuàng)建一個(gè)列表
                stickies.put(intent.getAction(), list);// 以action為鍵保存該列表
            }
            // 獲取該action對應(yīng)粘性廣播Intent列表的個(gè)數(shù)
            final int stickiesCount = list.size();
            int i;
            // 檢查在粘性廣播列表中是否保存了一個(gè)與參數(shù)Intent一致的廣播。如果存在直接替換,否則將參數(shù)
            // Intent描述的廣播添加到粘性廣播列表list中
            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) {// 如果該列表中不存在該粘性廣播的Intent加入進(jìn)去
                list.add(new Intent(intent));
                // 我們看到粘性廣播放在了list中,而list以action為鍵放置在了stickies中,而stickies
                // 又以userId為鍵放在了mStickyBroadcasts中,因此mStickyBroadcasts保存了設(shè)備中所有
                // 用戶粘性廣播的Intent
            }
        }

        int[] users;
        if (userId == UserHandle.USER_ALL) {// 發(fā)送廣播給全部用戶
            // Caller wants broadcast to go to all started users.
            // 獲取所有已啟動用戶的列表
            users = mUserController.getStartedUserArrayLocked();
        } else {// 發(fā)送廣播給指定用戶
            // Caller wants broadcast to go to one specific user.
            users = new int[]{userId};
        }

        // Figure out who all will receive this broadcast.
        List receivers = null;// 靜態(tài)注冊接收者
        List<BroadcastFilter> registeredReceivers = null;// 動態(tài)注冊接收者
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                == 0) {// 如果當(dāng)前的廣播Intent沒有指定FLAG_RECEIVER_REGISTERED_ONLY標(biāo)記,也就是允許靜態(tài)注冊
            // 允許靜態(tài)注冊的Intent,需要從PMS中去查詢對應(yīng)的廣播接收者
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        // 如果參數(shù)intent沒有指定廣播接收者的組件名,說明是發(fā)送給所有已注冊并且要接收該廣播的接收者的
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
                // Query one target user at a time, excluding shell-restricted users
                // 查找每一個(gè)用戶的廣播注冊者
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    // registeredReceiver快結(jié)束前將注冊的BroadcastFilter放入mReceiverResolver中
                    // 里面包含了對應(yīng)的動態(tài)注冊的廣播接收者
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {// 查找當(dāng)前用戶的所有廣播接收者
                // 查詢所有動態(tài)注冊廣播接收者
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false, userId);
            }
        }
          // 由于AMS是通過消息機(jī)制將接收到的廣播發(fā)送給目標(biāo)廣播接收者的,因此可能會出現(xiàn)一種情況:上次接收
        // 的廣播還沒有來得及發(fā)送給廣播接收者,又馬上接收到一個(gè)同樣的廣播,在這種情況下,如果現(xiàn)在接收的
        // 廣播標(biāo)志位FLAG_RECEIVER_REPLACE_PENDING等于1,那么AMS就會用新的廣播代替舊的廣播。
        final boolean replacePending =
                (intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;

        // 動態(tài)廣播接收者個(gè)數(shù)
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        // 處理無序廣播并且存在動態(tài)接收者,首先將當(dāng)前發(fā)送的廣播,即參數(shù)Intent所描述的對象轉(zhuǎn)發(fā)給這些動態(tài)
        // 注冊的目標(biāo)廣播接收者,然后轉(zhuǎn)發(fā)給靜態(tài)廣播接收者
        if (!ordered && NR > 0) {
            ...
            // 根據(jù)intent查找對應(yīng)的廣播隊(duì)列(前臺優(yōu)先級隊(duì)列還是后臺優(yōu)先級隊(duì)列),創(chuàng)建BroadcastRecord
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            // 將參數(shù)intent所描述的廣播以及動態(tài)注冊的目標(biāo)廣播接收者封裝成一個(gè)BroadcastRecord對象r,
            // 用來描述AMS要執(zhí)行的一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
                    appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
                    resultExtras, ordered, sticky, false, userId);
            ...
            // 在BroadcastQueue中等待發(fā)送廣播中搜索是否有相同的BroadcastRecord并且是否替換
            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
            if (!replaced) {
                // 如果不需要替換則插入到BroadcastQueue中,并推動一次廣播發(fā)送
                // ------------------!!!重要!!!-------------這里如果是非有序廣播,那就都是動態(tài)廣播接收者
                // 也就是說動態(tài)廣播接收者都放在了BroadcastQueue的mParallelBroadcasts中
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

        // Merge into one list.動態(tài)廣播registeredReceivers和靜態(tài)廣播receivers合并
        // 如果是order廣播,動態(tài)接收者和靜態(tài)的接收者合并到一個(gè)隊(duì)列里面進(jìn)行處理,也就是說order廣播下,
        // 所有的接收者(靜態(tài)和動態(tài))處理方式都是一樣的(后面會分析到,都是串行化處理的)。
        // 還有就是對于靜態(tài)的接收者而言,始終是和order廣播的處理方式是一樣的,也就是說靜態(tài)的接收者
        // 只有order模式(串行化接收)。
        // 在合并過程中,如果一個(gè)動態(tài)注冊的廣播接收者和一個(gè)靜態(tài)注冊的目標(biāo)廣播接收者的優(yōu)先級相同,那么
        // 動態(tài)注冊的目標(biāo)接收者會排在靜態(tài)注冊的目標(biāo)廣播接收者前面,即動態(tài)注冊的目標(biāo)廣播接收者會優(yōu)先于
        // 靜態(tài)注冊的廣播接收者接受有序廣播
        int ir = 0;
        if (receivers != null) {// order廣播(靜態(tài)廣播)
            // 對于ACTION_PACKAGE_ADDED廣播而言,如果是自己被add了,那么這個(gè)廣播只能別人收到,
            // 自己即使注冊了這個(gè)靜態(tài)廣播也接收不到,注釋上說是擔(dān)心有些應(yīng)用一安裝就接收自己的PACKAGE_ADDED
            // 廣播,然后就啟動了。簡言之,應(yīng)用永遠(yuǎn)接收不到自己的PACKAGE_ADDED廣播。
            String skipPackages[] = null;// 需要跳過的廣播
            ...

            // 合并中...
            // 下面這一段代碼是典型的有序鏈表的合并操作,合并的依據(jù)是接收者的priority值,這里需要注意的一點(diǎn)
            // 是動態(tài)廣播接收器注冊的時(shí)候一般都沒有指定priority,默認(rèn)值是0,具體實(shí)現(xiàn)好像有點(diǎn)像歸并排序的意思,
            // 而且是從后向前進(jìn)行的歸并,因此priority越小,在鏈表中的位置就越靠前,后面處理的時(shí)候也就越先處理。
            // 走完這里所有的靜態(tài)接收者和order模式下的動態(tài)接收者都已經(jīng)被合并到了receivers鏈表里面。
            // 合并以后在receivers鏈表里面靜態(tài)接收者對應(yīng)ResolveInfo對象,order模式下的動態(tài)接收者對應(yīng)的
            // 是BroadcastFilter對象。
            int NT = receivers != null ? receivers.size() : 0;// 靜態(tài)注冊廣播接收者
            int it = 0;
            ResolveInfo curt = null;// 靜態(tài)接收者
            BroadcastFilter curr = null;// 動態(tài)接收者
            ...
        }
        // 對于無序廣播來說,靜態(tài)注冊的廣播接收者全部保存在列表receivers中,而對于有序廣播來說,靜態(tài)
        // 注冊和動態(tài)注冊的目標(biāo)廣播接收者全部保存在receivers列表中
        // 合并中...
        ...

        // 可以看出,是在合并入receiver后統(tǒng)一發(fā)送BroadcastQueue.scheduleBroadcastsLocked
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            // 將剩余的其他目標(biāo)廣播接收者封裝成另外的一個(gè)BroadcastRecord對象,用來描述AMS要執(zhí)行的另
            // 一個(gè)廣播轉(zhuǎn)發(fā)任務(wù),兵器添加到AMS內(nèi)部的有序廣播調(diào)用隊(duì)列中
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            // 在BroadcastQueue中等待發(fā)送廣播中搜索是否有相同的BroadcastRecord并且是否替換
            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
            if (!replaced) {// 存在需要AMS的有序廣播調(diào)用隊(duì)列中增加新的額廣播任務(wù)
                // ---------!!!重要!!!----------包含動態(tài)和靜態(tài)接收者
                // 也就是說靜態(tài)廣播都放在BroadcastQueue的mOrderedBroadcasts中,這里也有orderd動態(tài)廣播
                queue.enqueueOrderedBroadcastLocked(r);
                // 執(zhí)行發(fā)送廣播
                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;
    }

這里代碼比較多,簡單解釋一下,首先是判斷是不是系統(tǒng)廣播,也就是switch語句中的部分,這部分的廣播是系統(tǒng)發(fā)出的,根據(jù)不同廣播做出不同的處理,系統(tǒng)廣播我們可以接收但是不能發(fā)送,只能由系統(tǒng)發(fā)出,詳細(xì)的不再解釋,自己可以看看;然后是sticky廣播的處理;然后是靜態(tài)廣播和動態(tài)廣播的處理,在動態(tài)廣播和靜態(tài)廣播處理中,先處理動態(tài)廣播接收者,再處理靜態(tài)廣播接收者,因此動態(tài)廣播接收者先收到廣播,然后是靜態(tài)廣播接收者,動態(tài)廣播和靜態(tài)廣播接收者都會通過調(diào)用BroadcastQueue.scheduleBroadcastsLocked方法來發(fā)送廣播,在看這個(gè)代碼之前先看一下時(shí)序圖中的第四步。

4、AMS.broadcastQueueForIntent

    // 根據(jù)Intent所帶標(biāo)簽判斷接收者是以前臺優(yōu)先級還是后臺優(yōu)先級運(yùn)行,前臺接收者優(yōu)先級超時(shí)時(shí)間較短
    // 正常是后臺優(yōu)先級運(yùn)行,并且不會被提升到前臺優(yōu)先級
    BroadcastQueue broadcastQueueForIntent(Intent intent) {
        final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
        return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
    }

這個(gè)方法主要是根據(jù)Intent中的標(biāo)簽在判斷是接收者是后臺優(yōu)先級還是前臺優(yōu)先級,關(guān)于這兩個(gè)概念看上面代碼中注釋的內(nèi)容。

5、BroadcastQueue.scheduleBroadcastsLocked

    // 驅(qū)動廣播,所有廣播都應(yīng)該從這里走,然后會到processNextBroadcast
    public void scheduleBroadcastsLocked() {
        ...
        // mBroadcastsScheduled用來描述AMS是否已經(jīng)向它所運(yùn)行在的線程的消息隊(duì)列發(fā)送了一個(gè)類型為
        // BROADCAST_INTENT_MSG的消息。AMS就是通過這個(gè)BROADCAST_INTENT_MSG消息類調(diào)度保存在無
        // 序廣播調(diào)度隊(duì)列mParallelBroadcasts和有序廣播調(diào)度隊(duì)列mOrderedBroadcasts中的廣播轉(zhuǎn)發(fā)任務(wù)的
        if (mBroadcastsScheduled) {// 如果true說明消息隊(duì)列已經(jīng)存在一個(gè)類型為BROADCAST_INTENT_MSG的消息了
            return;
        }
        // 雖然這里只發(fā)送了發(fā)送廣播的消息,但是這一步執(zhí)行完之后就已經(jīng)標(biāo)記廣播發(fā)送了,因此可以看出廣播發(fā)送和接
        // 受是異步的,即廣播發(fā)送者將一個(gè)廣播發(fā)送給AMS后,不會等待AMS將這個(gè)廣播轉(zhuǎn)發(fā)給廣播接收者處理
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

廣播中大多數(shù)內(nèi)容的處理是在BroadcastQueue類中,上面有個(gè)mBroadcastsScheduled參數(shù),如果為ture則阻止繼續(xù)執(zhí)行,那么我們看到下面發(fā)完消息后會將其設(shè)置為true,我們接著看哪里將其執(zhí)行為false的,

6、BroadcastQueue.processNextBroadcast

    // 廣播的核心部分,參數(shù)fromMsg是用來描述AMS類的成員函數(shù)processNextBroadcast是否是用來處理類型為
    // BROADCAST_INTENT_MSG的消息的
    final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            BroadcastRecord r;
            ...

            if (fromMsg) {// 從msg過來的時(shí)候?yàn)閠rue
                // 前面說到,如果消息隊(duì)列里面有BROADCAST_INTENT_MSG消息,該標(biāo)記為true,
                // 阻止新的消息加入隊(duì)列,這里開始處理這個(gè)消息的時(shí)候,將mBroadcastsScheduled變量設(shè)置為false,
                // 開始允許新的消息加入。
                mBroadcastsScheduled = false;
            }

            // 無序廣播之間不存在相互等待,這里處理的是所有非order的動態(tài)廣播
            // 處理保存在無序廣播調(diào)度隊(duì)列mParallelBroadcasts中的廣播發(fā)送任務(wù),即把保存在無序廣播調(diào)度
            // 隊(duì)列mParallelBroadcasts中的廣播發(fā)送給它的目標(biāo)廣播接收者處理
            while (mParallelBroadcasts.size() > 0) {
                // 首先保存無序廣播調(diào)度隊(duì)列mParallelBroadcasts中的每一個(gè)BroadcastRecord對象
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();
                // 調(diào)用deliverToRegisteredReceiverLocked向所有的receivers發(fā)送廣播
                final int N = r.receivers.size();
                // 將它所描述的每一個(gè)無序廣播發(fā)送給每一個(gè)廣播接收者
                for (int i = 0; i < N; i++) {
                    Object target = r.receivers.get(i);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false, i);
                }
                addBroadcastToHistoryLocked(r);
            }

            ...
            // 接下來處理保存在有序廣播調(diào)度隊(duì)列mPendingBroadcast中的廣播轉(zhuǎn)發(fā)任務(wù)。有前面可知,有序廣播
            // 調(diào)度隊(duì)列mOrderedBroadcast描述的目標(biāo)廣播接收者有可能是靜態(tài)注冊的,而這些靜態(tài)注冊的目標(biāo)廣
            // 播接收者可能還沒有啟動起來,因此AMS將一個(gè)廣播發(fā)送給它們處理時(shí),首先將它們啟動起來。事實(shí)上,
            // AMS只需要將他們所運(yùn)行在的進(jìn)程啟動起來就可以了,因?yàn)楫?dāng)這些進(jìn)程接收到AMS發(fā)送的廣播后,就會
            // 主動將目標(biāo)廣播接收者啟動起來
            // mPendingBroadcast對象是用來描述一個(gè)正在等待靜態(tài)注冊的目標(biāo)廣播接收者啟動起來的廣播轉(zhuǎn)發(fā)任務(wù)的
            if (mPendingBroadcast != null) {
                boolean isDead;
                synchronized (mService.mPidsSelfLocked) {
                    // 檢查目標(biāo)廣播接收者所在進(jìn)程是否已經(jīng)啟動
                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
                    isDead = proc == null || proc.crashing;
                }
                if (!isDead) {// 如果正在啟動,等待
                    // It's still alive, so keep waiting
                    return;
                } else {// 已經(jīng)啟動準(zhǔn)備發(fā)送廣播
                    ...
                }
            }

            boolean looped = false;

            // 逐條處理有序廣播列表mOrderedBroadcasts中的BroadcastRecord
            do {
                // 判斷有序廣播調(diào)度隊(duì)列mOrderedBroadcasts是否還有需要處理的廣播
                if (mOrderedBroadcasts.size() == 0) {// 沒有,說明調(diào)度隊(duì)列中的廣播已經(jīng)處理完成
                    ...
                    return;
                }
                // 如果沒有處理完成,取出下一個(gè)馬上要處理的廣播BroadcastRecord
                r = mOrderedBroadcasts.get(0);
                boolean forceReceive = false;

                // 獲取廣播轉(zhuǎn)發(fā)任務(wù)的目標(biāo)廣播接收者的個(gè)數(shù)
                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
                // 檢查前一個(gè)目標(biāo)廣播接收者是否在規(guī)定的時(shí)間內(nèi)處理完成AMS給它發(fā)送的一個(gè)有序廣播。AMS處理
                // BroadcastRecord對象r所描述的一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)時(shí),會將當(dāng)前時(shí)間記錄在這個(gè)BroadcastRecord
                // 對象中,如果這個(gè)廣播任務(wù)不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒內(nèi)完成,即它的目
                // 標(biāo)廣播接收者不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒內(nèi)完成AMS給它們發(fā)送的一個(gè)有
                // 序廣播,那么會調(diào)用broadcastTimeoutLocked函數(shù)來強(qiáng)制結(jié)束這個(gè)廣播轉(zhuǎn)發(fā)任務(wù),
                if (mService.mProcessesReady && r.dispatchTime > 0) {
                    long now = SystemClock.uptimeMillis();
                    if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) {
                        ...
                        // 出現(xiàn)超時(shí),強(qiáng)制結(jié)束
                        broadcastTimeoutLocked(false); // forcibly finish this broadcast
                        // 重置參數(shù),繼續(xù)處理有序廣播調(diào)度隊(duì)列mOrderedBroadcasts的下一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)
                        forceReceive = true;
                        r.state = BroadcastRecord.IDLE;
                    }
                }

                // 檢測廣播轉(zhuǎn)發(fā)任務(wù)是否正在處理中,即AMS正在將一個(gè)有序廣播轉(zhuǎn)發(fā)給它的前一個(gè)目標(biāo)廣播接收處理者,
                // 如果是,AMS就會等待這個(gè)目標(biāo)廣播接收者處理完該有序廣播,然后再轉(zhuǎn)發(fā)給下一個(gè)廣播接收者處理
                ...

                // 表示廣播已經(jīng)向所有的receiver發(fā)送結(jié)束或者中途被取消, 如果r.resultAbort為true,會停止處理
                // 當(dāng)前正在發(fā)送的BroadcastRecord,這樣優(yōu)先級比較低的接收者也就收不到這個(gè)廣播了
                // 檢查BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)是否已經(jīng)處理完成,或者是否已經(jīng)被強(qiáng)制結(jié)束了。
                // 如果是,那么調(diào)用函數(shù)cancelBroadcastTimeoutLocked來刪除前面發(fā)送到AMS所運(yùn)行在的線程的消息
                // 隊(duì)列中的一個(gè)BROADCAST_TIMEOUT_MSG消息,表示BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)已經(jīng)
                // 在規(guī)定時(shí)間內(nèi)處理完成了。接下來就講改廣播BroadcastRecord對象從隊(duì)列中刪除,然后賦值為null
                if (r.receivers == null || r.nextReceiver >= numReceivers
                        || r.resultAbort || forceReceive) {
                    // No more receivers for this broadcast!  Send the final
                    // result if requested...
                    if (r.resultTo != null) {
                        try {
                            ...
                            performReceiveLocked(r.callerApp, r.resultTo,
                                    new Intent(r.intent), r.resultCode,
                                    r.resultData, r.resultExtras, false, false, r.userId);
                            // Set this to null so that the reference
                            // (local and remote) isn't kept in the mBroadcastHistory.
                            r.resultTo = null;
                        } catch (RemoteException e) {
                            ...    
                        }
                    }
                    ...
                    // ... and on to the next...
                    ...
                    // BroadcastRecord處理完移除
                    mOrderedBroadcasts.remove(0);
                    r = null;
                    looped = true;
                    continue;
                }
            } while (r == null);// 如果第一次取出的r不為空,則退出循環(huán)

            // Get the next receiver...(獲取下一個(gè)將要處理的廣播接收者在其列表中的位置)
            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.
            // 保存當(dāng)前時(shí)間,
            r.receiverTime = SystemClock.uptimeMillis();
            if (recIdx == 0) {// 表示第一個(gè)開始處理的接收者,也就是BroadcastRecord對象r所描述的廣播任務(wù)剛被處理
                // 接收者開始處理的時(shí)間戳,也就是這個(gè)接收者開始處理了,要記錄開始時(shí)間來計(jì)算是否超過超時(shí)時(shí)間
                // 也就是說這是BroadcastRecord中第一個(gè)接收者開始被處理的時(shí)間戳,也就是上面BroadcastRecord
                // 超時(shí)的起點(diǎn),可以看到上面超時(shí)比較的時(shí)候用的就是r.dispatchTime
                r.dispatchTime = r.receiverTime;
                r.dispatchClockTime = System.currentTimeMillis();
                ...
            }
            // 檢查AMS是否已經(jīng)向它所在的線程的消息隊(duì)列發(fā)送了類型為BROADCAST_TIMEOUT_MSG的消息,如果沒有發(fā)送,
            // 那么會調(diào)用setBroadcastTimeoutLocked函數(shù)向這個(gè)線程發(fā)送一個(gè)類型為setBroadcastTimeoutLocked
            // 的消息,并且制定在timeoutTime毫秒后處理。上面指定了r.receiverTime為當(dāng)前時(shí)間表示AMS將一個(gè)有序
            // 廣播發(fā)送給BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)的下一個(gè)目標(biāo)廣播接收者處理的時(shí)間。如果這個(gè)
            // 廣播接收者不能再timeoutTime之內(nèi)完成這個(gè)有序廣播,AMS就會任務(wù)它超時(shí)。
            if (!mPendingBroadcastTimeoutMessage) {
                long timeoutTime = r.receiverTime + mTimeoutPeriod;
                ...
                // 設(shè)置超時(shí),傳入?yún)?shù)是r.receiverTime + mTimeoutPeriod,也就是開始時(shí)間加上超時(shí)時(shí)間
                // mTimeoutPeriod,mTimeoutPeriod初始化是在BroadcastQueue初始化的時(shí)候傳入的,
                // 也就是在AMS(AMS構(gòu)造函數(shù)中)中初始化mFgBroadcastQueue和mBgBroadcastQueue時(shí)傳入的
                // BROADCAST_FG_TIMEOUT = 10 * 1000和BROADCAST_BG_TIMEOUT = 60 * 1000,
                // 這里開始埋了ANR的雷
                setBroadcastTimeoutLocked(timeoutTime);
            }

            // 上面分析的時(shí)候?qū)τ贐roadcastRecord.receivers里面包含兩種receiver接收者:order廣播下的
            // 動態(tài)注冊接收者和靜態(tài)接收者,這兩種receiver處理的方式是不一樣的,對于order廣播下的動態(tài)注冊
            // receiver而言,接收者進(jìn)程一定是已經(jīng)啟動的,但是對于靜態(tài)接收者receiver而言,當(dāng)前的receiver進(jìn)程
            // 可能還沒有啟動,因此動態(tài)和靜態(tài)的receiver處理的邏輯不一樣,需要分開處理,而靜態(tài)接收者又分為進(jìn)程
            // 已經(jīng)啟動和尚未啟動兩種情況。

            final BroadcastOptions brOptions = r.options;
            // 得到下一個(gè)廣播接收者
            final Object nextReceiver = r.receivers.get(recIdx);

            // 如果當(dāng)前nextReceiver是一個(gè)BroadcastFilter類型,說名是一個(gè)動態(tài)注冊接收者,不需要啟動一個(gè)進(jìn)程,
            // 直接調(diào)用deliverToRegisteredReceiverLocked函數(shù)發(fā)送廣播
            if (nextReceiver instanceof BroadcastFilter) {
                // Simple case: this is a registered receiver who gets
                // a direct call.
                BroadcastFilter filter = (BroadcastFilter) nextReceiver;
                ...
                // 上面已經(jīng)分析
                deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
                // 檢查BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)是否用來轉(zhuǎn)發(fā)無序廣播的。
                if (r.receiver == null || !r.ordered) {// 如果是
                    ...
                    // 設(shè)置IDLE狀態(tài),表示AMS不需要等待它的前一個(gè)目標(biāo)廣播接收者處理完成一個(gè)廣播就可以將該廣播
                    // 繼續(xù)發(fā)送給它的下一個(gè)目標(biāo)廣播接收者處理
                    r.state = BroadcastRecord.IDLE;
                    // 調(diào)用下面函數(shù)就是為了將一個(gè)廣播繼續(xù)發(fā)送給BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)的
                    // 下一個(gè)目標(biāo)廣播接收者處理的
                    scheduleBroadcastsLocked();
                } else {
                    ...
                }
                return;
            }

            // Hard case: need to instantiate the receiver, possibly
            // starting its application process to host it.
            // 如果不是動態(tài)的說明是一個(gè)靜態(tài)注冊接收者(如果動態(tài)的上面if中處理并進(jìn)行攔截),此時(shí)進(jìn)程可能沒有啟動
            ResolveInfo info =
                    (ResolveInfo) nextReceiver;
            ComponentName component = new ComponentName(
                    info.activityInfo.applicationInfo.packageName,
                    info.activityInfo.name);

            // 是否跳過該廣播接收者不處理
            boolean skip = false;
            ...
            // 得到ResolveInfo對象info所描述的廣播接收者的android:process屬性值,即它需要運(yùn)行在的應(yīng)用程序
            // 進(jìn)程的名稱,并且保存在變量targetProcess中
            String targetProcess = info.activityInfo.processName;
            // 獲取當(dāng)前廣播接收者的進(jìn)程記錄,也就是該靜態(tài)廣播接收者是否已經(jīng)運(yùn)行
            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);

            ...

            // 跳過,恢復(fù)初始狀態(tài),開始下一個(gè)廣播接收者的處理
            if (skip) {
                ...
                return;
            }

            r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
            r.state = BroadcastRecord.APP_RECEIVE;
            r.curComponent = component;
            r.curReceiver = info.activityInfo;
            ...
            if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                scheduleTempWhitelistLocked(receiverUid,
                        brOptions.getTemporaryAppWhitelistDuration(), r);
            }

            // Broadcast is being executed, its package can't be stopped.
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
            } catch (RemoteException e) {
            } catch (IllegalArgumentException e) {
                ...
            }

            // Is this receiver's application already running?
            // 如果當(dāng)前進(jìn)程已經(jīng)運(yùn)行,則直接發(fā)給該進(jìn)程,然后返回
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(info.activityInfo.packageName,
                            info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                    // 將廣播發(fā)送給該進(jìn)程處理
                    processCurBroadcastLocked(r, app);
                    // order廣播是一種同步處理方式,因此處理完可以直接return
                    return;
                } catch (RemoteException e) {
                    ...
                } catch (RuntimeException e) {
                    ...
                    return;
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
            ...
            // 靜態(tài)接收者進(jìn)程尚未啟動,調(diào)用AMS的startProcessLocked函數(shù)啟動該接收者進(jìn)程,并將當(dāng)前正在等待進(jìn)程
            // 啟動的BroadcastRecord存儲到mPendingBroadcast里面,這個(gè)就是靜態(tài)廣播拉起應(yīng)用的原理,如果應(yīng)用
            // 沒有啟動,注冊一個(gè)靜態(tài)廣播(一般廠商會修改只能啟動自己的應(yīng)用)。到這里又開始進(jìn)入等待進(jìn)程啟動的
            // 過程,進(jìn)程啟動完成后才能處理廣播
            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))
                    == null) {// 如果啟動失敗
                ...
                logBroadcastReceiverDiscardLocked(r);
                // 結(jié)束廣播發(fā)送任務(wù)
                finishReceiverLocked(r, r.resultCode, r.resultData,
                        r.resultExtras, r.resultAbort, false);
                scheduleBroadcastsLocked();
                r.state = BroadcastRecord.IDLE;
                return;
            }

            // 正在啟動接收者進(jìn)程,將正在啟動的BroadcastRecord記錄存儲到mPendingBroadcast中,同時(shí)將當(dāng)前正在
            // 啟動的接收者進(jìn)程在所有接收者中的索引存儲到mPendingBroadcastRecvIndex,如果當(dāng)前廣播接收者處理
            // 完,需要繼續(xù)從mPendingBroadcastRecvIndex計(jì)算到下一個(gè)接收者發(fā)送當(dāng)前廣播
            mPendingBroadcast = r;
            mPendingBroadcastRecvIndex = recIdx;
        }
    }

我們根據(jù)第五步的發(fā)送消息類型可以跟蹤到,消息執(zhí)行是在BroadcastHandler的handleMessage方法中調(diào)用的,這里出入一個(gè)參數(shù)fromMsg,也就是該廣播是不是通過Handler發(fā)送消息的方式傳遞的,那么我們上面知道我們這就是通過這種方式執(zhí)行的,所以在代碼中會將mBroadcastsScheduled參數(shù)設(shè)置為false,也就是這個(gè)消息開始執(zhí)行了則開始運(yùn)行下一個(gè)消息發(fā)送。還有就是通過直接調(diào)用的方式來執(zhí)行的,那么就不會改變這個(gè)參數(shù)。

接著看,先執(zhí)行無序廣播,無序廣播接收者不需要等待,所以直接for循環(huán)執(zhí)行,調(diào)用deliverToRegisteredReceiverLocked方法發(fā)送廣播。

7、deliverToRegisteredReceiverLocked

    // AMS將一個(gè)廣播發(fā)給一個(gè)目標(biāo)廣播接收者之前,有可能需要檢查這個(gè)廣播的發(fā)送者和接收者的權(quán)限。這個(gè)權(quán)限檢查是
    // 雙向的,即需要檢查一個(gè)廣播發(fā)送者是否有權(quán)限向一個(gè)目標(biāo)廣播接收者發(fā)送廣播,以及一個(gè)目標(biāo)廣播接收者是否有權(quán)限
    // 接收一個(gè)廣播發(fā)送者發(fā)過來的一個(gè)廣播。這兩個(gè)權(quán)限主要是調(diào)用AMS的成員函數(shù)checkComponentPermission來檢查
    // 對方的PID以及UID是否符合要求
    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                   BroadcastFilter filter, boolean ordered, int index) {
        // 標(biāo)記是否要跳過該廣播接收者
        boolean skip = false;
        // 需要檢查廣播發(fā)送者的權(quán)限
        ...
        // r.requiredPermissions != null為true表示需要檢查廣播接收者的權(quán)限
        ...
        // 如果要跳過,則設(shè)置該廣播結(jié)束
        if (skip) {
            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
            return;
        }

        ...
        // order廣播,所有的接收者需要依次以一種同步的方式發(fā)送廣播,
        // 可以看到order廣播在BroadcastRecord保存了幾個(gè)狀態(tài)
        if (ordered) {
            // IBinder類型,代表當(dāng)前的接收者
            r.receiver = filter.receiverList.receiver.asBinder();
            // 當(dāng)前正在處理的BroadcastFilter,和上面的receiver是對應(yīng)好的
            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.curReceiver = r;
                mService.updateOomAdjLocked(r.curApp);
            }
        }
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // 如果正在備份或者恢復(fù)備份跳過,
                // 如果是一個(gè)有序廣播,則執(zhí)行下一個(gè)廣播
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                // 如果不需要進(jìn)行權(quán)限檢查或者通過權(quán)限檢查,調(diào)用performReceiveLocked發(fā)送廣播
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            ...
        } catch (RemoteException e) {
            ...
        }
    }

我們這里不是有序廣播,正常也不會備份,所以會走else里面的方法performReceiveLocked。如果是有序廣播我們后面再分析

8、performReceiveLocked

    /**
     * 由前面可知,當(dāng)一個(gè)Activity或者一個(gè)Service將一個(gè)廣播接收者注冊到AMS中時(shí),它所在的應(yīng)用程序進(jìn)程會先將
     * 這個(gè)廣播接收者封裝成一個(gè)類型為InnerReceiver的Binder本地對象,然后再注冊到AMS中。因此當(dāng)AMS要將一個(gè)
     * 廣播發(fā)給一個(gè)目標(biāo)廣播接收者處理時(shí),實(shí)際上是將這個(gè)廣播轉(zhuǎn)發(fā)給封裝了這個(gè)目標(biāo)廣播接收者的一個(gè)InnerReceiver
     * 對象來處理
     * <p>
     * AMS向一個(gè)應(yīng)用程序進(jìn)程發(fā)送一個(gè)廣播時(shí),采用的是異步進(jìn)程間通信方式。前面提到,發(fā)送給一個(gè)Binder實(shí)體對象
     * 的所有異步事物都是保存在一個(gè)異步事物隊(duì)列中的。由于保存在一個(gè)異步事物隊(duì)列中的異步事物在同一時(shí)刻只有一
     * 個(gè)會得到處理,即只有隊(duì)列頭部的異步事物才會得到處理,因此AMS就可以保證它發(fā)送給同一個(gè)應(yīng)用程序的所有廣
     * 播都是按照這個(gè)發(fā)送順序來串行的被接受和處理
     */
    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
                              Intent intent, int resultCode, String data, Bundle extras,
                              boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        // app不為空,表示進(jìn)程已經(jīng)啟動,調(diào)用ActivityThread.scheduleRegisteredReceiver發(fā)送當(dāng)前廣播
        if (app != null) {
            if (app.thread != null) {// 因?yàn)槭莿討B(tài)注冊廣播,所以一般不為空
                try {
                    // 這里scheduleRegisteredReceiver函數(shù)是一個(gè)Binder調(diào)用,注釋上面說的很清楚,
                    // 要用one-way calls像動態(tài)的注冊進(jìn)程發(fā)起B(yǎng)inder調(diào)用,意思就是在Binder調(diào)用里面會
                    // 加上IBinder.FLAG_ONEWAY標(biāo)記,Binder客戶端(動態(tài)注冊進(jìn)程)只要一收到Binder調(diào)用的
                    // 命令和數(shù)據(jù),立馬返回到Binder服務(wù)端(AMS進(jìn)程),是一個(gè)異步的調(diào)用方式。
                    // 大致流程是:
                    // 1) ApplicationThreadNative.ApplicationThreadProxy. scheduleRegisteredReceiver(system_server)
                    // 2) Binder驅(qū)動 (Binder驅(qū)動進(jìn)程,ONEWAY)
                    // 3)ApplicationThreadNative. scheduleRegisteredReceiver(應(yīng)用進(jìn)程,Binder線程向主線程發(fā)送消息)
                    // 4)Binder驅(qū)動返回 (Binder驅(qū)動進(jìn)程)
                    // 5)ActivityThread. scheduleRegisteredReceiver(應(yīng)用進(jìn)程,處理消息)
                    // 調(diào)用ApplicationThread對象的Binder代理對象的函數(shù)來向它發(fā)送廣播
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                    ...
                } catch (RemoteException ex) {
                    ...
                }
            } else {
                ...
            }
        } else {
            // 直接調(diào)用與它關(guān)聯(lián)的一個(gè)InnerReceiver對象的Binder代理對象的成員函數(shù)performReceive來向它發(fā)送廣播
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

如果進(jìn)程存在,則執(zhí)行ActivityThread.scheduleRegisteredReceiver方法,否則直接調(diào)用receiver.performReceive方法發(fā)送廣播。因?yàn)槲覀儎討B(tài)注冊的所以會執(zhí)行第一種情況。

9、ActivityThread.scheduleRegisteredReceiver

        // 處理非串行化動態(tài)廣播,非串化ordered是false,這里的receiver對應(yīng)的是
        // LoadedApk.ReceiverDispatcher.InnerReceiver對象
        // This function exists to make sure all receiver dispatching is
        // correctly ordered, since these are one-way calls and the binder driver
        // applies transaction ordering per object for such calls.
        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);
            // 調(diào)用LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive函數(shù)
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

這里我們看到和上面一樣最終還是執(zhí)行receiver.performReceive方法來發(fā)送廣播。

10、LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive

            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                                       Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                final LoadedApk.ReceiverDispatcher rd;
                ...
                    rd = mDispatcher.get();
                ...
                if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    ...
                    try {
                        ...
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        ...
                    }
                }
            }
        }

我們上一章注冊廣播是講過LoadedApk.ReceiverDispatcher對象封裝了廣播接收者,如果該廣播接收者注冊了,那么該對象就會存在,則會調(diào)用LodedApk.ReceiverDispatcher.performReceive,否則調(diào)用AMS.finishReceiver方法,我們先看有廣播的情況。

11、LodedApk.ReceiverDispatcher.performReceive

        public void performReceive(Intent intent, int resultCode, String data,
                                   Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            // 首先將參數(shù)Intent所描述的一個(gè)廣播封裝成一個(gè)Args對象,然后將這個(gè)Args對象封裝成一個(gè)消息對象,
            // 然后將這個(gè)消息對象發(fā)送到應(yīng)用程序主線程的消息隊(duì)列中。
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            // 將當(dāng)前廣播信息放到主線程的Handler中進(jìn)行處理,作為一個(gè)Runnable調(diào)度而不是在handleMessage中處理,
            // 而是在Handler內(nèi)部機(jī)制中,處理的時(shí)候會對應(yīng)run函數(shù),因此這里不久后會調(diào)用Args.run函數(shù)
            ..
            // 上面將廣播的參數(shù)封裝在一個(gè)Args對象里面,然后通過post到主線程的消息隊(duì)列里面
            if (intent == null || !mActivityThread.post(args)) {
                if (mRegistered && ordered) {
                    ...
                    args.sendFinished(mgr);
                }
            }
        }

上面初始化了一個(gè)Args對象,該對象實(shí)現(xiàn)了Runnable接口,在if語句中調(diào)用post方法,會調(diào)用Args中的run方法。

13、Args.run

            public void run() {
                // mReceiver指向一個(gè)廣播接收者
                final BroadcastReceiver receiver = mReceiver;
                ...
                // 這里處理的是動態(tài)廣播接收者,默認(rèn)認(rèn)為接收者BroadcastReceiver已經(jīng)存在
                try {
                    ...
                    // 接受廣播
                    receiver.onReceive(mContext, intent);
                    // 然后調(diào)用BroadcastReceiver.PendingResult.finish函數(shù),也就是下面的finish函數(shù)
                } catch (Exception e) {
                    // 檢查當(dāng)前廣播是否是有序廣播,并且廣播接收者是否已經(jīng)注冊到AMS中
                    if (mRegistered && ordered) {
                        // 通知AMS,它前面轉(zhuǎn)發(fā)過來的有序廣播已經(jīng)處理完了,這時(shí)AMS就可以繼續(xù)將這個(gè)有序廣播
                        // 轉(zhuǎn)發(fā)給下一個(gè)目標(biāo)廣播接收者了
                        sendFinished(mgr);
                    }
                    ...
                }

                ...
            }

在這里調(diào)用BroadcastReceiver.onReceive方法,這樣就會執(zhí)行完一次無需廣播發(fā)送過程。我們再回到第10步,如果對象接收者不存在則調(diào)用AMS.finishReceiver

15、AMS.finishReceiver

    public void finishReceiver(IBinder who, int resultCode, String resultData,
                               Bundle resultExtras, boolean resultAbort, int flags) {
        ...
        try {
            boolean doNext = false;
            BroadcastRecord r;

            // 首先辨別出當(dāng)前receiver所在的BroadcastRecord屬于前臺廣播還是后臺廣播,然后在對應(yīng)的
            // BroadcastQueue中找出對應(yīng)的BroadcastRecord,里面的finishReceiverLocked函數(shù)在前面介紹過,
            // 主要是重新設(shè)置BroadcastRecord里面一些狀態(tài)變量,以便于BroadcastRecord將廣播發(fā)送給下一個(gè)
            // 接收者。尤其的,如果前面的mAbortBroadcast設(shè)置為true,那么BroadcastRecord的成員resultAbort
            // 會設(shè)置成true
            synchronized (this) {
                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
                r = queue.getMatchingOrderedReceiver(who);
                // 結(jié)束當(dāng)前正在發(fā)送的廣播
                if (r != null) {
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                            resultData, resultExtras, resultAbort, true);
                }
            }

            // 立馬調(diào)度一次發(fā)送廣播,發(fā)送下一次廣播,但是processNextBroadcast是一個(gè)同步函數(shù),
            // 一次只能處理一個(gè)請求
            if (doNext) {
                r.queue.processNextBroadcast(false);
            }
            ...
        } finally {
            ...
        }
    }

這里是如果發(fā)送廣播時(shí)接收者不存在,那么要完成該次廣播,并且判斷是否執(zhí)行發(fā)送給下一個(gè)廣播接收者,如果需要發(fā)送給下個(gè)廣播接收者要再次調(diào)用BroadcastQueue.processNextBroadcast方法。這樣就又回到了前面第六步。我們再往前看BroadcastQueue.processNextBroadcast方法,執(zhí)行完無序廣播后開始執(zhí)行有序廣播,因?yàn)橛行驈V播是一個(gè)執(zhí)行完再執(zhí)行下一個(gè)所以必須設(shè)置超時(shí),并且如果超時(shí)要立即接受廣播,

17、broadcastTimeoutLocked

    /**
     * AMS在處理order模式廣播接收者時(shí),會為每一個(gè)order模式廣播處理設(shè)置超時(shí)時(shí)間,并且超時(shí)時(shí)間是各個(gè)接收者之間
     * 相互獨(dú)立,前面分析超時(shí)通過setBroadcastTimeoutLocked函數(shù)建立超時(shí)時(shí)間點(diǎn)消息的,本以為每次處理完以后,
     * 調(diào)用cancelBroadcastTimeoutLocked函數(shù)取消當(dāng)前接收者的超時(shí)消息,但是實(shí)際上用了一種更加高效的方法處理了
     * 超時(shí)機(jī)制,在每個(gè)order模式receiver開始處理的時(shí)候設(shè)置超時(shí)消息,BroadcastRecord.receiverTime記錄了
     * 當(dāng)前receiver開始處理的時(shí)間點(diǎn)
     * <p>
     * BroadcastRecord超時(shí):注意這里的超時(shí)和我們常說的廣播超時(shí)ANR不是一個(gè)概念,這個(gè)BroadcastRecord超時(shí)是針
     * 對當(dāng)前BroadcastRecord. receivers里面剩余的所有的成員而言的,比如說當(dāng)前receivers里面剩余4個(gè)廣播接收者,
     * 那么這個(gè)超時(shí)的時(shí)間: 2*(4*mTimeoutPeriod) 至于這個(gè)mTimeoutPeriod,對于前臺廣播mFgBroadcastQueue
     * 和mBgBroadcastQueue后臺廣播時(shí)間:BROADCAST_FG_TIMEOUT = 10 * 1000
     * 和BROADCAST_BG_TIMEOUT = 60 * 1000(AMS中),也就是對于有4個(gè)成員的receivers 后臺廣播的
     * BroadcastRecord而言超時(shí)的時(shí)間為:2*(4*10*1000)=80 000ms=80s,當(dāng)出現(xiàn)這種超時(shí)的時(shí)候,當(dāng)前正在處理的
     * 廣播接收者會出現(xiàn)ANR,并且導(dǎo)致后面尚未接收到廣播的收不到當(dāng)前的廣播。broadcastTimeoutLocked函數(shù)會將
     * mOrderedBroadcasts中下標(biāo)為0的應(yīng)用進(jìn)程ANR,下面forceReceive設(shè)置為true,走到下面的if判斷里面會將當(dāng)前
     * 正在處理的BroadcastRecord從mOrderedBroadcasts中remove掉,導(dǎo)致receivers后面的成員沒有收到廣播,
     * 并且將r設(shè)置為null,接著就處理broadcastTimeoutLocked里面的下一個(gè)廣播記錄BroadcastRecord。例如,
     * receivers里面包含4個(gè)成員,但是第1個(gè)接收者在80s內(nèi)都沒有處理完,那么這個(gè)接收者進(jìn)程會收到ANR,
     * 并且后面的3個(gè)廣播接收者都收不到當(dāng)前的廣播。
     * <p>
     * 注釋來自于:http://blog.csdn.net/houliang120/article/details/51607170
     *
     * @param fromMsg
     */
    final void broadcastTimeoutLocked(boolean fromMsg) {
        ...
        long now = SystemClock.uptimeMillis();
        BroadcastRecord r = mOrderedBroadcasts.get(0);
        if (fromMsg) {
            if (mService.mDidDexOpt) {
                ...
                long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
                setBroadcastTimeoutLocked(timeoutTime);
                return;
            }
            ...

            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            // 舉個(gè)例子:
            // 假設(shè)receiverA在100s的時(shí)候開始處理,超時(shí)時(shí)間為10s,那么receiverA的超時(shí)時(shí)間點(diǎn)就是110s,
            // 但是receiverA在105s的時(shí)候已經(jīng)處理完了,于是在105s的時(shí)候開始receiverB,但是并沒有取消
            // receiverA的超時(shí)消息,也就是在110s的時(shí)候仍然會走到這里的broadcastTimeoutLocked函數(shù),
            // receiverB開始處理,這時(shí)候r.receiverTime就是105s,對于receiverB而言超時(shí)時(shí)間應(yīng)該是115s,
            // 假設(shè)receiverB需要在112s才能處理完,在110s的時(shí)候broadcastTimeoutLocked函數(shù)處理的時(shí)候
            // timeoutTime=115s,now=110s,這時(shí)候不會進(jìn)行實(shí)際的超時(shí)處理,因?yàn)檫€沒有到真實(shí)的超時(shí)時(shí)間,
            // 所以重新設(shè)置超時(shí)時(shí)間點(diǎn)在115s。就這樣根據(jù)當(dāng)前BroadcastRecord.receiverTime的時(shí)間反復(fù)調(diào)整。
            if (timeoutTime > now) {// 判斷超時(shí)時(shí)間點(diǎn)和現(xiàn)在時(shí)間的關(guān)系,此處還沒有超時(shí)
                // We can observe premature timeouts because we do not cancel and reset the
                // broadcast timeout message after each receiver finishes.  Instead, we set up
                // an initial timeout then kick it down the road a little further as needed
                // when it expires.
                // 因?yàn)闆]有在每個(gè)廣播處理完之后取消或者重置超時(shí)時(shí)間,從而導(dǎo)致提前檢測到超時(shí)消息。取而代之,
                // 設(shè)置一個(gè)初始超時(shí)時(shí)間點(diǎn),然后每次出現(xiàn)超時(shí)事件的時(shí)候根據(jù)需要進(jìn)行處理或者調(diào)整超時(shí)機(jī)制。
                ...
                setBroadcastTimeoutLocked(timeoutTime);
                return;
            }
        }

        BroadcastRecord br = mOrderedBroadcasts.get(0);
        if (br.state == BroadcastRecord.WAITING_SERVICES) {
            ...
            processNextBroadcast(false);
            return;
        }
        ...
    }

這里主要是超時(shí)的處理,因?yàn)樽⑨屢呀?jīng)非常詳細(xì),所以不再解釋,所以我們在寫廣播接收到消息是最后采用Handler或者啟動服務(wù)將消息處理的過程放到Handler中或者服務(wù)中,而不是直接在廣播接收者中完成。

18、setBroadcastTimeoutLocked

    // 設(shè)置超時(shí)時(shí)間
    final void setBroadcastTimeoutLocked(long timeoutTime) {
        if (!mPendingBroadcastTimeoutMessage) {
            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
            mHandler.sendMessageAtTime(msg, timeoutTime);
            mPendingBroadcastTimeoutMessage = true;
        }
    }

如果廣播還沒有超時(shí)就執(zhí)行完了就從新設(shè)置下一個(gè)廣播的起始時(shí)間,方便計(jì)算下一個(gè)廣播的超時(shí)。這個(gè)消息處理就不分析了,自己看一下。再回到第六步BroadcastQueue.processNextBroadcast方法中,如果廣播發(fā)送完成,或者被中斷或者取消,則判斷是否發(fā)送最后的廣播,如果要發(fā)送,則執(zhí)行performReceiveLocked方法,這個(gè)方法在第八步講了,這里就不再重復(fù)分析。我們知道廣播有靜態(tài)廣播接收者和動態(tài)廣播接收者,動態(tài)廣播接收者進(jìn)程都是啟動的,但是靜態(tài)的就不一定了,可能進(jìn)程還沒有啟動,就想第六步中代碼注釋分析的一樣,我們上面處理的都是動態(tài)注冊的,不需要判斷進(jìn)程是否已經(jīng)啟動,但是靜態(tài)廣播就需要判斷該進(jìn)程是否已經(jīng)啟動了。這里的ResolveInfo表示靜態(tài)廣播接收者對象。找到對象后判斷是否要跳過該廣播,如果跳過則通過執(zhí)行scheduleBroadcastsLocked方法發(fā)送消息執(zhí)行下一個(gè)廣播。如果不需要跳過該廣播時(shí),判斷該進(jìn)程是否存在,如果該靜態(tài)廣播的進(jìn)程已經(jīng)存在了則執(zhí)行processCurBroadcastLocked,將廣播發(fā)送給該進(jìn)程處理,如果不存在則啟動進(jìn)程,并且將廣播對象BroadcastRecord放入等待廣播列表中,如果啟動失敗則接受該廣播并判斷是否執(zhí)行下一個(gè)廣播,我們先將一下進(jìn)程存在時(shí)廣播的處理,最后再分析進(jìn)程啟動時(shí)的廣播處理。

21、processCurBroadcastLocked

    // 這里只是將廣播發(fā)送到接收者進(jìn)程,需要一直等待接收者進(jìn)程處理完廣播后返回,AMS才能處理當(dāng)前BroadcastRecord
    // 里面的下一個(gè)receiver,所以直接返回就行了,反正需要等待的。
    private final void processCurBroadcastLocked(BroadcastRecord r,
                                                 ProcessRecord app) throws RemoteException {
        ...

        // 將進(jìn)程的相關(guān)信息寫入當(dāng)前BroadcastRecord中相關(guān)的接收者
        ...

        boolean started = false;
        try {
            ...
            // 處理廣播,等待接收進(jìn)程的返回
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
            ...
        } finally {
            ...
        }
    }

調(diào)用scheduleReceiver方法處理廣播。

22、ApplicationThread.scheduleReceiver

        // 處理應(yīng)用進(jìn)程中接收到的靜態(tài)廣播消息,實(shí)際處理該廣播的是ActivityThread.handleReceiver函數(shù)
        public final void scheduleReceiver(Intent intent, ActivityInfo info,
                                           CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                                           boolean sync, int sendingUser, int processState) {
            updateProcessState(processState, false);
            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
                    sync, false, mAppThread.asBinder(), sendingUser);
            ..
            sendMessage(H.RECEIVER, r);
        }

通過Handler消息處理機(jī)制調(diào)用handleReceiver方法處理該靜態(tài)廣播

23、ApplicationThread.handleReceiver

    // 主要包括三步:
    // 1) 創(chuàng)建BroadcastReceiver對象
    // 2) 執(zhí)行onReceive函數(shù)
    // 3) 向AMS發(fā)送處理結(jié)束消息
    private void handleReceiver(ReceiverData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        // 1) 創(chuàng)建BroadcastReceiver對象
        // 這里處理的是靜態(tài)廣播接收者,默認(rèn)認(rèn)為接收者BroadcastReceiver對象不存在
        // 每次接受都會創(chuàng)建一個(gè)新的BroadcastReceiver對象
        String component = data.intent.getComponent().getClassName();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);

        IActivityManager mgr = ActivityManagerNative.getDefault();

        BroadcastReceiver receiver;
        try {
            // 首先從AMS傳遞的intent中獲取當(dāng)前處理該廣播的組件名稱,然后通過反射創(chuàng)建一個(gè)BroadcastReceiver
            // 對象,從這里可以看出來,靜態(tài)廣播處理的時(shí)候,每次都會創(chuàng)建一個(gè)新的BroadcastReceiver對象;
            ...
            receiver = (BroadcastReceiver) cl.loadClass(component).newInstance();
        } catch (Exception e) {
            ...
        }

        // 2) 執(zhí)行onReceive函數(shù)
        try {
            // 創(chuàng)建Application對象,如果進(jìn)程已經(jīng)啟動,Application對象已經(jīng)創(chuàng)建
            Application app = packageInfo.makeApplication(false, mInstrumentation);

            ...
            // 調(diào)用接收者的onReceive方法,這里還調(diào)用了setPendingResult方法,詳細(xì)內(nèi)容請看
            // BroadcastReceiver.goAsync方法。
            receiver.setPendingResult(data);
            receiver.onReceive(context.getReceiverRestrictedContext(),
                    data.intent);
        } catch (Exception e) {
            ...
        } finally {
            sCurrentBroadcastIntent.set(null);
        }

        // 3) 向AMS發(fā)送處理結(jié)束消息
        if (receiver.getPendingResult() != null) {
            data.finish();
        }
    }

上面最開始注釋寫了這里分為三步,創(chuàng)建BroadcastReceiver對象,執(zhí)行onReceive函數(shù),結(jié)束。這樣進(jìn)程存在時(shí)靜態(tài)廣播就發(fā)送完成了。最后我們分析需要啟動進(jìn)程時(shí)發(fā)送廣播的流程,我們先看一張時(shí)序圖。

sendBroadcast2.jpg

Android系統(tǒng)源碼分析--Process啟動過程一章我們分析了進(jìn)程啟動過程,在最后會調(diào)用ActivityThread.mian方法,我們從這個(gè)方法開始看:

0、ActivityThread.mian

    /**
     * 啟動新的進(jìn)程時(shí)調(diào)用Process的start方法會最終調(diào)用改函數(shù)
     * 啟動新的進(jìn)程主要做了兩件事:
     * 1.在進(jìn)程中創(chuàng)建了一個(gè)ActivityThread對象,并調(diào)用了它的成員函數(shù)attach向AMS發(fā)送一個(gè)啟動完成的通知
     * 2.調(diào)用Looper類的靜態(tài)成員函數(shù)prepareMainLooper創(chuàng)建一個(gè)消息循環(huán),并且在向AMS發(fā)送啟動完成通知后,
     *   使得當(dāng)前進(jìn)程進(jìn)入到這個(gè)消息循環(huán)中
     *
     * @param args
     */
    public static void main(String[] args) {
        ...
        
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        ...
    }

這里會初始化一個(gè)ActivityThread對象,然后調(diào)用該對象的attach方法,傳入?yún)?shù)false。

1、ActivityThread.attach

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
            // 獲取AMS的代理對象,下面會調(diào)用它的成員函數(shù)attachApplication向AMS發(fā)送一個(gè)進(jìn)程間通信請求,并且
            // 將前面所創(chuàng)建的ApplicationThread(mAppThread)對象傳遞給AMS
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                // 這里向ActivityManagerService注冊Client端的binder對象,它是一個(gè)binder線程
                // ActivityManagerService中有關(guān)Activity聲明周期的消息都會發(fā)送到ActivityThread中的
                // 主線程mH處理
                // mAppThread是一個(gè)Binder本地對象,AMS是通過它來和應(yīng)用進(jìn)程通訊的。(AMS的代理對象類型為
                // ActivityManagerProxy,因此,接下來會調(diào)用ActivityManagerProxy類的成員函數(shù)向AMS發(fā)送一個(gè)
                // 進(jìn)程間通信請求)
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        } else {// system thread
            ...
        }

        ...
    }

我們上面接受了傳入?yún)?shù)是false,則會走if中的代碼,也就是會執(zhí)行mgr.attachApplication方法,通過注釋我們知道會調(diào)用ActivityManagerProxy.attachApplication方法,然后傳遞到ActivityManagerService.attachApplication方法。

2、ActivityManagerProxy.attachApplication

    public void attachApplication(IApplicationThread app) throws RemoteException {
        ...
        // 通過mRemote(Binder)向AMS發(fā)送一個(gè)類型為ATTACH_APPLICATION_TRANSACTION的進(jìn)程間通信請求
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        ...
    }

3、ActivityManagerService.attachApplication

    // 用來處理ActivityMangerProxy傳遞過來的類型為ATTACH_APPLICATION_TRANSACTION的進(jìn)程間通信請求
    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            ...
            attachApplicationLocked(thread, callingPid);
            ...
        }
    }

這里調(diào)用attachApplicationLocked方法:

4、attachApplicationLocked

    private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid) {

        ...
        // Check if a next-broadcast receiver is in this process...
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                didSomething |= sendPendingBroadcastsLocked(app);
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }
        ...
    }

因?yàn)槲覀冞@里分析發(fā)送廣播,所以我們只關(guān)心廣播的相關(guān)處理,所以上面只保留了廣播的內(nèi)容,if語句中判斷當(dāng)前應(yīng)用沒有問題,并且有等待的廣播,才會調(diào)用sendPendingBroadcastsLocked方法,前面我們知道靜態(tài)廣播有一種是進(jìn)程不存在的,所以這個(gè)廣播就要放到等待廣播中,這里就開始處理等待廣播的情況。

5、sendPendingBroadcastsLocked

    // The app just attached; send any pending broadcasts that it should receive
    boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        for (BroadcastQueue queue : mBroadcastQueues) {
            didSomething |= queue.sendPendingBroadcastsLocked(app);
        }
        return didSomething;
    }

mBroadcastQueues是包含前臺優(yōu)先級和后臺優(yōu)先級的廣播隊(duì)列,這里分別調(diào)用前臺和后臺優(yōu)先級廣播的BroadcastQueue.sendPendingBroadcastsLocked方法。

6、BroadcastQueue.sendPendingBroadcastsLocked

    // 未啟動進(jìn)程的廣播接收者需要先啟動進(jìn)程,最后到達(dá)這個(gè)函數(shù)
    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        // 前面分析mPendingBroadcast用于存儲當(dāng)前正在等待進(jìn)程啟動的BroadcastRecord
        final BroadcastRecord br = mPendingBroadcast;
        if (br != null && br.curApp.pid == app.pid) {
            ...
            try {
                // 啟動完成設(shè)置為null
                mPendingBroadcast = null;
                processCurBroadcastLocked(br, app);
                didSomething = true;
            } catch (Exception e) {
                ...
            }
        }
        return didSomething;
    }

這里是找到等待處理的廣播并且判斷是否為空,并且是否和當(dāng)前進(jìn)程的pid相同,也就是是不是找個(gè)進(jìn)程的等待廣播,如果是就調(diào)用processCurBroadcastLocked方法進(jìn)行處理,這個(gè)方法在上面第21步中已經(jīng)講過,所以又回到了進(jìn)程存在的情況下廣播的處理。這樣整個(gè)廣播的處理就分析完了,代碼量很大,但是邏輯很清楚,只需要對著注釋多看看看就明白了。下一篇我們開始講Activity啟動的源碼分析。

flowsendbroadcast.jpg

為了方便記憶,這里添加一個(gè)發(fā)送廣播的流程圖,這樣對照著上面的代碼流程再看就會好理解很多。

首發(fā)地址:http://www.codemx.cn

Android開發(fā)群:192508518

微信公眾賬號:Code-MX

注:本文原創(chuàng),轉(zhuǎn)載請注明出處,多謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,654評論 19 139
  • 昨天發(fā)表了一條說說,召喚小伙伴們一起寫作,欣慰的是得到了朋友的支持,他們也表示會響應(yīng)。對于時(shí)常感到孤獨(dú)的我來說,這...
    殘劍閱讀 299評論 2 1
  • 迷迷糊糊從清晨的余夢中轉(zhuǎn)醒,頭微微一轉(zhuǎn),枕著胳膊趴在床沿上看陽光從窗臺傾瀉入內(nèi),感覺這一刻有種說不出的好:時(shí)...
    叮拾玖閱讀 238評論 0 0
  • 都說人到中年,應(yīng)該做減法了,但是減法如何做,減多少,先減思想,還是先減事務(wù),卻是見仁見智的事。 晚上,同學(xué)聚會,一...
    阿渡SZ閱讀 459評論 0 0
  • 大家好,今天是2017年10月12日 是阿昌每天一篇原創(chuàng)日記的 第70篇 一到書店,就像打了雞血,怎么會有這么多牛...
    陪伴家阿昌閱讀 450評論 0 1

友情鏈接更多精彩內(nèi)容