Android Broadcast廣播機制分析

基於Android 6.0的源碼剖析, 分析android廣播的發送與接收流程。

一、概述

廣播(Broadcast)機制用於進程/線程間通信,廣播分爲廣播發送和廣播接收兩個過程,其中廣播接收者BroadcastReceiver便是Android四大組件之一。

BroadcastReceiver分爲兩類:

  • 靜態廣播接收者:通過AndroidManifest.xml的 標籤來申明的BroadcastReceiver。
  • 動態廣播接收者:通過AMS.registerReceiver()方式註冊的BroadcastReceiver,動態註冊更爲靈活,可在不需要時通過unregisterReceiver()取消註冊。

從廣播發送方式可分爲三類:

  • 普通廣播:通過Context.sendBroadcast()發送,可並行處理
  • 有序廣播:通過Context.sendOrderedBroadcast()發送,串行處理
  • Sticky廣播:通過Context.sendOrderedBroadcast()發送

二、註冊廣播

2.1 registerReceiver

廣播註冊,對於應用開發來說,往往是在Activity/Service中調用 registerReceiver()方法,而Activity/Service都間接繼承於Context抽象類,真正幹活是交給ContextImpl類。另外調用getOuterContext()可獲取最外層的調用者Activity/Service。

[ContextImpl.java]

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    return registerReceiver(receiver, filter, null, null);
}

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
        String broadcastPermission, Handler scheduler) {
    //【見小節2.2】
    return registerReceiverInternal(receiver, getUserId(),
            filter, broadcastPermission, scheduler, getOuterContext());
}

當執行兩參數的 registerReceiver方法,增加兩個broadcastPermission=null和scheduler=null調用四參數的註冊方法。其中broadcastPermission擁有廣播的權限控制,scheduler用於指定接收到廣播時onRecive執行線程,當scheduler=null則默認代表在主線程中執行,這也是最常見的用法。 再然後調用6參數的 registerReceiverInternal

2.2 registerReceiverInternal

[ContextImpl.java]

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                //將主線程Handler賦予scheuler
                scheduler = mMainThread.getHandler();
            }
            //獲取IIntentReceiver對象【2.3】
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = new LoadedApk.ReceiverDispatcher(
                  receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
    try {
        //調用AMP.registerReceiver 【2.4】
        return ActivityManagerNative.getDefault().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName,
                rd, filter, broadcastPermission, userId);
    } catch (RemoteException e) {
        return null;
    }
}

ActivityManagerNative.getDefault()返回的是ActivityManagerProxy對象,簡稱AMP,該方法中參數有mMainThread.getApplicationThread()返回的是ApplicationThread,這是Binder的Bn端,用於system_server進程與該進程的通信。

2.3 LoadedApk.getReceiverDispatcher

[-> LoadedApk.java]

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
        Context context, Handler handler,
        Instrumentation instrumentation, boolean registered) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        //此處registered=true,則進入該分支
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }
        
        if (rd == null) {
            //當廣播分發者爲空,則創建ReceiverDispatcher【2.3.1】
            rd = new ReceiverDispatcher(r, context, handler,
                    instrumentation, registered);
            if (registered) {
                if (map == null) {
                    map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                    mReceivers.put(context, map);
                }
                map.put(r, rd);
            }
        } else {
            //驗證廣播分發者的context、handler是否一致
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        //獲取IIntentReceiver對象
        return rd.getIIntentReceiver();
    }
}

不妨令 以BroadcastReceiver(廣播接收者)爲key,LoadedApk.ReceiverDispatcher(分發者)爲value的ArrayMap 記爲 A。此處 mReceivers是一個以 Context爲key,以 A爲value的ArrayMap。對於ReceiverDispatcher(廣播分發者),當不存在時則創建一個。

2.3.1 創建ReceiverDispatcher

ReceiverDispatcher(BroadcastReceiver receiver, Context context,
        Handler activityThread, Instrumentation instrumentation,
        boolean registered) {
    //創建InnerReceiver【2.3.2】
    mIIntentReceiver = new InnerReceiver(this, !registered);
    mReceiver = receiver;
    mContext = context;
    mActivityThread = activityThread;
    mInstrumentation = instrumentation;
    mRegistered = registered;
    mLocation = new IntentReceiverLeaked(null);
    mLocation.fillInStackTrace();
}

2.3.2 創建InnerReceiver

final static class InnerReceiver extends IIntentReceiver.Stub {
    final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
    final LoadedApk.ReceiverDispatcher mStrongRef;

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

ReceiverDispatcher(廣播分發者)有一個內部類 InnerReceiver,該類繼承於 IIntentReceiver.Stub。顯然,這是一個Binder服務端,廣播分發者通過rd.getIIntentReceiver()可獲取該Binder服務端對象 InnerReceiver,用於Binder IPC通信。

2.4 AMP.registerReceiver

[-> ActivityManagerNative.java]

public Intent registerReceiver(IApplicationThread caller, String packageName,
        IIntentReceiver receiver,
        IntentFilter filter, String perm, int userId) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(packageName);
    data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
    filter.writeToParcel(data, 0);
    data.writeString(perm);
    data.writeInt(userId);

    //CommandREGISTER_RECEIVER_TRANSACTION
    mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
    reply.readException();
    Intent intent = null;
    int haveIntent = reply.readInt();
    if (haveIntent != 0) {
        intent = Intent.CREATOR.createFromParcel(reply);
    }
    reply.recycle();
    data.recycle();
    return intent;
}

