广播接收器的注册,发送和接收广播的过程

基于源码9.0

广播接收器的注册

先来个不专业的时序图


注册广播接收器.png

注册广播,需要调用Context的registerReceiver方法,这是一个抽象方法,ContextWrapper类实现了这个方法。

 public abstract Intent registerReceiver(BroadcastReceiver receiver,
            IntentFilter filter, @Nullable String broadcastPermission,
            @Nullable Handler scheduler);

ContextWrapper的registerReceiver方法

@Override
public Intent registerReceiver(
    BroadcastReceiver receiver, IntentFilter filter,
    String broadcastPermission, Handler scheduler) {
    return mBase.registerReceiver(receiver, filter, broadcastPermission,  scheduler);
}

mBase是一个ContextImpl类型的对象。

ContextImpl的registerReceiver方法

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

ContextImpl的registerReceiverInternal方法

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        // IIntentReceiver类型的对象
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {//注释1处
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //注释2处
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //注释3处
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
            //注释4处
            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();
        }
    }

在注释1处判断如果LoadedApk类型的对象mPackageInfo不为null并且context不为null,就调用注释2处的代码通过mPackageInfo的getReceiverDispatcher方法来获取rd对象,否则就调用注释3处的代码来创建rd对象。

注释2处和注释3处的代码都是为了获取IIntentReceiver类型的对象rd,IIntentReceiver是一个Binder接口,用于广播的跨进程的通信。IIntentReceiver对应的实现类是LoadedApk.ReceiverDispatcher.InnerReceiver。

在注释4处调用了ActivityManagerService的registerReceiver方法。

ActivityManagerService的registerReceiver方法

 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
    
    ProcessRecord callerApp = null;
    //...
     synchronized(this) {
            if (caller != null) {
                //注释5处
                callerApp = getRecordForAppLocked(caller);
                //...
            }
          //...
          //注释6处
          Iterator actions = filter.actionsIterator();
            if (actions == null) {
                ArrayList noAction = new ArrayList(1);
                noAction.add(null);
                actions = noAction.iterator();
            }
            
           // 收集所有的粘性广播Intent
            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
            while (actions.hasNext()) {
                String action = actions.next();
                for (int id : userIds) {
                    ArrayMap> stickies = mStickyBroadcasts.get(id);
                    if (stickies != null) {
                        //获取匹配IntentFilter的action的粘性广播的Intent
                        ArrayList intents = stickies.get(action);
                        if (intents != null) {
                            if (stickyIntents == null) {
                                stickyIntents = new ArrayList();
                            }
                            //注释7处
                            stickyIntents.addAll(intents);
                        }
                    }
                }
            } 
    }
     ArrayList allSticky = null;
        if (stickyIntents != null) {
            final ContentResolver resolver = mContext.getContentResolver();
            // 查找所有匹配的粘性广播的intent
            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                Intent intent = stickyIntents.get(i);
              
                if (filter.match(resolver, intent, true, TAG) >= 0) {
                    if (allSticky == null) {
                        allSticky = new ArrayList();
                    }
                    //注释8处
                    allSticky.add(intent);
               }
            }
        }
    //...
 synchronized (this) {
        //...
        //注释9处
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    //...
                    //注释10处
                    rl.app.receivers.add(rl);
                }
                //...
                //注释11处
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
            //...
            //注释12处
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
          //...
          rl.add(bf);
          //注释13处
          mReceiverResolver.addFilter(bf);
          //...
          return sticky;

    }

}

在注释5处,调用getRecordForAppLocked方法获取ProcessRecord类型的对象callerApp,它用来描述请求AMS注册广播接收器的应用程序的进程信息。

在注释6处根据传入的IntentFilter 类型对象filter得到actions列表,根据actions列表和userIds得到所有的粘性广播的intent,并在注释7处传入到stickyIntents中。

在注释8处,从stickyIntents中找到匹配传入的参数filter的粘性广播的intent,然后将这些intent加入到allSticky中。

在注释9处获取ReceiverList对象,如果为null则创建。ReceiverList存储的是BroadcastFilter。

在注释12处创建了BroadcastFilter类型对象bf,并加入到ReceiverList中去。

在注释13处将bf加入到IntentResolver类型的对象mReceiverResolver中,这样当AMS接收到广播时就可以从mReceiverResolver中找到对应的广播接收者了,从而达到了注册广播接收器的作用。

