android广播这订阅、发布的过程

BroadcastReceiver是Android四大组件之一。它作为应用内、进程间的一种重要通信手段,能够将某个消息通过广播的形式 传递给它注册的对应广播接收器的对象,接收对象需要通过Context的registerReceiver函数注册到AMS中,当通过sendBroadcast发送广播时,所有注册了对应的IntentFilter的BroadcastReceiver对象就会接收到这个消息,BroadcastReceiver的onreceive方法就会被调用,这就是典型的发布——订阅模式,也就是我们所说的观察者模式。

registerReceiver函数并不是在Activity中实现的,于是我们把目标移向Activity的父类ContextWrapper,registerReceiver函数如下:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient {

}

public class ContextThemeWrapper extends ContextWrapper {

}

public class ContextWrapper extends Context {
 Context mBase;
... ...
@Override
 public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
 }
... ...
}

 这里的成员变量mBase,mBase是ContextImpl的实例,转移到ContextImpl的registerReceiver函数。

public class ContextImpl extends Context {

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

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

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

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

@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
        IntentFilter filter, String broadcastPermission, Handler scheduler) {
    return registerReceiverInternal(receiver, user.getIdentifier(),
            filter, broadcastPermission, scheduler, getOuterContext(), 0);
}

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();//            获取Handler来投递消息
            }
    //获取IIntentReceiver对象,通过它与AMS交互,并通过Handler传递消息
            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 {
       //调用ActivityManager的registerReceiver函数
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags);
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

... ....
}

注册广播接收器的函数调用最终进入到了ContextImpl的registerReceiverInternal 这个函数。这里的成员变量mPackageInfo是一个LoadedApk实例,它是用来负责处理广播的接收。参数broadcastPermission 和 scheduler 都为null,而参数Context是上面通过调用函数getOuterContext() 函数得到的,这里指向的是(Activity)。

由于条件mPackageInfo != null 和 context != null都成立,而且条件scheduler == null也成立,于是就调用mMainThread.getHandler来获得一个handler,这个Handler是用来分发ActivityyManagerService发送过的广播,这里的成员变量mMainThread是一个ActivityThread实例,我们先看看ActivityThread.getHandler函数的实现,然后再分析ContextImpl.registerReceiverInternal函数。

public final class ActivityThread {

    final H mH = new H();
     private class H extends Handler {

public void handleMessage(Message msg) {

    switch (msg.what) {
        ... ....
    }
}
    }

       final Handler getHandler() {
        return mH;
    }
}

有了这个Handler之后,就可以分发消息给应用程序处理了。

再回到上一步的ContextImpl的 registerReceiverInternal 函数中, 它通过mPackageInfo.getReceiverDispatcher,函数获得一个IIntentReceiver接口对象rd,这是一个Binder对象,接下来会把它传给ActivityManagerService ,ActivityManagerService在收到相应的广播时,就是通过这个Binder对象来通知MainActivity来接收的。

public final class LoadedApk {

}


public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
        Context context, Handler handler,
        Instrumentation instrumentation, boolean registered) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }
        if (rd == null) {
            rd = new ReceiverDispatcher(r, context, handler,
                    instrumentation, registered);
            if (registered) {
                if (map == null) {
                     //BroadcastReceiver为key,LoadedApk.ReceiverDispatcher为value。
                    map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
   //以context为key,map为value存储到mReceivers中。
                    mReceivers.put(context, map);
                }
                map.put(r, rd);
            }
        } else {
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        return rd.getIIntentReceiver();
    }
}

//ReceiverDispatcher为LoadedApk的静态内部类
static final class ReceiverDispatcher {

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


... ...
final IIntentReceiver.Stub mIIntentReceiver;
final BroadcastReceiver mReceiver;
final Context mContext;
final Handler mActivityThread;
... ...

ReceiverDispatcher(BroadcastReceiver receiver, Context context,
        Handler activityThread, Instrumentation instrumentation,
        boolean registered) {
    if (activityThread == null) {
        throw new NullPointerException("Handler must not be null");
    }

    mIIntentReceiver = new InnerReceiver(this, !registered);
    mReceiver = receiver;
    mContext = context;
    mActivityThread = activityThread;
    mInstrumentation = instrumentation;
    mRegistered = registered;
    mLocation = new IntentReceiverLeaked(null);
    mLocation.fillInStackTrace();
}

... ...
IIntentReceiver getIIntentReceiver() {
    return mIIntentReceiver;
}
... ...
}

