Android Broadcast广播机制分析

基于Android 6.0的源码剖析, 分析android广播的发送与接收流程。java

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

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

framework/base/core/java/android/app/
  - ActivityManagerNative.java (内含AMP)
  - ActivityManager.java
  - ApplicationThreadNative.java (内含ATP)
  - ActivityThread.java (内含ApplicationThread)
  - ContextImpl.java
  - LoadedApk

1、概述

广播(Broadcast)机制用于进程/线程间通讯,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver即是Android四大组件之一。android

BroadcastReceiver分为两类:git

  • 静态广播接收者:经过AndroidManifest.xml的标签来申明的BroadcastReceiver。
  • 动态广播接收者:经过AMS.registerReceiver()方式注册的BroadcastReceiver,动态注册更为灵活,可在不须要时经过unregisterReceiver()取消注册。

从广播发送方式可分为三类:缓存

  • 普通广播:经过Context.sendBroadcast()发送,可并行处理
  • 有序广播:经过Context.sendOrderedBroadcast()发送,串行处理
  • Sticky广播:经过Context.sendStickyBroadcast()发送

1.1 BroadcastRecord

广播在系统中以BroadcastRecord对象来记录, 该对象有几个时间相关的成员变量.网络

final class BroadcastRecord extends Binder {
    final ProcessRecord callerApp; //广播发送者所在进程
    final String callerPackage; //广播发送者所在包名
    final List receivers;   // 包括动态注册的BroadcastFilter和静态注册的ResolveInfo

    final String callerPackage; //广播发送者
    final int callingPid;   // 广播发送者pid
    final List receivers;   // 广播接收者
    int nextReceiver;  // 下一个被执行的接收者
    IBinder receiver; // 当前正在处理的接收者
    int anrCount;   //广播ANR次数

    long enqueueClockTime;  //入队列时间
    long dispatchTime;      //分发时间
    long dispatchClockTime; //分发时间
    long receiverTime;      //接收时间(首次等于dispatchClockTime)
    long finishTime;        //广播完成时间

}
  • enqueueClockTime 伴随着 scheduleBroadcastsLocked
  • dispatchClockTime伴随着 deliverToRegisteredReceiverLocked
  • finishTime 位于 addBroadcastToHistoryLocked方法内

2、注册广播

广播注册,对于应用开发来讲,每每是在Activity/Service中调用registerReceiver()方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。另外调用getOuterContext()可获取最外层的调用者Activity或Service。并发

2.1 registerReceiver

[ContextImpl.java]app

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

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) {
    return registerReceiverInternal(receiver, getUserId(),
            filter, broadcastPermission, scheduler, getOuterContext());
}

其中broadcastPermission拥有广播的权限控制,scheduler用于指定接收到广播时onRecive执行线程,当scheduler=null则默认表明在主线程中执行,这也是最多见的用法异步

2.2 registerReceiverInternal

[ContextImpl.java]oop

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进程与该进程的通讯。post

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();
}