发送和接收广播的过程

广播可分为无序广播(普通广播),有序广播和粘性广播,这里以无序广播为例来讲解广播发送的过程。


发送和接收无序广播.png

发送广播需要调用Context的sendBroadcast方法,ContextWrapper实现了这个方法。

@Override
public void sendBroadcast(Intent intent) {
    //调用ContextImpl的sendBroadcast方法
    mBase.sendBroadcast(intent);
}

ContextImpl的sendBroadcast方法

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

ActivityManagerService的broadcastIntent方法

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) {
            //注释1处,验证广播是否合法
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            //注释2处
            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;
        }
    }

在注释2处调用了broadcastIntentLocked方法

ActivityManagerService的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) {

        intent = new Intent(intent);
        //...
        // 找出谁将会接受这个广播
        List receivers = null;
        List registeredReceivers = null;
        //...
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            //根据intent的优先级获取广播队列
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            //创建BroadcastRecord对象,BroadcastRecord代表一个活动的广播
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            //...

            queue.enqueueOrderedBroadcastLocked(r);
            //注释3处
            queue.scheduleBroadcastsLocked();
    
        } 
     return ActivityManager.BROADCAST_SUCCESS;
}

在注释3处调用了BroadcastQueue的scheduleBroadcastsLocked方法。

BroadcastQueue的scheduleBroadcastsLocked方法

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

在方法内部使用了mHandler发送到了BROADCAST_INTENT_MSG类型的message。mHandler是一个BroadcastHandler类型的对象,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: {
                    //注释1处
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                      broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

这里要注意一下:如果注册广播接收器的时候,如果我们没有传递handler参数,那么BroadcastHandler的Looper就是主线程的Looper。
在上面的注释1处,调用了BroadcastQueue的processNextBroadcast方法

final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            processNextBroadcastLocked(fromMsg, false);
        }
    }
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        //...
        if (fromMsg) {
            mBroadcastsScheduled = false;
        }
       // 首先,立即发送无序广播
        while (mParallelBroadcasts.size() > 0) {
            r = mParallelBroadcasts.remove(0);     
            //广播接受者的个数
            final int N = r.receivers.size();
        
            for (int i=0; i

注释1处,调用了BroadcastQueue的deliverToRegisteredReceiverLocked方法

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
  //...
  //注释1处,调用performReceiveLocked方法
  performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
  //...
}

注释1处,调用了BroadcastQueue的performReceiveLocked方法

 void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        if (app != null) {//注释1处,
            if (app.thread != null) {//注释2处
                
                try {//注释3处
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState); 
                } catch (RemoteException ex) {
                    app.scheduleCrash("can't deliver broadcast");
                    throw ex;
                }
            } else {
                // 应用程序已经死亡了,Receiver不存在
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

注释1处和注释2处的代码表示如果广播接收器所在的应用程序进程存在并且正在运行,就执行注释3处的代码,app.thread表示的是ApplicationThread。
ApplicationThread的scheduleRegisteredReceiver方法

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            //注释1处
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

在注释1处调用了IIntentReceiver的performReceive方法。在上文中我们已经知道了
IIntentReceiver的实现类是LoadedApk.ReceiverDispatcher.InnerReceiver。

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;
               //...
              rd = mDispatcher.get();
                
                if (rd != null) {
                    //注释1处
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    IActivityManager mgr = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
}

在注释1处,调用了LoadedApk.ReceiverDispatcher的performReceive方法。

public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            //注释1处
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            //注释2处
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                //...
            }
        }

在注释1处,将广播的intent等信息封装成Args对象。Arg是
LoadedApk.ReceiverDispatcher的内部类。

Arg的getRunnable方法

 public final Runnable getRunnable() {
                return () -> {
                     try {
                            ClassLoader cl = mReceiver.getClass().getClassLoader();
                            intent.setExtrasClassLoader(cl);
                            intent.prepareToEnterProcess();
                            setExtrasClassLoader(cl);
                            receiver.setPendingResult(this);
                            //收到广播
                            receiver.onReceive(mContext, intent);
                    }
        }
}

在注释2处,intent == null肯定是flase,所以会执行mActivityThread.post(args.getRunnable())。最终会执行args.getRunnable()返回的Runnable对象的run方法,执行广播接收器的onReceive方法。

参考:
《Android进阶解密》

你可能感兴趣的:(广播接收器的注册,发送和接收广播的过程)