Android 广播启动流程

1,874 阅读6分钟

概述

我们从三个方面来分析广播的流程

  • 广播的注册
  • 广播的发送
  • 广播的处理

广播的注册

广播的注册分为静态注册和动态注册,我们主要分析动态注册

首先我们从context.registerReceiver()这个方法开始,看他内部调用了ContextWrapper#registerReceiver方法

ContextWrapper.java

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

mBase的实现类是ContextImpl

ContextImpl.java

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

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();
            }
            //注释1
            //获取IIntentReceiver对象
            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 {
        //注释2
        //调用AMP.registerReceiver
        return ActivityManagerNative.getDefault().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName,
                rd, filter, broadcastPermission, userId);
    } catch (RemoteException e) {
        return null;
    }
}

我们先看一下注释1,他的主要作用是获取IIntentReceiver对象,其中mPackageInfoLoadedApk类型,我们看一下IIntentReceiver到底是什么

LoadedApk.java

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

IIntentReceiver原来是一个Binder接口,用于广播的跨进程通信,他在LoadedApk.ReceiverDispatcher.InnerReceiver中实现

ActivityManagerService.java

接下来我们看一下注释2,ActivityManagerNative.getDefault().registerReceiver,其中ActivityManagerNative.getDefault()这个最终会指向ActivityManagerService,这也是一个Binder用于进程间的通信,我们看一下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) {
            //注释1
            //查询调用者的进程信息
            callerApp = getRecordForAppLocked(caller);
            ...
            //获取IntentFilter中的actions,这个就是平时所加的action
            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) {
                   //从mStickyBroadcasts中查看用户的sticky Inten
                    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>();
                            }
                            //注释3
                            //把粘性广播添加到列表中
                            stickyIntents.addAll(intents);
                        }
                    }
                }
            }
        }
        ...


        synchronized (this) {
            if (callerApp != null && (callerApp.thread == null
                    || callerApp.thread.asBinder() != caller.asBinder())) {
                // Original caller already died
                return null;
            }
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                //对于未注册的广播,则创建接受者队列
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
                    rl.app.receivers.add(rl);
                } else {
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                //新建的接受者队列,添加到已注册广播队列
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
            ...
            //创建BroadcastFilter,并添加到接受者队列
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
                Slog.w(TAG, "Receiver with filter " + filter
                        + " already registered for pid " + rl.pid
                        + ", callerPackage is " + callerPackage);
            } else {
                rl.add(bf);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
                //新建的BroadcastFilter,添加到mReceiverResolver队列中
                mReceiverResolver.addFilter(bf);
            }
            ...

            return sticky;
        }
    }

这个方法有点长,其中mRegisteredReceivers记录着所有已经注册的广播

注册广播小结

  • 传递的参数是BroadcastReceiverIntentFilter
  • 创建LoadedApk.ReceiverDispatcher.InnerReceiver,该对象是一个Binder
  • 通过AMSInnerReceiver对象的代理类,注册到system_server进程
  • 如果广播没有被注册过,则创建广播接受者队列ReceiverList,并添加到AMS.mRegisteredReceivers(已注册广播队列);
  • 创建BroadcastFilter,并添加到AMS.mReceiverResolverReceiverList

发送广播

发送广播是调用sendBroadcast(),其实真正干货的是ContextImpl类,广播分很多种,有序广播和无序广播,粘性广播,这里我们只分析无序挂广播

ContextImpl.java

public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess();
        // 调用AMP.broadcastIntent 
        ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId());
    } catch (RemoteException e) {
        ...
    }
}

还是很熟悉的代码,最终还是会调用到ActivityManagerService#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 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();
            //注释1
            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;
        }
    }

注释1处,调用了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) {
    ...
    if ((receivers != null && receivers.size() > 0)
        || resultTo != null) {
    //根据intent的flag来判断前台队列或者后台队列
    BroadcastQueue queue = broadcastQueueForIntent(intent);
    //注释1
    //创建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);
        //注释2
        //处理广播
        queue.scheduleBroadcastsLocked();
    }
}

    return ActivityManager.BROADCAST_SUCCESS;
}

这个方法很长,前面省略了很多,前面的工作主要是,把静态注册和动态注册的广播,按照优先级不同存储在不同的列表中,然后把俩个列表合并到recevers列表中,这样recevers列表就包含了所有的广播接收者,然后再注释1处创建BroadcastRecord对象并把recevers传入,然后再注释2处调用BroadcastQueuescheduleBroadcastsLocked方法处理广播

处理广播

不管哪种广播最终都会调用scheduleBroadcastsLocked方法来处理广播

BroadcastQueue.java

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

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

此处的HandlerBroadcastHandler,消息在BroadcastHandler中处理

BroadcastHandler.java

private final class BroadcastHandler extends Handler {

    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BROADCAST_INTENT_MSG: {
                processNextBroadcast(true); 
            } break;
            ...
    }
}

调用了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 
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
            }
            addBroadcastToHistoryLocked(r);//将广播添加历史统计
        }
        ...
    }    

通过deliverToRegisteredReceiverLocked方法,把广播分发给对应的广播接收者

private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) {
    ...
    //检查发送者是否有BroadcastFilter所需权限
    //以及接收者是否有发送者所需的权限等等
    //当权限不满足要求,则skip=true。
    ...
        // 处理广播
        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;
        }
        ...
    }
}

这个方法主要是检查权限,如果权限通过就调用performReceiveLocked处理广播

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类对应的方法 
            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);
    }
}

这个方法表示,如果广播接受者的进程还存在,则通过Binder发送广播,这里的app.thread指的是ApplicationThread,我们看一下scheduleRegisteredReceiver这个方法

ActivityThread.java

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

他调用了IIntentReceiverperformReceive方法,前面说过IIntentReceiver用于广播的跨进程通信,具体实现在LoadedApk.ReceiverDispatcher.InnerReceive

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) {
        rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);
    } else {
       ...
    }
}
   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);
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            if (intent == null || !mActivityThread.post(args.getRunnable())) {//注释2
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

注释1处把广播的intent对象封装为Args,注释2处利用mActivityThread的post传入了Arg对象,mActivityThread是一个Handler指向内部类H,注释2处的args.getRunnable(),就是要处理的逻辑,我们看下这个getRunnable

  public final Runnable getRunnable() {
                return () -> {
                   ...
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        //注释1
                        receiver.onReceive(mContext, intent);

再注释1处,调用了onReceive方法,这样注册的广播接受者,就收到了消息

参考:gityuan.com/2016/06/04/…

Android 进阶解密