在LoadedApk类的getReceiverDispatcher函数中,首先看一下参数r是不是已经有相应的BroadcastReceiver存在了,如果有,就直接返回;否则就重新创建一个ReceiverDispatcher,并且以r为key值保存在一个HashMap中,而这个HashMap又被存储在mReceivers这个map中,mReceivers以Context为Key、map为value。即这里的MainActivity为Key保存在LoadedApk的成员变量mReceivers中,只要给定一个Activity和BroadcastReceiver,就可以查看LoadedApk里面是否已经存在相应的广播接收发布器getReceiverDispatcher了。

在新创建的广播接收发布器ReceiverDispatcher时,会在构造函数里创建一个InnerReceiver实例,这是一个Binder对象,实现了IIntentReceiver接口,可以通过ReceiverDispatcher.getIIntentReceiver函数来获得,获得后就把它传递给ActivityManagerService,以便接收广播。在ReceiverDispatcher类的构造函数中,还会把Handler类型的参数activityThread保存下来,以便后面分发广播的时候使用。


/**********************************************************/
ReceiverDispatcher构造器
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
        Handler activityThread, Instrumentation instrumentation,
        boolean registered) {
    if (activityThread == null) {
        throw new NullPointerException("Handler must not be null");
    }

    mIIntentReceiver = new InnerReceiver(this, !registered);
    mReceiver = receiver;
    mContext = context;
    mActivityThread = activityThread;
    mInstrumentation = instrumentation;
    mRegistered = registered;
    mLocation = new IntentReceiverLeaked(null);
    mLocation.fillInStackTrace();
}
/***********************************************************/
#ReceiverDispatcher
 IIntentReceiver getIIntentReceiver() {
            return mIIntentReceiver;
  }

      /****************************************************************/



#ContextImpl
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    ... ...
  IIntentReceiver rd = null;
    try {
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags);
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

 再回到ContextImpl.registerReceiverInternal函数,在获得了IIntentReceiver类型的Binder对象后,就开始把它注册到ActivityManagerService中,具体代码如下:

#ActivityManagerService
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
            ... ...
}


#ActivityManagerService
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
    enforceNotIsolatedCaller("registerReceiver");
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    final boolean visibleToInstantApps
            = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
    int callingUid;
    int callingPid;
    boolean instantApp;
    synchronized(this) {
        if (caller != null) {
             //1.获取 ProcessRecord
            callerApp = getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when registering receiver " + receiver);
            }
            if (callerApp.info.uid != SYSTEM_UID &&
                    !callerApp.pkgList.containsKey(callerPackage) &&
                    !"android".equals(callerPackage)) {
                throw new SecurityException("Given caller package " + callerPackage
                        + " is not running in process " + callerApp);
            }
            callingUid = callerApp.info.uid;
            callingPid = callerApp.pid;
        } else {
            callerPackage = null;
            callingUid = Binder.getCallingUid();
            callingPid = Binder.getCallingPid();
        }

        instantApp = isInstantApp(callerApp, callerPackage, callingUid);
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_FULL_ONLY, "registerReceiver", callerPackage);

//2.根据Action查找匹配的stickly接收器
        Iterator<String> actions = filter.actionsIterator();
        if (actions == null) {
            ArrayList<String> noAction = new ArrayList<String>(1);
            noAction.add(null);
            actions = noAction.iterator();
        }

        // Collect stickies of users
        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
        while (actions.hasNext()) {
            String action = actions.next();
            for (int id : userIds) {
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                if (stickies != null) {
                    ArrayList<Intent> intents = stickies.get(action);
                    if (intents != null) {
                        if (stickyIntents == null) {
                            stickyIntents = new ArrayList<Intent>();
                        }
                        stickyIntents.addAll(intents);
                    }
                }
            }
        }
    }

    ArrayList<Intent> allSticky = null;
    if (stickyIntents != null) {
        final ContentResolver resolver = mContext.getContentResolver();
        // Look for any matching sticky broadcasts...
        for (int i = 0, N = stickyIntents.size(); i < N; i++) {
            Intent intent = stickyIntents.get(i);
            // Don't provided intents that aren't available to instant apps.
            if (instantApp &&
                    (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                continue;
            }
            // If intent has scheme "content", it will need to acccess
            // provider that needs to lock mProviderMap in ActivityThread
            // and also it may need to wait application response, so we
            // cannot lock ActivityManagerService here.
            if (filter.match(resolver, intent, true, TAG) >= 0) {
                if (allSticky == null) {
                    allSticky = new ArrayList<Intent>();
                }
                allSticky.add(intent);
            }
        }
    }

    // The first sticky in the list is returned directly back to the client.
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
    if (receiver == null) {
        return sticky;
    }

    synchronized (this) {
        if (callerApp != null && (callerApp.thread == null
                || callerApp.thread.asBinder() != caller.asBinder())) {
            // Original caller already died
            return null;
        }
     //3.获取ReceiverList
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());

这里传进来的receiver不为null,于是继续往下执行到注释3处。这里其实就是把广播接收器receiver保存到一个ReceiverList列表中,这个列表的宿主进程是rl.app,这里就是MainActivity所在的进程,在ActivityManagerService中,用一个进程记录模块来表示应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key保存在ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器。

        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);
        } else if (rl.uid != callingUid) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for uid " + callingUid
                    + " was previously registered for uid " + rl.uid
                    + " callerPackage is " + callerPackage);
        } else if (rl.pid != callingPid) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for pid " + callingPid
                    + " was previously registered for pid " + rl.pid
                    + " callerPackage is " + callerPackage);
        } else if (rl.userId != userId) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for user " + userId
                    + " was previously registered for user " + rl.userId
                    + " callerPackage is " + callerPackage);
        }
    //4.构建BroadcastFilter对象,并且添加到ReceiverList 中
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        rl.add(bf);

