1. 程式人生 > 其它 >Android R 廣播發送流程

Android R 廣播發送流程

Android R 廣播發送流程

本篇基於R版本原始碼11.0.0_r1分析廣播的傳送流程:通常我們傳送廣播是直接在Activity中呼叫sendBroadcast(Intent intent)(這裡以最簡單的廣播發送為例,當然還可以增加許可權引數,限定接受使用者,傳送有序廣播或者粘性廣播等),而Activity的繼承關係:Activity --> ContextThemeWrapper --> ContextWrapper --> Context,其中Context為抽象類,其實現類為ContextImpl(在Activity建立的時候ActivityThread會通過ContextImpl.createActivityContext建立Activity的ContextImpl),所以實際上是呼叫ContextImpl.sendBroadcast,接下來我們看具體的程式碼流程(由於篇幅有限,所以部分地方只貼關鍵流程和程式碼):
1.1 ContextImpl.java:sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess(this);
        // 跨程序呼叫ActivityManagerService.broadcastIntentWithFeature, 注意這裡的mMainThread.getApplicationThread()即ApplicationThread,它是應用程序和system server程序之間溝通的橋樑
        ActivityManager.getService().broadcastIntentWithFeature(
                mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
                false, getUserId());
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
1.2 ActivityManagerService.java:broadcastIntentLocked(broadcastIntentWithFeature會直接呼叫broadcastIntentLocked,所以這裡省略broadcastIntentWithFeature程式碼)
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
        @Nullable String callerFeatureId, 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 realCallingUid,
        int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
        @Nullable int[] broadcastWhitelist) {
        intent = new Intent(intent);

        // 預設情況下廣播不傳送給stopped狀態的應用
        // By default broadcasts do not go to stopped apps.
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
    
        // 如果system server還未ready而且未新增BOOT_UPGRADE Flag,則該廣播只有動態註冊的廣播接收器才能接受
        // If we have not finished booting, don't allow this to launch new processes.
        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        }
        // 廣播的Action
        final String action = intent.getAction();
    
        // Verify that protected broadcasts are only being sent by system code,
        // and that system code is only sending protected broadcasts.
        final boolean isProtectedBroadcast;
        try {
            // 通過PackageManager查詢所有受保護的廣播
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", e);
            return ActivityManager.BROADCAST_SUCCESS;
        }

        final boolean isCallerSystem;
        // 特定UID或者persistent程序認為是系統程序
        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);
            }
        }    
        
        if (action != null) {
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
                }
                // 隱式廣播白名單裡的廣播可以傳送給靜態廣播接收器(無論應用程序後臺是否存活)
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }
        }     
        
        // Add to the sticky list if requested.
        if (sticky) {
            // 粘性廣播不能新增許可權
            if (requiredPermissions != null && requiredPermissions.length > 0) {
                Slog.w(TAG, "Can't broadcast sticky intent " + intent
                        + " and enforce permissions " + Arrays.toString(requiredPermissions));
                return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
            }
            // 粘性廣播不能指定Component
            if (intent.getComponent() != null) {
                throw new SecurityException(
                        "Sticky broadcasts can't target a specific component");
            }

            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
            // 查詢指定使用者的ArrayMap, 如果沒有就新建一個
            if (stickies == null) {
                stickies = new ArrayMap<>();
                mStickyBroadcasts.put(userId, stickies);
            }
            ArrayList<Intent> list = stickies.get(intent.getAction());
            // 查詢指定action的Intent列表,如果沒有就建立一個
            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))) {
                    // 如果這個粘性廣播Intent已經存在,則更新為最新的
                    // This sticky already exists, replace it.
                    list.set(i, new Intent(intent));
                    break;
                }
            }
            // 否則新增到列表最後
            if (i >= stickiesCount) {
                list.add(new Intent(intent));
            }
        }    
        
        // 重點來了,查詢廣播接收器
        // 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) {
            // 如果未禁止僅傳送給動態接受器, 則收集靜態接受器1.2.1
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastWhitelist);
        }
        if (intent.getComponent() == null) {
                // 如果沒有指定Component, 則收集動態接收器1.2.2
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
        } 