此处mActivityThread即是前面传递过来的当前主线程的Handler.

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);

    //Command为REGISTER_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) {
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    ...
    synchronized(this) {
        if (caller != null) {
            //从mLruProcesses查询调用者的进程信息【见2.5.1】
            callerApp = getRecordForAppLocked(caller);
            ...
            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. 这就是平时所加须要监听的广播action
        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 {
                receiver.asBinder().linkToDeath(rl, 0); //注册死亡通知
                ...
                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返回前台或后台广播队列【见2.5.3】
                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。

在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,任何一项匹配不成功都会失败。

2.5.3 AMS.broadcastQueueForIntent

BroadcastQueue broadcastQueueForIntent(Intent intent) {
    final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
    return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}

broadcastQueueForIntent(Intent intent)经过判断intent.getFlags()是否包含FLAG_RECEIVER_FOREGROUND 来决定是前台或后台广播,进而返回相应的广播队列mFgBroadcastQueue或者mBgBroadcastQueue。

  • 当Intent的flags包含FLAG_RECEIVER_FOREGROUND,则返回mFgBroadcastQueue;
  • 当Intent的flags不包含FLAG_RECEIVER_FOREGROUND,则返回mBgBroadcastQueue;

2.6 广播注册小结

注册广播:

  1. 传递的参数为广播接收者BroadcastReceiver和Intent过滤条件IntentFilter;
  2. 建立对象LoadedApk.ReceiverDispatcher.InnerReceiver,该对象继承于IIntentReceiver.Stub;
  3. 经过AMS把当前进程的ApplicationThread和InnerReceiver对象的代理类,注册登记到system_server进程;
  4. 当广播receiver没有注册过,则建立广播接收者队列ReceiverList,该对象继承于ArrayList, 并添加到AMS.mRegisteredReceivers(已注册广播队列);
  5. 建立BroadcastFilter,并添加到AMS.mReceiverResolver;
  6. 将BroadcastFilter添加到该广播接收者的ReceiverList

另外,当注册的是Sticky广播:

  • 建立BroadcastRecord,并添加到BroadcastQueue的mParallelBroadcasts(并行广播队列),注册后调用AMS来尽快处理该广播。
  • 根据注册广播的Intent是否包含FLAG_RECEIVER_FOREGROUND,则mFgBroadcastQueue

广播注册完, 另外一个操做即是在广播发送过程.

3、 发送广播

发送广播是在Activity或Service中调用sendBroadcast()方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。

3.1 sendBroadcast

[ContextImpl.java]

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) {
        ...
    }
}

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);

    //Command为BROADCAST_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) {

    //step1: 设置flag
    //step2: 广播权限验证
    //step3: 处理系统相关广播
    //step4: 增长sticky广播
    //step5: 查询receivers和registeredReceivers
    //step6: 处理并行广播
    //step7: 合并registeredReceivers到receivers
    //step8: 处理串行广播

    return ActivityManager.BROADCAST_SUCCESS;
}

broadcastIntentLocked方法比较长,这里划分为8个部分来分别说明。

3.4.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 //升级模式下,容许系统准备就绪前能够发送广播

3.4.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())) {
            ...
        }
    } 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时,虽然不但愿该应用发送这种广播,处于兼容性考虑,限制该广播只容许发送给本身,不然抛出异常。

3.4.3 处理系统相关广播

final String action = intent.getAction();
if (action != null) {
    switch (action) {
        case Intent.ACTION_UID_REMOVED: //uid移除
        case Intent.ACTION_PACKAGE_REMOVED: //package移除
        case Intent.ACTION_PACKAGE_ADDED: //增长package
        case Intent.ACTION_PACKAGE_CHANGED: //package改变

        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: //外部设备不可用
        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: //外部设备可用

        case Intent.ACTION_TIMEZONE_CHANGED: //时区改变,通知全部运行中的进程
        case Intent.ACTION_TIME_CHANGED: //时间改变,通知全部运行中的进程

        case Intent.ACTION_CLEAR_DNS_CACHE: //DNS缓存清空
        case Proxy.PROXY_CHANGE_ACTION: //网络代理改变
    }
}

这个过主要处于系统相关的10类广播,这里不就展开讲解了.

3.4.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里面。

3.4.5 查询receivers和registeredReceivers

List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
//当容许静态接收者处理该广播,则经过PKMS根据Intent查询相应的静态receivers
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
    receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
    if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
        ...
    } else {
        // 查询相应的动态注册的广播
        registeredReceivers = mReceiverResolver.queryIntent(intent,
                resolvedType, false, userId);
    }
}
  • receivers:记录着匹配当前intent的全部静态注册广播接收者;
  • registeredReceivers:记录着匹配当前的全部动态注册的广播接收者。

其余说明:

  • 根据userId来决定广播是发送给所有的接收者,仍是指定的userId;
  • 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;
}

3.4.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) {
    //根据intent的flag来判断前台队列或者后台队列[见小节2.5.3]
    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,记录着全部的并行广播。

// 并行广播,加入mParallelBroadcasts队列
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
    mParallelBroadcasts.add(r);
    r.enqueueClockTime = System.currentTimeMillis();
}

3.4.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)) {
        ...
    }

    //[3.4.6]有一个处理动态广播的过程,处理完后再执行将动态注册的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++;
}