但是还没有把它和filter关联起来,这里就创建一个BroadcastFilter来把列表rl和filter关联起来,然后保存在ActivityManagerService的成员变量mReceiverResolver中,这样,就将广播接收器receiver以及其要接收的广播类型filter保存在ActivityManagerService中,以便以后能够接收到相应的广播并进行处理。

        if (!bf.debugCheck()) {
            Slog.w(TAG, "==> For Dynamic broadcast");
        }
        mReceiverResolver.addFilter(bf);

        // Enqueue broadcasts for all existing stickies that match
        // this filter.
        if (allSticky != null) {
            ArrayList receivers = new ArrayList();
            receivers.add(bf);

            final int stickyCount = allSticky.size();
            for (int i = 0; i < stickyCount; i++) {
                Intent intent = allSticky.get(i);
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                        null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
                        null, 0, null, null, false, true, true, -1);
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        }

        return sticky;
    }
}

 函数首先是获得调用registerReceiver函数的应用程序进程记录模块,即注释1,然后获取这个进程对应的pid、uid。注释2处获取到IntentFilter的所有Action,在MainActivity中构建的filter只有一个Action,就是前面描述的“info.update”,这里先通过getStickiesLocked函数(Android8.1中没有了)查找一下有没有对应的sticky intent列表存在。什么是Sticky Intent呢?我们在最后一次调用sendStickyBroadcast函数来发送某个Action类型的广播时,系统会把代表这个广播的Intent保存下来,这样,后来调用registerReceiver来注册相同Action类型的广播接收器,就会得到这个最后发出的广播,这就是为什么叫做Sticky Intent了。这个最后发出的广播虽然被处理完了,但是仍然被粘在ActivityManagerService中,以便下一个注册相应Action类型的广播接收器还能继续处理。

#ContextImpl
   @Override
    public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
                    options, false, false, getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


#ContextImpl
    @Override
    public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


#ActivityManagerService
  public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

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

... ...
(发送粘性广播)(这里涉及到了粘性广播的概念)
// We use userId directly here, since the "all" target is maintained
    // as a separate set of sticky broadcasts.
//我们在这里直接使用userId,因为“all”目标是作为一组独立的粘性广播维护的。
    if (userId != UserHandle.USER_ALL) {
      //但首先,如果这不是对所有用户的广播,那么请确保它不与所有用户的现有广播冲突。
        // But first, if this is not a broadcast to all users, then
        // make sure it doesn't conflict with an existing broadcast to
        // all users.
        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                UserHandle.USER_ALL);
        if (stickies != null) {
            ArrayList<Intent> list = stickies.get(intent.getAction());
            if (list != null) {
                int N = list.size();
                int i;
                for (i=0; i<N; i++) {
                    if (intent.filterEquals(list.get(i))) {
                        throw new IllegalArgumentException(
                                "Sticky broadcast " + intent + " for user "
                                + userId + " conflicts with existing global broadcast");
                    }
                }
            }
        }
    }
    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
    if (stickies == null) {
        stickies = new ArrayMap<>();
        mStickyBroadcasts.put(userId, stickies);
    }
    ArrayList<Intent> list = stickies.get(intent.getAction());
    if (list == null) {
        list = new ArrayList<>();
        stickies.put(intent.getAction(), list);
    }
    final int stickiesCount = list.size();
    int i;
    for (i = 0; i < stickiesCount; i++) {
        if (intent.filterEquals(list.get(i))) {
            // This sticky already exists, replace it.
            list.set(i, new Intent(intent));
            break;
        }
    }
    if (i >= stickiesCount) {
        list.add(new Intent(intent));
    }
}
... ...
}

继续往下看,这里传进来的receiver不为null,于是继续往下执行到注释3处。这里其实就是把广播接收器receiver保存到一个ReceiverList列表中,这个列表的宿主进程是rl.app,这里就是MainActivity所在的进程,在ActivityManagerService中,用一个进程记录模块来表示应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key保存在ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器。