1.2.1 ActivityManagerService.java:collectReceiverComponents
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
        int callingUid, int[] users, int[] broadcastWhitelist) {
    // TODO: come back and remove this assumption to triage all broadcasts
    int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;

    List<ResolveInfo> receivers = null;
    try {
        HashSet<ComponentName> singleUserReceivers = null;
        boolean scannedFirstReceivers = false;
        for (int user : users) {
            // 通過PackageManagerService查詢當前使用者下所有AndroidManifest.xml中的靜態廣播接收器
            List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                    .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
            if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
                // If this is not the system user, we need to check for
                // any receivers that should be filtered out.
                for (int i=0; i<newReceivers.size(); i++) {
                    ResolveInfo ri = newReceivers.get(i);
                    // 該應用只希望接受系統使用者下的廣播
                    if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
                        newReceivers.remove(i);
                        i--;
                    }
                }
            }
            if (newReceivers != null && newReceivers.size() == 0) {
                newReceivers = null;
            }
            if (receivers == null) {
                receivers = newReceivers;
            }
        }
    } catch (RemoteException ex) {
        // pm is in same process, this will never happen.
    }
    // 如果靜態廣播白名單裡找不到該應用程式,則禁止應用接受該靜態註冊的廣播接收器
    if (receivers != null && broadcastWhitelist != null) {
        for (int i = receivers.size() - 1; i >= 0; i--) {
            final int receiverAppId = UserHandle.getAppId(
                    receivers.get(i).activityInfo.applicationInfo.uid);
            if (receiverAppId >= Process.FIRST_APPLICATION_UID
                    && Arrays.binarySearch(broadcastWhitelist, receiverAppId) < 0) {
                receivers.remove(i);
            }
        }
    }
    return receivers;
}
1.2.2 IntentResolver.java:queryIntent
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
        int userId) {
    ArrayList<R> finalList = new ArrayList<R>();

    F[] firstTypeCut = null;
    F[] secondTypeCut = null;
    F[] thirdTypeCut = null;
    F[] schemeCut = null;
    
    // If the intent does not specify any data -- either a MIME type or
    // a URI -- then we will only be looking for matches against empty
    // data.
    // 如果廣播未指定MIME type或者URI則只用關注firstTypeCut的獲取,它是從mActionToFilter獲取的,而mActionToFilter是在動態註冊時新增的,具體新增過程我們會在廣播註冊流程中介紹
    if (resolvedType == null && scheme == null && intent.getAction() != null) {
        firstTypeCut = mActionToFilter.get(intent.getAction());
        if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut));
    }

    FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
    if (firstTypeCut != null) {
        // 構建動態廣播接收器列表的過程也留到廣播註冊流程中介紹
        buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                scheme, firstTypeCut, finalList, userId);
    }
    if (secondTypeCut != null) {
        buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                scheme, secondTypeCut, finalList, userId);
    }
    if (thirdTypeCut != null) {
        buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                scheme, thirdTypeCut, finalList, userId);
    }
    if (schemeCut != null) {
        buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                scheme, schemeCut, finalList, userId);
    }
    filterResults(finalList);
    sortResults(finalList);

    return finalList;
}
1.3 ActivityManagerService.java:broadcastIntentLocked(接1.2)
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    // 處理動態非有序廣播
    if (!ordered && NR > 0) {
        // 根據Intent查詢廣播佇列 1.3.1
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        // 根據廣播佇列和intent等引數構造BroadcastRecord 1.3.2
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, ***registeredReceivers***, resultTo,
                resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                allowBackgroundActivityStarts, timeoutExempt);
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
        final boolean replaced = replacePending
                && (queue.replaceParallelBroadcastLocked(r) != null);
        // Note: We assume resultTo is null for non-ordered broadcasts.
        if (!replaced) {
            // 入隊並行廣播列表mParallelBroadcasts,並記錄入隊時間
            queue.enqueueParallelBroadcastLocked(r);
            // 開始分發動態非有序廣播 1.4
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        // 如果已處理完或者沒有動態接受者則NR為0
        NR = 0;
    }