這裏有兩個Binder服務端對象 callerreceiver,AMP通過Binder驅動將這些信息發送給system_server進程中的AMS對象,接下來進入AMS.registerReceiver。

2.5 AMS.registerReceiver

[-> ActivityManagerService.java]

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
    //孤立進程不允許註冊廣播接收者
    enforceNotIsolatedCaller("registerReceiver");
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    int callingUid;
    int callingPid;
    synchronized(this) {
        if (caller != null) {
            //從mLruProcesses隊列中查找調用者的ProcessRecord 【見2.5.1】
            callerApp = getRecordForAppLocked(caller);
            //查詢不到目標進程,則拋出異常
            if (callerApp == null) {
                throw new SecurityException("");
            }
            //非系統進程且包名不等於“android”,同時調用者進程不包括該包名時拋異常
            if (callerApp.info.uid != Process.SYSTEM_UID &&
                    !callerApp.pkgList.containsKey(callerPackage) &&
                    !"android".equals(callerPackage)) {
                throw new SecurityException("");
            }
            callingUid = callerApp.info.uid;
            callingPid = callerApp.pid;
        } else {
            callerPackage = null;
            callingUid = Binder.getCallingUid();
            callingPid = Binder.getCallingPid();
        }

        userId = handleIncomingUser(callingPid, callingUid, userId,
                true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);

        //獲取IntentFilter中的actions
        Iterator<String> actions = filter.actionsIterator();
        if (actions == null) {
            ArrayList<String> noAction = new ArrayList<String>(1);
            noAction.add(null);
            actions = noAction.iterator();
        }

        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
        while (actions.hasNext()) {
            String action = actions.next();
            for (int id : userIds) {
                //從mStickyBroadcasts中查看用戶的sticky Intent
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                if (stickies != null) {
                    ArrayList<Intent> intents = stickies.get(action);
                    if (intents != null) {
                        if (stickyIntents == null) {
                            stickyIntents = new ArrayList<Intent>();
                        }
                        //將sticky Intent加入到隊列
                        stickyIntents.addAll(intents);
                    }
                }
            }
        }
    }

    ArrayList<Intent> allSticky = null;
    if (stickyIntents != null) {
        final ContentResolver resolver = mContext.getContentResolver();
        for (int i = 0, N = stickyIntents.size(); i < N; i++) {
            Intent intent = stickyIntents.get(i);
            //查詢匹配的sticky廣播 【見2.5.2】
            if (filter.match(resolver, intent, true, TAG) >= 0) {
                if (allSticky == null) {
                    allSticky = new ArrayList<Intent>();
                }
                //匹配成功,則將給intent添加到allSticky隊列
                allSticky.add(intent);
            }
        }
    }

    //當IIntentReceiver爲空,則直接返回第一個sticky Intent,
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (receiver == null) {
        return sticky;
    }

    synchronized (this) {
        if (callerApp != null && (callerApp.thread == null
                || callerApp.thread.asBinder() != caller.asBinder())) {
            //調用者已經死亡
            return null;
        }
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
            //對於沒有註冊的廣播,則創建接收者隊列
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                    userId, receiver);
            if (rl.app != null) {
                rl.app.receivers.add(rl);
            } else {
                try {
                    //註冊死亡通知
                    receiver.asBinder().linkToDeath(rl, 0);
                } catch (RemoteException e) {
                    return sticky;
                }
                rl.linkedToDeath = true;
            }
            //新創建的接收者隊列,添加到已註冊廣播隊列。
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        }
        ...
        //創建BroadcastFilter對象,並添加到接收者隊列
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId);
        rl.add(bf);
        //新創建的廣播過濾者,添加到ReceiverResolver隊列
        mReceiverResolver.addFilter(bf);

        //所有匹配該filter的sticky廣播執行入隊操作
        //如果沒有使用sendStickyBroadcast,則allSticky=null。
        if (allSticky != null) {
            ArrayList receivers = new ArrayList();
            receivers.add(bf);

            final int stickyCount = allSticky.size();
            for (int i = 0; i < stickyCount; i++) {
                Intent intent = allSticky.get(i);
                //當intent爲前臺廣播,則返回mFgBroadcastQueue
                //當intent爲後臺廣播,則返回mBgBroadcastQueue
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                //創建BroadcastRecord
                BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                        null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
                        null, 0, null, null, false, true, true, -1);
                //該廣播加入到並行廣播隊列
                queue.enqueueParallelBroadcastLocked(r);
                //調度廣播,發送BROADCAST_INTENT_MSG消息,觸發處理下一個廣播。
                queue.scheduleBroadcastsLocked();
            }
        }
        return sticky;
    }
}

其中 mRegisteredReceivers記錄着所有已註冊的廣播,以receiver IBinder爲key, ReceiverList爲value爲HashMap。另外,這個過程涉及對象 ReceiverListBroadcastFilterBroadcastRecord的創建。