动态注册的registeredReceivers,所有合并都receivers,再统一按串行方式处理。

3.4.8 处理串行广播

if ((receivers != null && receivers.size() > 0)
        || resultTo != null) {
    //根据intent的flag来判断前台队列或者后台队列[见小节2.5.3]
    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,记录着全部的有序广播。

// 串行广播 加入mOrderedBroadcasts队列
public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
    mOrderedBroadcasts.add(r);
    r.enqueueClockTime = System.currentTimeMillis();
}

3.5 小结

发送广播过程:

  1. 默认不发送给已中止(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES)的应用包;
  2. 处理各类PACKAGE,TIMEZONE等相关的系统广播;
  3. 当为粘性广播,则将sticky广播增长到list,并放入mStickyBroadcasts里面;
  4. 当广播的Intent没有设置FLAG_RECEIVER_REGISTERED_ONLY,则容许静态广播接收者来处理该广播; 建立BroadcastRecord对象,并将该对象加入到相应的广播队列, 而后调用BroadcastQueue的scheduleBroadcastsLocked()方法来完成的不一样广播处理:

处理方式:

  1. Sticky广播: 广播注册过程处理AMS.registerReceiver,开始处理粘性广播,见小节[2.5];
    • 建立BroadcastRecord对象;
    • 并添加到mParallelBroadcasts队列;
    • 而后执行queue.scheduleBroadcastsLocked;
  2. 并行广播: 广播发送过程处理,见小节[3.4.6]
    • 只有动态注册的mRegisteredReceivers才会并行处理;
    • 会建立BroadcastRecord对象;
    • 并添加到mParallelBroadcasts队列;
    • 而后执行queue.scheduleBroadcastsLocked;
  3. 串行广播: 广播发送广播处理,见小节[3.4.8]
    • 全部静态注册的receivers以及动态注册mRegisteredReceivers合并到一张表处理;
    • 建立BroadcastRecord对象;
    • 并添加到mOrderedBroadcasts队列;
    • 而后执行queue.scheduleBroadcastsLocked;

可见无论哪一种广播方式,都是经过broadcastQueueForIntent()来根据intent的flag来判断前台队列或者后台队列,而后再调用对应广播队列的scheduleBroadcastsLocked方法来处理广播;

4、 处理广播

在发送广播过程当中会执行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来处理:

4.1.1 BroadcastHandler

public ActivityManagerService(Context systemContext) {
    //名为"ActivityManager"的线程
    mHandlerThread = new ServiceThread(TAG,
            android.os.Process.THREAD_PRIORITY_FOREGROUND, false);
    mHandlerThread.start();
    mHandler = new MainHandler(mHandlerThread.getLooper());
    ...
    //建立BroadcastQueue对象
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "foreground", BROADCAST_FG_TIMEOUT, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "background", BROADCAST_BG_TIMEOUT, true);
    ...
}


BroadcastQueue(ActivityManagerService service, Handler handler,
        String name, long timeoutPeriod, boolean allowDelayBehindServices) {
    mService = service;
    //建立BroadcastHandler
    mHandler = new BroadcastHandler(handler.getLooper());
    mQueueName = name;
    mTimeoutPeriod = timeoutPeriod;
    mDelayBehindServices = allowDelayBehindServices;
}

因而可知BroadcastHandler采用的是”ActivityManager”线程的Looper