1.3.1 ActivityManagerService.java:broadcastQueueForIntent
BroadcastQueue broadcastQueueForIntent(Intent intent) {
    // Intent.ACTION_LOCKED_BOOT_COMPLETED和Intent.ACTION_BOOT_COMPLETED這種長週期廣播專屬佇列, 預設不支援
    if (isOnOffloadQueue(intent.getFlags())) {
        if (DEBUG_BROADCAST_BACKGROUND) {
            Slog.i(TAG_BROADCAST,
                    "Broadcast intent " + intent + " on offload queue");
        }
        return mOffloadBroadcastQueue;
    }
    // 根據Flag來確定是走前臺廣播佇列還是後臺廣播佇列 1.3.1.1,二者在ActivityManagerService初始化時建立
    final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
    if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
            "Broadcast intent " + intent + " on "
            + (isFg ? "foreground" : "background") + " queue");
    return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
1.3.1.1 ActivityManagerService.java:建立mFgBroadcastQueue和mBgBroadcastQueue
    // How long we allow a receiver to run before giving up on it.
    // 前臺廣播超時時間為10s
    static final int BROADCAST_FG_TIMEOUT = 10*1000;
    // 後臺廣播超時時間為60s
    static final int BROADCAST_BG_TIMEOUT = 60*1000;
    
    // Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
        // Broadcast policy parameters
        final BroadcastConstants foreConstants = new BroadcastConstants(
                Settings.Global.BROADCAST_FG_CONSTANTS);
        foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT;

        final BroadcastConstants backConstants = new BroadcastConstants(
                Settings.Global.BROADCAST_BG_CONSTANTS);
        backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;
          
        // 構造前臺佇列和後臺佇列 1.3.1.2
        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", foreConstants, false);
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", backConstants, true);
1.3.1.2 BroadcastQueue.java:BroadcastQueue
    /**
     * 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<>();
    
    BroadcastQueue(ActivityManagerService service, Handler handler,
            String name, BroadcastConstants constants, boolean allowDelayBehindServices) {
        mService = service;
        mHandler = new BroadcastHandler(handler.getLooper());
        mQueueName = name;
        mDelayBehindServices = allowDelayBehindServices;

        mConstants = constants;
        // 建立BroadcastDispatcher記錄並處理有序廣播 1.3.1.3   
        mDispatcher = new BroadcastDispatcher(this, mConstants, mHandler, mService);    
    }

    // 加入並行廣播接收器列表
    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        mParallelBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }
    // 通過BroadcastDispatcher加入序列即有序廣播接收器列表
    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        mDispatcher.enqueueOrderedBroadcastLocked(r);
        enqueueBroadcastHelper(r);
    } 
1.3.1.3 BroadcastDispatcher.java
/**
 * Manages ordered broadcast delivery, applying policy to mitigate the effects of
 * slow receivers.
 */
public class BroadcastDispatcher {
    // Usual issuance-order outbound queue
    // 有序廣播列表
    private final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
    // General deferrals not holding up alarms
    private final ArrayList<Deferrals> mDeferredBroadcasts = new ArrayList<>();
    // Deferrals that *are* holding up alarms; ordered by alarm dispatch time
    private final ArrayList<Deferrals> mAlarmBroadcasts = new ArrayList<>();

    // Next outbound broadcast, established by getNextBroadcastLocked()
    private BroadcastRecord mCurrentBroadcast;

