BroadcastReceiver注册和发送过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18242391/article/details/81609551

前言


BroadcastReceiver四大组件之一,作为应用内、进程间的一种重要通信机制,能够将消息通过广播的形式传递给它注册的对应广播接收器的对象,那么它们之间信息的传递机制,传递过程是如何的了?接下来就来从广播的注册以及发送两方面讲起,看下它们之间的代码执行过程。

注册


广播的注册调用的是

Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

这个方法真正的实现是在ContextWrapper中,因此我们去它的父类ContextWrapper 中看下它的实现

@Override
public Intent registerReceiver(
   BroadcastReceiver receiver, IntentFilter filter) {
   return mBase.registerReceiver(receiver, filter); //转发
}

这里的mBase是一个Context,而它是一个抽象类,它的具体实现是ContextImpl,那么继续转移到它的registerReceiver 方法中

@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) {
    return registerReceiverInternal(receiver, getUserId(),
            filter, broadcastPermission, scheduler, getOuterContext(), 0);
}

它接着调用另一个registerReceiver 的重载方法,在它的重载方法中接着转到调用registerReceiverInternal 方法中,它的实现过程如下:

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(); //1
            }
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true); //2
        } else {
      ...
        }
    }
    try {
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags); //3
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

这里的receiver 就是外面注册的广播,mPackageInfo 它是一个LoadedApk 实例,参数scheduler 转发过来就是为的, 所以这里首先会执行到注释1处,它会去获取一个handler, 这个Handler就是ActivityThread 里面维护的Handler ,它里面有处理各种消息事件的code 。接着调用到注释2处,看下getReceiverDispatcher 函数的实现

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) { //true
                map = mReceivers.get(context); //获取ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>>
                if (map != null) {
                    rd = map.get(r); //根据receiver获取ReceiverDispatcher
                }
            }
            if (rd == null) { 
                //构造一个ReceiverDispatcher, 如果集合中没有rd
                rd = new ReceiverDispatcher(r, context, handler,
                        instrumentation, registered);
                if (registered) { //true
                    if (map == null) {
                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                        mReceivers.put(context, map); 
                    }
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver(); 获取ReceiverDispatcher的getIIntentReceiver()方法
        }
    }
}

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

        InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
            mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
        }
    }
    ReceiverDispatcher(BroadcastReceiver receiver, Context context,
           Handler activityThread, Instrumentation instrumentation,
           boolean registered) {
       mIIntentReceiver = new InnerReceiver(this, !registered);
       mReceiver = receiver;
       mContext = context;
       mActivityThread = activityThread;
      ...
    }
    IIntentReceiver getIIntentReceiver() {
        return mIIntentReceiver;
    }

}

从这段代码可以看出ReceiverDispatcher 里面的InnerReceiver 是一个Binder 对象,在ReceiverDispatcher 的构造函数中创建了一个InnerReceiver 实例,这时候通过getReceiverDispatcher 获取的就是一个Binder 对象,同时在ReceiverDispatcher 中保存了mActivityThreadmIIntentReceiver 等实例,方便后面广播事件的分发调用。

回到registerReceiverInternal 方法,看注释3处,ActivityManager.getService()获取的就是一个ActivityManagerProxy 代理对象,然后调用registerReceiverInnerReceiver 注册给它。

class ActivityManagerProxy implements IActivityManager
{
    public Intent registerReceiver(IApplicationThread caller,
            IIntentReceiver receiver,
            IntentFilter filter, String perm) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
        filter.writeToParcel(data, 0);
        data.writeString(perm);
        //向AMS注册广播接收器的请求
        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 驱动程序就进入到ActivityManagerServiceregisterReceiver中。

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
  ...
    synchronized(this) {
        if (caller != null) {
            //get ProcessRecord  获取应用程序记录快,每个应用都用一个进程记录快记录
            callerApp = getRecordForAppLocked(caller);
            if (callerApp == null) {
            ...
            }
            if (callerApp.info.uid != SYSTEM_UID &&
                    !callerApp.pkgList.containsKey(callerPackage) &&
                    !"android".equals(callerPackage)) {
             ...
            }、
            //获取uid, pid
            callingUid = callerApp.info.uid;
            callingPid = callerApp.pid;
        } else {
        ...
        }

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

        //这里和粘性广播相关 1
        Iterator<String> actions = filter.actionsIterator();
        ...

        // 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集合中,后面会处理这个集合
                        allSticky.add(intent);
                    }
                }
            }
  ...

    synchronized (this) {
        ...
        //获取ReceiverList 它是一个arrayList集合 2 
        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 {
            ...
            }
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        }
        ...
        //构建BroadcastFilter对象 3
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        添加到ReceiverList中
        rl.add(bf);
        ...
        mReceiverResolver.addFilter(bf);

        ...

        return sticky;
    }
}