private final class BroadcastHandler extends Handler {

    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) {
        //part1: 处理并行广播
        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);//将广播添加历史统计
        }

        //part2: 处理当前有序广播
        do {
            if (mOrderedBroadcasts.size() == 0) {
                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); //当广播处理时间超时,则强制结束这条广播
                }
            }
            ...
            if (r.receivers == null || r.nextReceiver >= numReceivers
                    || r.resultAbort || forceReceive) {
                if (r.resultTo != null) {
                    //处理广播消息消息,调用到onReceive()
                    performReceiveLocked(r.callerApp, r.resultTo,
                        new Intent(r.intent), r.resultCode,
                        r.resultData, r.resultExtras, false, false, r.userId);
                }

                cancelBroadcastTimeoutLocked(); //取消BROADCAST_TIMEOUT_MSG消息
                addBroadcastToHistoryLocked(r);
                mOrderedBroadcasts.remove(0);
                continue;
            }
        } while (r == null);

        //part3: 获取下一个receiver
        r.receiverTime = SystemClock.uptimeMillis();
        if (recIdx == 0) {
            r.dispatchTime = r.receiverTime;
            r.dispatchClockTime = System.currentTimeMillis();
        }
        if (!mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            setBroadcastTimeoutLocked(timeoutTime); //设置广播超时延时消息
        }

        //part4: 处理下条有序广播
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                info.activityInfo.applicationInfo.uid, false);
        if (app != null && app.thread != null) {
            app.addPackage(info.activityInfo.packageName,
                    info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
            processCurBroadcastLocked(r, app); //[处理串行广播]
            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) {
            ...
            return;
        }
    }
}

此处mService为AMS,整个流程仍是比较长的,全程持有AMS锁,因此广播效率低的状况下,直接会严重影响这个手机的性能与流畅度,这里应该考虑细化同步锁的粒度。

  • 设置广播超时延时消息: setBroadcastTimeoutLocked:
  • 当广播接收者等待时间过长,则调用broadcastTimeoutLocked(false);
  • 当执行完广播,则调用cancelBroadcastTimeoutLocked;

4.2.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);//将广播添加历史统计
}

经过while循环, 一次性分发完全部的并发广播后,则分发完成后则添加到历史广播队列. fromMsg是指processNextBroadcast()是否由BroadcastHandler所调用的.

private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
    if (r.callingUid < 0) { return; } r.finishTime = SystemClock.uptimeMillis(); //记录分发完成时间 mBroadcastHistory[mHistoryNext] = r; mHistoryNext = ringAdvance(mHistoryNext, 1, MAX_BROADCAST_HISTORY); mBroadcastSummaryHistory[mSummaryHistoryNext] = r.intent; mSummaryHistoryEnqueueTime[mSummaryHistoryNext] = r.enqueueClockTime; mSummaryHistoryDispatchTime[mSummaryHistoryNext] = r.dispatchClockTime; mSummaryHistoryFinishTime[mSummaryHistoryNext] = System.currentTimeMillis(); mSummaryHistoryNext = ringAdvance(mSummaryHistoryNext, 1, MAX_BROADCAST_SUMMARY_HISTORY); }

4.2.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) {
            //处理广播消息消息,调用到onReceive()
            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,接收者个数numReceivers越多则广播超时总时长越大。

4.2.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));

4.2.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建立进程。

接下来,介绍deliverToRegisteredReceiverLocked的处理流程:

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 performReceiveLocked

[-> 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

[-> ApplicationThreadNative.java ::ApplicationThreadProxy]

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端发送消息(oneway调用方式), ATP所对应的Bn端位于发送广播调用端所在进程的ApplicationThread,即进入AT.scheduleRegisteredReceiver, 接下来讲明该方法。

4.6 AT.scheduleRegisteredReceiver

[-> ActivityThread.java ::ApplicationThread]

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 {
       ...
    }
}

此处方法LoadedApk()属于LoadedApk.ReceiverDispatcher.InnerReceiver, 也就是LoadedApk内部类的内部类InnerReceiver.

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)) {
        //消息成功post到主线程,则不会走此处。
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            args.sendFinished(mgr);
        }
    }
}

其中Args继承于BroadcastReceiver.PendingResult,实现了接口Runnable; 其中mActivityThread是当前进程的主线程, 是由[小节2.3.1]完成赋值过程.

这里mActivityThread.post(args) 消息机制,关于Handler消息机制,见Android消息机制1-Handler(Java层),把消息放入MessageQueue,再调用Args的run()方法。

4.9 ReceiverDispatcher.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(); //【见小节4.10】
            }
        }
      }
    }

接下来,便进入主线程,最终调用BroadcastReceiver具体实现类的onReceive()方法。

4.10 PendingResult.finish

[-> BroadcastReceiver.java ::PendingResult]