    /**
     * Constructed & sharing a lock with its associated BroadcastQueue instance
     */
    public BroadcastDispatcher(BroadcastQueue queue, BroadcastConstants constants,
            Handler handler, Object lock) {
        mQueue = queue;
        mConstants = constants;
        mHandler = handler;
        mLock = lock;
    }
    // 加入有序廣播列表
    void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        mOrderedBroadcasts.add(r);
    }    
}
1.3.2 BroadcastRecord.java
final class BroadcastRecord extends Binder {
    // 當前廣播的Intent
    final Intent intent;    // the original intent that generated us
    // 根據Intent得到的目標Component
    final ComponentName targetComp; // original component name set on the intent
    // 傳送廣播的程序
    final ProcessRecord callerApp; // process that sent this
    // 是否為有序廣播
    final boolean ordered;  // serialize the send to receivers?
    // 是否為sticky廣播
    final boolean sticky;   // originated from existing sticky data?
    // 廣播接收者,包括靜態註冊和動態註冊的廣播接收器
    final List receivers;   // contains BroadcastFilter and ResolveInfo
    // 記錄每個廣播接收器的接收情況
    final int[] delivery;   // delivery state of each receiver
    // 記錄每個廣播接收器的處理時間
    final long[] duration;   // duration a receiver took to process broadcast
    // 入列時間
    long enqueueClockTime;  // the clock time the broadcast was enqueued
    // 開始分發的時間
    long dispatchTime;      // when dispatch started on this set of receivers
    long dispatchClockTime; // the clock time the dispatch started
    // 開始超時的時間
    long receiverTime;      // when current receiver started for timeouts.
    // 結束的時間
    long finishTime;        // when we finished the broadcast.
    // 下一個即將被處理的廣播接收器
    int nextReceiver;       // next receiver to be executed.
    // 所屬的廣播佇列
    BroadcastQueue queue;   // the outbound queue handling this broadcast
1.4 BroadcastQueue.java:開始分發廣播
public void scheduleBroadcastsLocked() {
    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
            + mQueueName + "]: current="
            + mBroadcastsScheduled);
    // 如果處理過了就直接返回
    if (mBroadcastsScheduled) {
        return;
    }
    // 通過Handler傳送處理廣播的訊息
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

private final class BroadcastHandler extends Handler {
    @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;
        }
    }
}

final void processNextBroadcast(boolean fromMsg) {
    synchronized (mService) {
        // 開始依次處理每個廣播接收器 1.4.1
        processNextBroadcastLocked(fromMsg, false);
    }
}
1.4.1 BroadcastQueue.java:processNextBroadcastLocked
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
    BroadcastRecord r;
    
    if (fromMsg) {
        mBroadcastsScheduled = false;
    }

    // 先處理並行廣播
    // First, deliver any non-serialized broadcasts right away.
    while (mParallelBroadcasts.size() > 0) {
        // 依次取出每條廣播,並記錄分發時間
        r = mParallelBroadcasts.remove(0);
        r.dispatchTime = SystemClock.uptimeMillis();
        r.dispatchClockTime = System.currentTimeMillis();

        final int N = r.receivers.size();
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                + mQueueName + "] " + r);
        for (int i=0; i<N; i++) {
            Object target = r.receivers.get(i);
            // 該並行廣播的接收器都是動態註冊的即BroadcastFilter,強轉之後傳遞給deliverToRegisteredReceiverLocked 1.4.2
            deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
        }
        // 廣播處理完之後記錄結束時間並將BroadcastRecord加入mBroadcastHistory列表
        addBroadcastToHistoryLocked(r);
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                + mQueueName + "] " + r);
    }
1.4.2 BroadcastQueue.java:deliverToRegisteredReceiverLocked
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered, int index) {
        // 記錄傳遞狀態
        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
        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 {
                // 記錄廣播接收時間
                r.receiverTime = SystemClock.uptimeMillis();
                maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                // 準備切回廣播註冊者程序接收並處理廣播 1.4.3
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
                // parallel broadcasts are fire-and-forget, not bookended by a call to
                // finishReceiverLocked(), so we manage their activity-start token here
                if (r.allowBackgroundActivityStarts && !r.ordered) {
                    postActivityStartTokenRemoval(filter.receiverList.app, r);
                }
            }
        }       