在BroadcastQueue中有兩個廣播隊列 mParallelBroadcasts, mOrderedBroadcasts,數據類型都爲ArrayList :

  • mParallelBroadcasts:並行廣播隊列,可以立刻執行,而無需等待另一個廣播運行完成,該隊列只允許動態已註冊的廣播,從而避免發生同時拉起大量進程來執行廣播,前臺的和後臺的廣播分別位於獨立的隊列。
  • mOrderedBroadcasts:有序廣播隊列,同一時間只允許執行一個廣播,該隊列頂部的廣播便是活動廣播,其他廣播必須等待該廣播結束才能運行,也是獨立區別前臺的和後臺的廣播。

2.5.1 AMS.getRecordForAppLocked

final ProcessRecord getRecordForAppLocked(
        IApplicationThread thread) {
    if (thread == null) {
        return null;
    }
    //從mLruProcesses隊列中查看
    int appIndex = getLRURecordIndexForAppLocked(thread);
    return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
}

mLruProcesses數據類型爲 ArrayList<ProcessRecord>,而ProcessRecord對象有一個IApplicationThread字段,根據該字段查找出滿足條件的ProcessRecord對象。

2.5.2 IntentFilter.match

public final int match(ContentResolver resolver, Intent intent,
        boolean resolve, String logTag) {
    String type = resolve ? intent.resolveType(resolver) : intent.getType();
    return match(intent.getAction(), type, intent.getScheme(),
                 intent.getData(), intent.getCategories(), logTag);
}

public final int match(String action, String type, String scheme,
        Uri data, Set<String> categories, String logTag) {
    //不存在匹配的action
    if (action != null && !matchAction(action)) {
        return NO_MATCH_ACTION; 
    }

    //不存在匹配的type或data
    int dataMatch = matchData(type, scheme, data);
    if (dataMatch < 0) {
        return dataMatch; 
    }

    //不存在匹配的category
    String categoryMismatch = matchCategories(categories);
    if (categoryMismatch != null) {
        return NO_MATCH_CATEGORY;
    }
    return dataMatch;
}

該方法用於匹配發起的Intent數據是否匹配成功,匹配項共有4項action, type, data, category,任何一項匹配不成功都會失敗。

小結

註冊廣播的過程,主要功能:

  • 創建ReceiverList(接收者隊列),並添加到AMS.mRegisteredReceivers(已註冊廣播隊列);
  • 創建BroadcastFilter(廣播過濾者),並添加到AMS.mReceiverResolver(接收者的解析人);
  • 當註冊的是Sticky廣播,則創建BroadcastRecord,並添加到BroadcastQueue的mParallelBroadcasts(並行廣播隊列),註冊後調用AMS來儘快處理該廣播。

三、 發送廣播

發送廣播,同樣往往是在Activity/Service中調用 registerReceiver()方法,而Activity/Service都間接繼承於Context抽象類,真正幹活是交給ContextImpl類。

3.1 sendBroadcast

[ContextImpl.java]

@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess();
        // 調用AMP.broadcastIntent  【見3.2】
        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 new RuntimeException("Failure from system", e);
    }
}

3.2 AMP.broadcastIntent

[-> ActivityManagerNative.java]

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
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
    data.writeInt(resultCode);
    data.writeString(resultData);
    data.writeBundle(map);
    data.writeStringArray(requiredPermissions);
    data.writeInt(appOp);
    data.writeBundle(options);
    data.writeInt(serialized ? 1 : 0);
    data.writeInt(sticky ? 1 : 0);
    data.writeInt(userId);

    //CommandBROADCAST_INTENT_TRANSACTION
    mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
    reply.readException();
    int res = reply.readInt();
    reply.recycle();
    data.recycle();
    return res;
}

3.3 AMS.broadcastIntent

[-> ActivityManagerService.java]

public final int broadcastIntent(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle options,
        boolean serialized, boolean sticky, int userId) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        //驗證廣播intent是否有效
        intent = verifyBroadcastLocked(intent);
        //獲取調用者進程記錄對象
        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        //【見小節3.4】
        int res = broadcastIntentLocked(callerApp,
                callerApp != null ? callerApp.info.packageName : null,
                intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                requiredPermissions, appOp, null, serialized, sticky,
                callingPid, callingUid, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}

broadcastIntent()方法有兩個布爾參數serialized和sticky來共同決定是普通廣播,有序廣播,還是Sticky廣播,參數如下:

類型 serialized sticky
sendBroadcast false false
sendOrderedBroadcast true false
sendStickyBroadcast false true

3.4 AMS.broadcastIntentLocked

private final int broadcastIntentLocked(ProcessRecord callerApp,
        String callerPackage, Intent intent, String resolvedType,
        IIntentReceiver resultTo, int resultCode, String resultData,
        Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options,
        boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
    
    //part 1: 設置flag
    //part 2: 廣播權限驗證
    //part 3: 處理系統相關廣播
    //part 4: 增加sticky廣播
    //part 5: 查詢receivers和registeredReceivers
    //part 6: 處理並行廣播
    //part 7: 合併registeredReceivers到receivers
    //part 8: 處理串行廣播

    return ActivityManager.BROADCAST_SUCCESS;
}

broadcastIntentLocked方法比較長,這裏劃分爲8個部分來分別說明。