public final void finish() {
  if (mType == TYPE_COMPONENT) { //表明是静态注册的广播
      final IActivityManager mgr = ActivityManagerNative.getDefault();
      if (QueuedWork.hasPendingWork()) {
          QueuedWork.singleThreadExecutor().execute( new Runnable() {
              void run() {
                  sendFinished(mgr); //[见小节4.10.1]
              }
          });
      } else {
          sendFinished(mgr); //[见小节4.10.1]
      }
  } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { //动态注册的串行广播
      final IActivityManager mgr = ActivityManagerNative.getDefault();
      sendFinished(mgr); //[见小节4.10.1]
  }
}

主要功能:

  • 静态注册的广播接收者:
    • 当QueuedWork工做未完成, 即SharedPreferences写入磁盘的操做没有完成, 则等待完成再执行sendFinished方法;
    • 当QueuedWork工做已完成, 则直接调用sendFinished方法;
  • 动态注册的广播接收者:
    • 当发送的是串行广播, 则直接调用sendFinished方法.

另外常量参数说明:

  • TYPE_COMPONENT: 静态注册
  • TYPE_REGISTERED: 动态注册
  • TYPE_UNREGISTERED: 取消注册

4.10.1 sendFinished

[-> BroadcastReceiver.java ::PendingResult]

public void sendFinished(IActivityManager am) {
    synchronized (this) {
        mFinished = true;
        ...
        // mOrderedHint表明发送是否为串行广播 [见小节4.10.2]
        if (mOrderedHint) {
            am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                    mAbortBroadcast, mFlags);
        } else {
            //并行广播, 但属于静态注册的广播, 仍然须要告知AMS. [见小节4.10.2]
            am.finishReceiver(mToken, 0, null, null, false, mFlags);
        }
        ...
    }
}

此处AMP.finishReceiver,通过binder调用,进入AMS.finishReceiver方法

4.10.2 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) {
                //[见小节4.10.3]
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                    resultData, resultExtras, resultAbort, true);
            }
        }

        if (doNext) {
            //处理下一条广播
            r.queue.processNextBroadcast(false);
        }
        trimApplications();
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

4.10.3 BQ.finishReceiverLocked

[-> BroadcastQueue.java]

public boolean finishReceiverLocked(BroadcastRecord r, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
    final int state = r.state;
    final ActivityInfo receiver = r.curReceiver;
    r.state = BroadcastRecord.IDLE;

    r.receiver = null;
    r.intent.setComponent(null);
    if (r.curApp != null && r.curApp.curReceiver == r) {
        r.curApp.curReceiver = null;
    }
    if (r.curFilter != null) {
        r.curFilter.receiverList.curBroadcast = null;
    }
    r.curFilter = null;
    r.curReceiver = null;
    r.curApp = null;
    mPendingBroadcast = null;

    r.resultCode = resultCode;
    r.resultData = resultData;
    r.resultExtras = resultExtras;
    if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
        r.resultAbort = resultAbort;
    } else {
        r.resultAbort = false;
    }

    if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
            && r.queue.mOrderedBroadcasts.size() > 0
            && r.queue.mOrderedBroadcasts.get(0) == r) {
        ActivityInfo nextReceiver;
        if (r.nextReceiver < r.receivers.size()) {
            Object obj = r.receivers.get(r.nextReceiver);
            nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
        } else {
            nextReceiver = null;
        }

        if (receiver == null || nextReceiver == null
                || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
                || !receiver.processName.equals(nextReceiver.processName)) {
            if (mService.mServices.hasBackgroundServices(r.userId)) {
                r.state = BroadcastRecord.WAITING_SERVICES;
                return false;
            }
        }
    }
    r.curComponent = null;

    return state == BroadcastRecord.APP_RECEIVE
            || state == BroadcastRecord.CALL_DONE_RECEIVE;
}

5、总结

5.1 基础知识

1.BroadcastReceiver分为两类:

  • 静态广播接收者:经过AndroidManifest.xml的标签来申明的BroadcastReceiver;
  • 动态广播接收者:经过AMS.registerReceiver()方式注册的BroadcastReceiver, 不须要时记得调用unregisterReceiver();