1.4.3 BroadcastQueue.java:deliverToRegisteredReceiverLocked
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.
    if (app != null) {
        if (app.thread != null) {
            // 如果動態接收者的ProcessRecord不為null而且其ApplicationThread不為null則切換到應用端處理 1.4.4
            // If we have an app thread, do the call through that so it is
            // correctly ordered with other one-way calls.
            try {
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                        data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
            } catch (RemoteException ex) {
                // Failed to call into the process. It's either dying or wedged. Kill it gently.
                synchronized (mService) {
                    Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                            + " (pid " + app.pid + "). Crashing it.");
                    app.scheduleCrash("can't deliver broadcast");
                }
                throw ex;
            }
        } else {
            // Application has died. Receiver doesn't exist.
            throw new RemoteException("app.thread must not be null");
        }
    } else {
        // 否則直接回調IIntentReceiver.performReceive
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}
1.4.4 ActivityThread.java:ApplicationThread.scheduleRegisteredReceiver
private class ApplicationThread extends IApplicationThread.Stub {
    private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

    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);
        r.info = info;
        r.compatInfo = compatInfo;
        sendMessage(H.RECEIVER, r);
    }
    
    // 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);
        // 可以看到這裡實際上跟1.4.3 中 app為null的時候走的邏輯是一樣的 1.5
        receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                sticky, sendingUser);
    }
1.5 LoadedApk.java:ReceiverDispatcher.InnerReceiver
    final static class InnerReceiver extends IIntentReceiver.Stub {
        final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
        final LoadedApk.ReceiverDispatcher mStrongRef;

        @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) {
                Log.wtf(TAG, "Null intent received");
                rd = null;
            } else {
                // 註冊廣播時建立的
                rd = mDispatcher.get();
            }
            if (rd != null) {
                // 呼叫ReceiverDispatcher.performReceive 1.5.1
                rd.performReceive(intent, resultCode, data, extras,
                        ordered, sticky, sendingUser);
            } else {
                // The activity manager dispatched a broadcast to a registered
                // receiver in this process, but before it could be delivered the
                // receiver was unregistered.  Acknowledge the broadcast on its
                // behalf so that the system's broadcast sequence can continue.
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing broadcast to unregistered receiver");
                IActivityManager mgr = ActivityManager.getService();
                try {
                    if (extras != null) {
                        extras.setAllowFds(false);
                    }
                    // 未註冊的廣播直接finish
                    mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        }
    }
1.5.1 LoadedApk.java:ReceiverDispatcher
static final class ReceiverDispatcher {
    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);
        // post一個Runnale到主執行緒上執行,這個Runnable也是由ReceiverDispatcher的內部類提供的 1.5.2
        if (intent == null || !mActivityThread.post(args.getRunnable())) {
            if (mRegistered && ordered) {
                IActivityManager mgr = ActivityManager.getService();
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing sync broadcast to " + mReceiver);
                args.sendFinished(mgr);
            }
        }
    }
}
1.5.2 LoadedApk.java:ReceiverDispatcher.Args
    final class Args extends BroadcastReceiver.PendingResult {
        private Intent mCurIntent;
        private final boolean mOrdered;
        private boolean mDispatched;
        private boolean mRunCalled;

        public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                boolean ordered, boolean sticky, int sendingUser) {
            super(resultCode, resultData, resultExtras,
                    mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
                    sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
            mCurIntent = intent;
            mOrdered = ordered;
        }

        public final Runnable getRunnable() {
            return () -> {
                final BroadcastReceiver receiver = mReceiver;
                final boolean ordered = mOrdered;

                final IActivityManager mgr = ActivityManager.getService();
                final Intent intent = mCurIntent;
                if (intent == null) {
                    Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
                            + (mRunCalled ? ", run() has already been called" : ""));
                }

                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
                try {
                    ClassLoader cl = mReceiver.getClass().getClassLoader();
                    intent.setExtrasClassLoader(cl);
                    intent.prepareToEnterProcess();
                    setExtrasClassLoader(cl);
                    receiver.setPendingResult(this);
                    // 回撥BroadcastReceiver.onReceive方法正式接收廣播,這裡的receiver也是在註冊廣播時賦予的
                    receiver.onReceive(mContext, intent);
                } 

                if (receiver.getPendingResult() != null) {
                    finish();
                }
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            };
        }
    }