part 1: 設置廣播flag

    intent = new Intent(intent);
    //增加該flag,則廣播不會發送給已停止的package
    intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

    //當沒有啓動完成時,不允許啓動新進程
    if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    }
    userId = handleIncomingUser(callingPid, callingUid, userId,
            true, ALLOW_NON_FULL, "broadcast", callerPackage);

    //檢查發送廣播時用戶狀態
    if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {
        if ((callingUid != Process.SYSTEM_UID
                || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
                && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
            return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
        }
    }

這個過程最重要的工作是:

  • 添加flag= FLAG_EXCLUDE_STOPPED_PACKAGES,保證已停止app不會收到該廣播;
  • 當系統還沒有啓動完成,則不允許啓動新進程,,即只有動態註冊receiver才能接受廣播
  • 當非USER_ALL廣播且當前用戶並沒有處於Running的情況下,除非是系統升級廣播或者關機廣播,否則直接返回。

BroadcastReceiver還有其他flag,位於Intent.java常量:

FLAG_RECEIVER_REGISTERED_ONLY //只允許已註冊receiver接收廣播
FLAG_RECEIVER_REPLACE_PENDING //新廣播會替代相同廣播
FLAG_RECEIVER_FOREGROUND //只允許前臺receiver接收廣播
FLAG_RECEIVER_NO_ABORT //對於有序廣播,先接收到的receiver無權拋棄廣播
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT //Boot完成之前,只允許已註冊receiver接收廣播
FLAG_RECEIVER_BOOT_UPGRADE //升級模式下,允許系統準備就緒前可以發送廣播

part 2: 廣播權限驗證

    int callingAppId = UserHandle.getAppId(callingUid);
    if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
        || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
        || callingAppId == Process.NFC_UID || callingUid == 0) {
        //直接通過
    } else if (callerApp == null || !callerApp.persistent) {
        try {
            if (AppGlobals.getPackageManager().isProtectedBroadcast(
                    intent.getAction())) {
                //不允許發送給受保護的廣播
                throw new SecurityException(msg);
            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {
                //這個case是出於兼容性考慮,限制只允許發送給自己。
                ...
            }
        } catch (RemoteException e) {
            return ActivityManager.BROADCAST_SUCCESS;
        }
    }

主要功能:

  • 對於callingAppId爲SYSTEM_UID,PHONE_UID,SHELL_UID,BLUETOOTH_UID,NFC_UID之一或者callingUid == 0時都暢通無阻;
  • 否則對於調用者進程爲空並且不是persistent進程的情況下:
    • 當發送的是受保護廣播 mProtectedBroadcasts(只允許系統使用),則拋出異常;
    • 當action爲ACTION_APPWIDGET_CONFIGURE時,雖然不希望該應用發送這種廣播,處於兼容性考慮,限制該廣播只允許發送給自己,否則拋出異常。

part 3: 處理系統相關廣播

    final String action = intent.getAction();
    if (action != null) {
        switch (action) {
            case Intent.ACTION_UID_REMOVED:
                mBatteryStatsService.removeUid(uid);
                mAppOpsService.uidRemoved(uid);
                break;
            case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                if (list != null && list.length > 0) {
                    for (int i = 0; i < list.length; i++) {
                        forceStopPackageLocked(list[i], -1, false, true, true,
                                false, false, userId, "storage unmount");
                    }
                    mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
                    sendPackageBroadcastLocked(
                        IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,userId);
                }
                break;
            case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
                mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
                break;
            case Intent.ACTION_PACKAGE_REMOVED:
            case Intent.ACTION_PACKAGE_CHANGED:
                Uri data = intent.getData();
                boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
                boolean fullUninstall = removed && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                final boolean killProcess = !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
                if (killProcess) {
                    forceStopPackageLocked(ssp, UserHandle.getAppId(
                            intent.getIntExtra(Intent.EXTRA_UID, -1)),
                            false, true, true, false, fullUninstall, userId,
                            removed ? "pkg removed" : "pkg changed");
                }
                if (removed) {
                    sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,new String[] {ssp}, userId);
                    if (fullUninstall) {
                        mAppOpsService.packageRemoved(intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
                        removeUriPermissionsForPackageLocked(ssp, userId, true);
                        removeTasksByPackageNameLocked(ssp, userId);
                        mBatteryStatsService.notePackageUninstalled(ssp);
                    }
                } else {
                    cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
                            intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
                }
                break;

            case Intent.ACTION_PACKAGE_ADDED:
                Uri data = intent.getData();
                final boolean replacing =intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
                ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(ssp, 0, 0);
                break;
            case Intent.ACTION_TIMEZONE_CHANGED:
                mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
                break;
            case Intent.ACTION_TIME_CHANGED:
                final int is24Hour = intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1: 0;
                mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
                BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
                synchronized (stats) {
                    stats.noteCurrentTimeChangedLocked();
                }
                break;
            case Intent.ACTION_CLEAR_DNS_CACHE: 
                mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
                break;
            case Proxy.PROXY_CHANGE_ACTION:
                ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
                mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
                break;
        }
    }

這個過程代碼較長,主要處於系統相關的廣播,如下10個case:

    case Intent.ACTION_UID_REMOVED: //uid移除
    case Intent.ACTION_PACKAGE_REMOVED: //package移除,
    case Intent.ACTION_PACKAGE_CHANGED: //package改變
    case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: //外部設備不可用時,強制停止所有波及的應用並清空cache數據
    case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: //外部設備可用
    case Intent.ACTION_PACKAGE_ADDED: //增加package,處於兼容考慮

    case Intent.ACTION_TIMEZONE_CHANGED: //時區改變,通知所有運行中的進程
    case Intent.ACTION_TIME_CHANGED: //時間改變,通知所有運行中的進程
    case Intent.ACTION_CLEAR_DNS_CACHE: //dns緩存清空
    case Proxy.PROXY_CHANGE_ACTION: //網絡代理改變

part 4:增加sticky廣播

    if (sticky) {
        if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
                callingPid, callingUid)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("");
        }
        if (requiredPermissions != null && requiredPermissions.length > 0) {
            return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
        }
        
        if (intent.getComponent() != null) {
           //當sticky廣播發送給指定組件,則throw Exception
        }
        if (userId != UserHandle.USER_ALL) {
           //當非USER_ALL廣播跟USER_ALL廣播出現衝突,則throw Exception
        }

        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
        if (stickies == null) {
            stickies = new ArrayMap<>();
            mStickyBroadcasts.put(userId, stickies);
        }
        ArrayList<Intent> list = stickies.get(intent.getAction());
        if (list == null) {
            list = new ArrayList<>();
            stickies.put(intent.getAction(), list);
        }
        final int stickiesCount = list.size();
        int i;
        for (i = 0; i < stickiesCount; i++) {
            if (intent.filterEquals(list.get(i))) {
                //替換已存在的sticky intent
                list.set(i, new Intent(intent));
                break;
            }
        }
        //新的intent追加到list
        if (i >= stickiesCount) {
            list.add(new Intent(intent));
        }
    }