2.广播发送方式可分为三类:

类型 方法 ordered sticky
普通广播 sendBroadcast false false
有序广播 sendOrderedBroadcast true false
Sticky广播 sendStickyBroadcast false true

3.广播注册registerReceiver():默认将当前进程的主线程设置为scheuler. 再向AMS注册该广播相应信息, 根据类型选择加入mParallelBroadcasts或mOrderedBroadcasts队列.

4.广播发送processNextBroadcast():根据不一样状况调用不一样的处理过程:

  • 若是是动态广播接收者,则调用deliverToRegisteredReceiverLocked处理;
  • 若是是静态广播接收者,且对应进程已经建立,则调用processCurBroadcastLocked处理;
  • 若是是静态广播接收者,且对应进程还没有建立,则调用startProcessLocked建立进程。

5.2 流程图

最后,经过一幅图来总结整个广播处理过程. 点击查看大图

send_broadcast

5.2.1 并行广播

整个过程涉及过程进程间通讯, 先来讲说并行广播处理过程:

  1. 广播发送端所在进程: 步骤1~2;
  2. system_server的binder线程: 步骤3~5;
  3. system_server的ActivityManager线程: 步骤6~11;
  4. 广播接收端所在进程的binder线程: 步骤12~13;
  5. 广播接收端所在进程的主线程: 步骤14~15,以及23;
  6. system_server的binder线程: 步骤24~25.

5.2.2 串行广播

能够看出整个流程中,步骤8~15是并行广播, 而步骤16~22则是串行广播.那么再来讲说串行广播的处理过程.

  1. 广播发送端所在进程: 步骤1~2;
  2. system_server的binder线程: 步骤3~5;
  3. system_server的ActivityManager线程:步骤6以及16~18;
  4. 广播接收端所在进程的binder线程: 步骤19;
  5. 广播接收端所在进程的主线程: 步骤20~22;
  6. system_server的binder线程: 步骤24~25.

再来讲说几个关键的时间点:

  • enqueueClockTime: 位于步骤4 scheduleBroadcastsLocked(), 这是在system_server的binder线程.
  • dispatchClockTime: 位于步骤8 deliverToRegisteredReceiverLocked(),这是在system_server的ActivityManager线程.
  • finishTime : 位于步骤11 addBroadcastToHistoryLocked()以后, 这是在并行广播向全部receivers发送完成后的时间点,而串行广播则是一个一个发送完成才会继续.

5.2.3 粘性广播

对于粘性广播,registerReceiver()会有一个返回值,数据类型为Intent。 只有粘性广播在注册过程过程会直接返回Intent,里面带有相关参数。 好比常见的使用场景好比Battery广播的注册。

5.3 广播处理机制

  1. 当发送串行广播(ordered=true)的状况下:
    • 静态注册的广播接收者(receivers),采用串行处理;
    • 动态注册的广播接收者(registeredReceivers),采用串行处理;
  2. 当发送并行广播(ordered=false)的状况下:
    • 静态注册的广播接收者(receivers),依然采用串行处理;
    • 动态注册的广播接收者(registeredReceivers),采用并行处理;

简单来讲,静态注册的receivers始终采用串行方式来处理(processNextBroadcast); 动态注册的registeredReceivers处理方式是串行仍是并行方式, 取决于广播的发送方式(processNextBroadcast)。

静态注册的广播每每其所在进程尚未建立,而进程建立相对比较耗费系统资源的操做,因此 让静态注册的广播串行化,能防止出现瞬间启动大量进程的喷井效应。

ANR时机:只有串行广播才须要考虑超时,由于接收者是串行处理的,前一个receiver处理慢,会影响后一个receiver;并行广播 经过一个循环一次性向全部的receiver分发广播事件,因此不存在彼此影响的问题,则没有广播超时;

  • 串行广播超时状况1:某个广播总处理时间 > 2* receiver总个数 * mTimeoutPeriod, 其中mTimeoutPeriod,前台队列默认为10s,后台队列默认为60s;
  • 串行广播超时状况2:某个receiver的执行时间超过mTimeoutPeriod;
相关文章
相关标签/搜索