再往下看注释4,只是把广播接收器receiver保存起来,但是还没有把它和filter关联起来,这里就创建一个BroadcastFilter来把列表rl和filter关联起来,然后保存在ActivityManagerService的成员变量mReceiverResolver中,这样,就将广播接收器receiver以及其要接收的广播类型filter保存在ActivityManagerService中,以便以后能够接收到相应的广播并进行处理。

广播的发送过程比广播接收的过程要复杂的多,不过这个过程依然以ActivityManagerService为核心。

简单总结应用程序发送广播的过程:

1.通过sendBroadcast把一个广播通过Binder发送给ActivityManagerService,ActivityManagerService根据这个广播的Action类型找到相应的广播接收器,然后把这个广播放进自己的消息队列中,就完成了第一阶段对这个广播的异步分发。

#ActivityManagerService

final int broadcastIntentLocked(ProcessRecord callerApp,
        String callerPackage, Intent intent, String resolvedType,
        IIntentReceiver resultTo, int resultCode, String resultData,
        Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        
        ... ...
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// Need to resolve the intent to interested receivers...

if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                // Query one target user at a time, excluding shell-restricted users
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
//查询到该Intent对应的BroadcastFilter,也就是接收器列表
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
  if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();  //处理广播的异步分发
            }
            registeredReceivers = null;
            NR = 0;

... ...
}

 2.ActivityManagerService在消息循环中处理这个广播,并通过Binder机制把这个广播分发给注册的ReceiverDispatcher,ReceiverDispatcher把这个广播放进MainActivity所在线程的消息队列中,就完成第二阶段对这个广播的异步分发。

#BroadcastQueue
    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);

        if (mBroadcastsScheduled) {
            return;
        }
       //mHandler发送一个消息
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

 #BroadcastQueue
   final BroadcastHandler mHandler;

#BroadcastQueue
BroadcastHandler 是 BroadcastQueue 内部类
    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: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                    processNextBroadcast(true);  //处理下一个广播
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

 3.ReceiverDispatcher的内部类Args在MainActiviy所在的线程消息循环中处理这个广播,最终是将这个广播分发给所注册的BroadcastReceiver实例的onReceive函数进行处理。

/**
 * Local state maintained about a currently loaded .apk.
 * @hide
 */
public final class LoadedApk {

... ...
#ReceiverDispatcher 是 LoadedApk 的内部类
 static final class ReceiverDispatcher {
... ...
 final class Args extends BroadcastReceiver.PendingResult {
... ...
public final Runnable getRunnable() {
... ...
//Lambda表达式

return () -> {

/*************************************************************************************************************************/
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;

if (ActivityThread.DEBUG_BROADCAST) {
    int seq = mCurIntent.getIntExtra("seq", -1);
    Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
            + " seq=" + seq + " to " + mReceiver);
    Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
            + " mOrderedHint=" + ordered);
}

final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
if (intent == null) {
    Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
            + ": run() previously called at "
            + Log.getStackTraceString(mPreviousRunStacktrace));
}

mCurIntent = null;
mDispatched = true;
mPreviousRunStacktrace = new Throwable("Previous stacktrace");
if (receiver == null || intent == null || mForgotten) {
    if (mRegistered && ordered) {
        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                "Finishing null broadcast to " + mReceiver);
        sendFinished(mgr);
    }
    return;
}

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
    ClassLoader cl = mReceiver.getClass().getClassLoader();
    intent.setExtrasClassLoader(cl);
    intent.prepareToEnterProcess();
    setExtrasClassLoader(cl);
    receiver.setPendingResult(this);
   //调用接收器的onReceive方法
    receiver.onReceive(mContext, intent);
} catch (Exception e) {
    if (mRegistered && ordered) {
        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                "Finishing failed broadcast to " + mReceiver);
        sendFinished(mgr);
    }
    if (mInstrumentation == null ||
            !mInstrumentation.onException(mReceiver, e)) {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        throw new RuntimeException(
                "Error receiving broadcast " + intent
                        + " in " + mReceiver, e);
    }
}

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


/***********************************************************************************************************************/
}
}
  }
}
}

简单来说,广播这就是一个订阅——发布的过程,通过一些map存储BroadcastReceiver,key就是封装了这些广播的信息类,如Action之类的。当发布一个广播时通过AMS到这个map中查找注册了这个广播的IntentFilter的BroadcastReceiver,然后通过ReceiverDispatcher将广播分发给各个订阅对象。从而完成这个发布——订阅过程。 

 参考《Android源码设计模式》

 

发布了161 篇原创文章 · 获赞 154 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zhangying1994/article/details/86761399