這個過程主要是將sticky廣播增加到list,並放入mStickyBroadcasts裏面。

part 5:查詢receivers和registeredReceivers

    int[] users;
    if (userId == UserHandle.USER_ALL) {
        users = mStartedUserArray; //廣播給所有已啓動用戶
    } else {
        users = new int[] {userId}; //廣播給指定用戶
    }

    List receivers = null;
    List<BroadcastFilter> registeredReceivers = null;
    //找出所有能接收該廣播的receivers
    if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
        //根據intent查找相應的receivers
        receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
    }
    if (intent.getComponent() == null) {
        if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
            UserManagerService ums = getUserManagerLocked();
            for (int i = 0; i < users.length; i++) {
                //shell用戶是否開啓允許debug功能
                if (ums.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                    continue;
                }
                // 查詢動態註冊的廣播
                List<BroadcastFilter> registeredReceiversForUser =
                        mReceiverResolver.queryIntent(intent,
                                resolvedType, false, users[i]);
                if (registeredReceivers == null) {
                    registeredReceivers = registeredReceiversForUser;
                } else if (registeredReceiversForUser != null) {
                    registeredReceivers.addAll(registeredReceiversForUser);
                }
            }
        } else {
            // 查詢動態註冊的廣播
            registeredReceivers = mReceiverResolver.queryIntent(intent,
                    resolvedType, false, userId);
        }
    }
  • receivers:記錄着匹配當前intent的所有靜態註冊廣播接收者;
  • registeredReceivers:記錄着匹配當前的所有動態註冊的廣播接收者。

其中, mReceiverResolver是AMS的成員變量,記錄着已註冊的廣播接收者的resolver.

AMS.collectReceiverComponents:

private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
        int callingUid, int[] users) {
    List<ResolveInfo> receivers = null;
    for (int user : users) {
        //調用PKMS.queryIntentReceivers,可獲取AndroidManifest.xml聲明的接收者信息
        List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
        if (receivers == null) {
            receivers = newReceivers;
        } else if (newReceivers != null) {
            ...
            //將所用戶的receiver整合到receivers
        }
     }
    return receivers;
}

part 6:處理並行廣播

    //用於標識是否需要用新intent替換舊的intent。
    final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
    //處理並行廣播
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    if (!ordered && NR > 0) {
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        //創建BroadcastRecord對象
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
                appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
                resultExtras, ordered, sticky, false, userId);

        final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
        if (!replaced) {
            //將BroadcastRecord加入到並行廣播隊列
            queue.enqueueParallelBroadcastLocked(r);
            //處理廣播【見小節4.1】
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }

廣播隊列中有一個成員變量 mParallelBroadcasts,類型爲ArrayList ,記錄着所有的並行廣播。

part 7:合併registeredReceivers到receivers

    int ir = 0;
    if (receivers != null) {
        //防止應用監聽該廣播,在安裝時直接運行。
        String skipPackages[] = null;
        if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
            Uri data = intent.getData();
            if (data != null) {
                String pkgName = data.getSchemeSpecificPart();
                if (pkgName != null) {
                    skipPackages = new String[] { pkgName };
                }
            }
        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
            skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
        }

        //將skipPackages相關的廣播接收者從receivers列表中移除
        if (skipPackages != null && (skipPackages.length > 0)) {
            for (String skipPackage : skipPackages) {
                if (skipPackage != null) {
                    int NT = receivers.size();
                    for (int it=0; it<NT; it++) {
                        ResolveInfo curt = (ResolveInfo)receivers.get(it);
                        if (curt.activityInfo.packageName.equals(skipPackage)) {
                            receivers.remove(it);
                            it--;
                            NT--;
                        }
                    }
                }
            }
        }

        //前面part6有一個處理動態廣播的過程,處理完後再執行將動態註冊的registeredReceivers合併到receivers
        int NT = receivers != null ? receivers.size() : 0;
        int it = 0;
        ResolveInfo curt = null;
        BroadcastFilter curr = null;
        while (it < NT && ir < NR) {
            if (curt == null) {
                curt = (ResolveInfo)receivers.get(it);
            }
            if (curr == null) {
                curr = registeredReceivers.get(ir);
            }
            if (curr.getPriority() >= curt.priority) {
                receivers.add(it, curr);
                ir++;
                curr = null;
                it++;
                NT++;
            } else {  
                it++;
                curt = null;
            }
        }
    }
    while (ir < NR) {
        if (receivers == null) {
            receivers = new ArrayList();
        }
        receivers.add(registeredReceivers.get(ir));
        ir++;
    }