在这段代码 首先看注释1处 这里会获取匹配的粘性广播allSticky,当registerReceiver 的时候,如果有匹配的广播,后面就会直接分发去调用注册的广播。接着走到注释2处,获取ReceiverList 实例,接着走到注释3处,构建一个BroadcastFilter 将广播接收器列表ReceiverListfilter 关联起来,然后保存到AMS的成员变量mReceiverResolver 中,方便以后可以接受到相应的广播进行处理。 这样就完成了广播的注册过程。

广播注册UML如下
这里写图片描述

扫描二维码关注公众号,回复: 3712472 查看本文章

发送


发送过程相对于注册过程还是比较复杂的,这里以发送普通广播sendBroadcast为例,同样也会调用到ContextImpl类的sendBroadcast方法中。

@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess(this);
        ActivityManager.getService().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId()); //1
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

看注释1处最终也会通过Binder调用到AMSbroadcastIntent 方法,而在这个方法中接着会调用到broadcastIntentLocked 方法中,

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

     ...
        //1
        List<BroadcastFilter> registeredReceiversForUser =
               mReceiverResolver.queryIntent(intent,
                       resolvedType, false /*defaultOnly*/, users[i]);
       if (registeredReceivers == null) {
           registeredReceivers = registeredReceiversForUser;
       } else if (registeredReceiversForUser != null) {
           registeredReceivers.addAll(registeredReceiversForUser);
       }

      BroadcastQueue queue = broadcastQueueForIntent(intent);

       queue.enqueueOrderedBroadcastLocked(r);
       //2
       queue.scheduleBroadcastsLocked(); 
      ...
    }
}

首先在注释1处查询对应intentBroadcastFilter 接收器列表,然后在注视2处将广播信息放到自己的消息队列中。

public void scheduleBroadcastsLocked() {
...
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

在这个方法中通过内部维护的一个mHandler 对象发送了一个message,对应的处理过程如下

private final class BroadcastHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                  ...
                    processNextBroadcast(true);
                } break;
               ...
            }
        }
    }

接着会调用processNextBroadcast 处理广播消息,它的方法很长,它最终会调用deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); 来将消息分发给注册者执行,这里是第一阶段广播的事件分发。

接着在它的方法中又会调用performReceiveLocked 方法,然后它的方法里面有这样一句话

app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);

这里的thread 是一个IApplicationThread 对象,它的具体实现是客户端调用者的ApplicationThread 对象,也就是说这里通过binder 将广播消息传回给调用者进程ApplicationThread,接着看这个对象里面的scheduleRegisteredReceiver 方法

private class ApplicationThread extends IApplicationThread.Stub {
    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);
       receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
               sticky, sendingUser); //1
    }
}

注释1处的receiver 实例就是前面注册广播的LoadedApk.ReceiverDispatcher.InnerReceiver 对象实例,这里接着会调用到它的performReceive 方法

@Override
public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final LoadedApk.ReceiverDispatcher rd;
    if (intent == null) {
..
    } else {
        rd = mDispatcher.get();  //WeakReference<LoadedApk.ReceiverDispatcher>
    }
   ...
    if (rd != null) {
        rd.performReceive(intent, resultCode, data, extras,
                ordered, sticky, sendingUser);//1
    } else {
    ...
    }
}

接着注释1处会调用ReceiverDispatcherperformReceive 方法

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
 ...
    if (intent == null || !mActivityThread.post(args.getRunnable()) /*1*/) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManager.getService();
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing sync broadcast to " + mReceiver);
            args.sendFinished(mgr);
        }
    }
}

注释1处会调用mActivityThread.post(args.getRunnable())mActivityThreadActivityThread 中维护的一个内部Handler ,它的实例化在调用者线程,也就是主线程,并且Args 内部 维护了一个getRunnable() 方法,所以最终会在主线程里面执行这个方法

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

   ...

        final IActivityManager mgr = ActivityManager.getService();
        final Intent intent = mCurIntent;
   ...    
        try {
            ClassLoader cl = mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            receiver.onReceive(mContext, intent); //1
        } catch (Exception e) {
        ...
        }
        ...
    };
}

最终会在注释1处调用接收器的onReceive方法,这里是第二阶段广播的事件分发。

广播发送UML类图如下

这里写图片描述

总结


到这里整个广播事件注册,发送流程已经完成了,还是很复杂的,简单来看它就是一个订阅–发布的过程,通过map存储BroadcastReceiver ,当注册广播时候,通过AMS存放到map中, 发送广播的时候,通过IntentFilterAMS中查询对应的BroadcastReceiver ,然后通过两次消息分发,以及ReceiverDispatcher发送给订阅者调用,从而完成整个过程。

猜你喜欢

转载自blog.csdn.net/qq_18242391/article/details/81609551