part 8: 處理串行廣播

    if ((receivers != null && receivers.size() > 0)
            || resultTo != null) {
        BroadcastQueue queue = broadcastQueueForIntent(intent);
        //創建BroadcastRecord
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, resolvedType,
                requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                resultData, resultExtras, ordered, sticky, false, userId);

        boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
        if (!replaced) {
            //將BroadcastRecord加入到有序廣播隊列
            queue.enqueueOrderedBroadcastLocked(r);
            //處理廣播【見小節4.1】
            queue.scheduleBroadcastsLocked(); 
        }
    }

廣播隊列中有一個成員變量 mOrderedBroadcasts,類型爲ArrayList ,記錄着所有的有序廣播。

四、 處理廣播

在發送廣播過程中會執行 scheduleBroadcastsLocked方法來處理相關的廣播

4.1 scheduleBroadcastsLocked

[-> BroadcastQueue.java]

public void scheduleBroadcastsLocked() {    
    // 正在處理BROADCAST_INTENT_MSG消息
    if (mBroadcastsScheduled) {
        return;
    }
    //發送BROADCAST_INTENT_MSG消息
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

在BroadcastQueue對象創建時,mHandler=new BroadcastHandler(handler.getLooper());那麼此處交由mHandler的handleMessage來處理:

private final class BroadcastHandler extends Handler {
    public BroadcastHandler(Looper looper) {
        super(looper, null, true);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BROADCAST_INTENT_MSG: {
                processNextBroadcast(true); //【見小節4.2】
            } break;
            ...
    }
}

4.2 processNextBroadcast

[-> BroadcastQueue.java]

final void processNextBroadcast(boolean fromMsg) {
    synchronized(mService) {
        //part 1: 處理並行廣播
        //part 2: 處理有序廣播
        //part 3: 獲取下條有序廣播
        //part 4: 處理下條有序廣播
    }
}

此處mService爲AMS,整個流程還是比較長的,全程持有AMS鎖,所以廣播效率低的情況下,直接會嚴重影響這個手機的性能與流暢度,這裏應該考慮細化同步鎖的粒度。

part 1: 處理並行廣播

BroadcastRecord r;           
mService.updateCpuStats(); //更新CPU統計信息
if (fromMsg)  mBroadcastsScheduled = false;

while (mParallelBroadcasts.size() > 0) {
    r = mParallelBroadcasts.remove(0);
    r.dispatchTime = SystemClock.uptimeMillis();
    r.dispatchClockTime = System.currentTimeMillis();
    final int N = r.receivers.size();
    for (int i=0; i<N; i++) {
        Object target = r.receivers.get(i);
        //分發廣播給已註冊的receiver 【見小節4.3】
        deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
    }
    addBroadcastToHistoryLocked(r);//將廣播添加歷史統計
}

part 2:處理有序廣播

if (mPendingBroadcast != null) {
    boolean isDead;
    synchronized (mService.mPidsSelfLocked) {
        //從mPidsSelfLocked獲取正在處理該廣播進程,判斷該進程是否死亡
        ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
        isDead = proc == null || proc.crashing;
    }
    if (!isDead) {
        //正在處理廣播的進程保持活躍狀態,則繼續等待其執行完成
        return;
    } else {
        mPendingBroadcast.state = BroadcastRecord.IDLE;
        mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
        mPendingBroadcast = null;
    }
}

boolean looped = false;
do {
    if (mOrderedBroadcasts.size() == 0) {
        //所有串行廣播處理完成,則調度執行gc
        mService.scheduleAppGcsLocked();
        if (looped) {
            mService.updateOomAdjLocked();
        }
        return;
    }
    r = mOrderedBroadcasts.get(0);
    boolean forceReceive = false;

    //獲取所有該廣播所有的接收者
    int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
    if (mService.mProcessesReady && r.dispatchTime > 0) {
        long now = SystemClock.uptimeMillis();
        if ((numReceivers > 0) &&
                (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
            //當廣播處理時間超時,則強制結束這條廣播
            broadcastTimeoutLocked(false);
            forceReceive = true;
            r.state = BroadcastRecord.IDLE;
        }
    }

    if (r.state != BroadcastRecord.IDLE) {
        return;
    }

    if (r.receivers == null || r.nextReceiver >= numReceivers
            || r.resultAbort || forceReceive) {
        if (r.resultTo != null) {
            //處理廣播消息消息
            performReceiveLocked(r.callerApp, r.resultTo,
                new Intent(r.intent), r.resultCode,
                r.resultData, r.resultExtras, false, false, r.userId);
            r.resultTo = null;
        }
        //取消BROADCAST_TIMEOUT_MSG消息
        cancelBroadcastTimeoutLocked();

        addBroadcastToHistoryLocked(r);
        mOrderedBroadcasts.remove(0);
        r = null;
        looped = true;
        continue;
    }
} while (r == null);

mTimeoutPeriod,對於前臺廣播則爲10s,對於後臺廣播則爲60s,此時廣播超時爲 2*mTimeoutPeriod*numReceivers,接收者越多則廣播超時總時長越長。

part 3: 獲取下條有序廣播

//獲取下一個receiver的index
int recIdx = r.nextReceiver++;

r.receiverTime = SystemClock.uptimeMillis();
if (recIdx == 0) {
    r.dispatchTime = r.receiverTime;
    r.dispatchClockTime = System.currentTimeMillis();
}
if (!mPendingBroadcastTimeoutMessage) {
    long timeoutTime = r.receiverTime + mTimeoutPeriod;
    //設置廣播超時時間,發送BROADCAST_TIMEOUT_MSG
    setBroadcastTimeoutLocked(timeoutTime);
}

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

if (nextReceiver instanceof BroadcastFilter) {
    //對於動態註冊的廣播接收者,deliverToRegisteredReceiverLocked處理廣播
    BroadcastFilter filter = (BroadcastFilter)nextReceiver;
    deliverToRegisteredReceiverLocked(r, filter, r.ordered);
    if (r.receiver == null || !r.ordered) {
        r.state = BroadcastRecord.IDLE;
        scheduleBroadcastsLocked();
    } else {
        ...
    }
    return;
}

//對於靜態註冊的廣播接收者
ResolveInfo info = (ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
        info.activityInfo.applicationInfo.packageName,
        info.activityInfo.name);
...
//執行各種權限檢測,此處省略,當權限不滿足時skip=true

if (skip) {
    r.receiver = null;
    r.curFilter = null;
    r.state = BroadcastRecord.IDLE;
    scheduleBroadcastsLocked();
    return;
}

r.state = BroadcastRecord.APP_RECEIVE;
String targetProcess = info.activityInfo.processName;
r.curComponent = component;
final int receiverUid = info.activityInfo.applicationInfo.uid;
if (r.callingUid != Process.SYSTEM_UID && isSingleton
        && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
    info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
}
r.curReceiver = info.activityInfo;
...

//Broadcast正在執行中,stopped狀態設置成false
AppGlobals.getPackageManager().setPackageStoppedState(
        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));

part 4: 處理下條有序廣播

//該receiver所對應的進程已經運行,則直接處理
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
        info.activityInfo.applicationInfo.uid, false);
if (app != null && app.thread != null) {
    try {
        app.addPackage(info.activityInfo.packageName,
                info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
        processCurBroadcastLocked(r, app);
        return;
    } catch (RemoteException e) {
    } catch (RuntimeException e) {
        finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);
        scheduleBroadcastsLocked();
        r.state = BroadcastRecord.IDLE; //啓動receiver失敗則重置狀態
        return;
    }
}

//該receiver所對應的進程尚未啓動,則創建該進程
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) {
    //創建失敗,則結束該receiver
    finishReceiverLocked(r, r.resultCode, r.resultData,
            r.resultExtras, r.resultAbort, false);
    scheduleBroadcastsLocked();
    r.state = BroadcastRecord.IDLE;
    return;
}
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
  • 如果是動態廣播接收者,則調用deliverToRegisteredReceiverLocked處理;
  • 如果是動態廣播接收者,且對應進程已經創建,則調用processCurBroadcastLocked處理;
  • 如果是動態廣播接收者,且對應進程尚未創建,則調用startProcessLocked創建進程。

4.3 deliverToRegisteredReceiverLocked

[-> BroadcastQueue.java]

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered) {
    ...
    //檢查發送者是否有BroadcastFilter所需權限
    //以及接收者是否有發送者所需的權限等等
    //當權限不滿足要求,則skip=true。

    if (!skip) {
        //並行廣播ordered = false,只有串行廣播才進入該分支
        if (ordered) {
            r.receiver = filter.receiverList.receiver.asBinder();
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                r.curApp = filter.receiverList.app;
                filter.receiverList.app.curReceiver = r;
                mService.updateOomAdjLocked(r.curApp);
            }
        }
        // 處理廣播【見小節4.4】
        performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                new Intent(r.intent), r.resultCode, r.resultData,
                r.resultExtras, r.ordered, r.initialSticky, r.userId);
        if (ordered) {
            r.state = BroadcastRecord.CALL_DONE_RECEIVE;
        }
        ...
    }
}

4.4 deliverToRegisteredReceiverLocked

[-> BroadcastQueue.java]

private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
        Intent intent, int resultCode, String data, Bundle extras,
        boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
    //通過binder異步機制,向receiver發送intent
    if (app != null) {
        if (app.thread != null) {
            //調用ApplicationThreadProxy類對應的方法 【4.5】
            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                    data, extras, ordered, sticky, sendingUser, app.repProcState);
        } else {
            //應用進程死亡,則Recevier並不存在
            throw new RemoteException("app.thread must not be null");
        }
    } else {
        //調用者進程爲空,則執行該分支
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}

4.5 ATP.scheduleRegisteredReceiver

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
        int resultCode, String dataStr, Bundle extras, boolean ordered,
        boolean sticky, int sendingUser, int processState) throws RemoteException {
    Parcel data = Parcel.obtain();
    data.writeInterfaceToken(IApplicationThread.descriptor);
    data.writeStrongBinder(receiver.asBinder());
    intent.writeToParcel(data, 0);
    data.writeInt(resultCode);
    data.writeString(dataStr);
    data.writeBundle(extras);
    data.writeInt(ordered ? 1 : 0);
    data.writeInt(sticky ? 1 : 0);
    data.writeInt(sendingUser);
    data.writeInt(processState);

    //command=SCHEDULE_REGISTERED_RECEIVER_TRANSACTION
    mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
            IBinder.FLAG_ONEWAY);
    data.recycle();
}

ATP位於system_server進程,是Binder Bp端通過Binder驅動向Binder Bn端發送消息, ATP所對應的Bn端位於發送廣播調用端所在進程的ApplicationThread,即進入AT.scheduleRegisteredReceiver, 接下來說明該方法。

4.6 AT.scheduleRegisteredReceiver

[-> ActivityThread.java]

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
        int resultCode, String dataStr, Bundle extras, boolean ordered,
        boolean sticky, int sendingUser, int processState) throws RemoteException {
    //更新虛擬機進程狀態
    updateProcessState(processState, false);
    //【見小節4.7】
    receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
            sticky, sendingUser);
}

此處receiver是註冊廣播時創建的,見小節[2.3],可知該 receiver= LoadedApk.ReceiverDispatcher.InnerReceiver

4.7 InnerReceiver.performReceive

[-> LoadedApk.java]

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
    if (rd != null) {
        //【4.8】
        rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);
    } else {
       ...
    }
}

4.8 ReceiverDispatcher.performReceive

[-> LoadedApk.java]

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
    //通過handler消息機制發送args.
    if (!mActivityThread.post(args)) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            args.sendFinished(mgr);
        }
    }
}

其中 Args繼承於 BroadcastReceiver.PendingResult,實現了接口 Runnable。這裏mActivityThread.post(args) 消息機制,關於Handler消息機制,見 Android消息機制1-Handler(Java層),把消息放入MessageQueue,再調用Args的run()方法。

4.9 Args.run

[-> LoadedApk.java]

public final class LoadedApk {
  static final class ReceiverDispatcher {
    final class Args extends BroadcastReceiver.PendingResult implements Runnable {
        public void run() {
            final BroadcastReceiver receiver = mReceiver;
            final boolean ordered = mOrdered;
           
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            final Intent intent = mCurIntent;
            mCurIntent = null;
            
            if (receiver == null || mForgotten) {
                if (mRegistered && ordered) {
                    sendFinished(mgr);
                }
                return;
            }

            try {
                //獲取mReceiver的類加載器
                ClassLoader cl =  mReceiver.getClass().getClassLoader();
                intent.setExtrasClassLoader(cl);
                setExtrasClassLoader(cl);
                receiver.setPendingResult(this);
                //回調廣播onReceive方法
                receiver.onReceive(mContext, intent);
            } catch (Exception e) {
                ...
            }
            
            if (receiver.getPendingResult() != null) {
                finish();
            }
        }
      }
    }

最終調用 BroadcastReceiver具體實現類的 onReceive()方法。

4.10 PendingResult.finish

[-> BroadcastReceiver.java]

public final void finish() {
    final IActivityManager mgr = ActivityManagerNative.getDefault();
    sendFinished(mgr);
    ...
}

public void sendFinished(IActivityManager am) {
    synchronized (this) {
        try {
            if (mResultExtras != null) {
                mResultExtras.setAllowFds(false);
            }
            if (mOrderedHint) {
                //串行廣播
                am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                        mAbortBroadcast, mFlags);
            } else {
                //並行廣播
                am.finishReceiver(mToken, 0, null, null, false, mFlags);
            }
        } catch (RemoteException ex) {
        }
    }
}

此處AMP.finishReceiver,經過binder調用,進入AMS.finishReceiver方法

4.11 AMS.finishReceiver

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

        synchronized(this) {
            BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                    ? mFgBroadcastQueue : mBgBroadcastQueue;
            r = queue.getMatchingOrderedReceiver(who);
            if (r != null) {
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                    resultData, resultExtras, resultAbort, true);
            }
        }

        if (doNext) {
            //處理下一條廣播
            r.queue.processNextBroadcast(false);
        }
        trimApplications();
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

五、總結

未完留坑,後續總結以及增加流程圖說明…

附錄

本文所涉及的源碼:

framework/base/core/java/android/content/BroadcastReceiver.java
framework/base/core/java/android/content/Context.java
framework/base/core/java/android/content/IntentFilter.java

framework/base/core/java/android/app/ContextImpl.java
framework/base/core/java/android/app/LoadedApk
framework/base/core/java/android/app/ActivityManagerNative.java
framework/base/core/java/android/app/ApplicationThreadNative.java
framework/base/core/java/android/app/ActivityThread.java

framework/base/services/core/java/com/android/server/ActivityManagerService.java
framework/base/services/core/java/com/android/server/am/BroadcastQueue.java
framework/base/services/core/java/com/android/server/am/BroadcastFilter.java
framework/base/services/core/java/com/android/server/am/BroadcastRecord.java
framework/base/services/core/java/com/android/server/am/ReceiverList.java

原文: http://gityuan.com/2016/06/04/broadcast-receiver/?utm_source=tuicool&utm_medium=referral 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章