美文网首页
组件之BroadcastReceiver源码解析

组件之BroadcastReceiver源码解析

作者: kjy_112233 | 来源:发表于2018-09-27 19:45 被阅读0次

    一、BroadcastReceiver源码解析

    (1)BroadcastReceiver注册过程

    • 注册过程是从ContextWraper的registerReceiver方法开始的
        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            //ContextWrapper是mBase的代理,mBase成员变量其实是ContextImpl。
            return mBase.registerReceiver(receiver, filter);
        }
    
        //ContextImpl.java
        @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);
        }
    
        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();
                    }
                    //注释一
                    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 {
                //注释三
                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();
            }
        }
    
    • 注释一:将广播接收者及其他参数封装成一个IIntentReceiver对象
    • 注释二:最终返回的是IIntentReceiver.Stub类型的对象InnerReceiver,该类实现了IIntentReceiver接口并继承Binder。
    • 注释三:基于Binder机制,通过调用代理对象IActivityManager的方法,使得系统服务ActivityManagerService对应的方法被调用。因此,注册的操作就交给了系统服务ActivityManagerService来处理了。
    • 查看LoadedApk.ReceiverDispatcher源码
            ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                    Handler activityThread, Instrumentation instrumentation,
                    boolean registered) {
                if (activityThread == null) {
                    throw new NullPointerException("Handler must not be null");
                }
                //初始化IIntentReceiver类,InnerReceiver是IIntentReceiver实现类
                mIIntentReceiver = new InnerReceiver(this, !registered);
                mReceiver = receiver;
                mContext = context;
                mActivityThread = activityThread;
                mInstrumentation = instrumentation;
                mRegistered = registered;
                mLocation = new IntentReceiverLeaked(null);
                mLocation.fillInStackTrace();
            }
    
    • 查看ActivityManagerService.registerReceiver源码
        public Intent registerReceiver(IApplicationThread caller, String callerPackage,
                IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
                int flags) {
            //code..
            synchronized (this) {
                //code...
                //注释一
                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();
                        //code...
                        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) {
                    //code...(IllegalArgumentException异常)
                } else if (rl.pid != callingPid) {
                    throw new IllegalArgumentException(
                    //code...(IllegalArgumentException异常)
                } else if (rl.userId != userId) {   
                    //code...(IllegalArgumentException异常)
                }
                //注释三
                BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                        permission, callingUid, userId, instantApp, visibleToInstantApps);
                if (rl.containsFilter(filter)) {
                    //code...
                } else {
                    rl.add(bf);
                    //注释四
                    mReceiverResolver.addFilter(bf);
                }
                //code...
                return sticky;
            }
        }
    
    • 注释一:每次发来的一个注册请求都会对应ReceiverList中的一条数据。
    • 注释二:将客户端传递过来的广播接收器InnerReceiver保存起来。
    • 注释三:创建一个BroadcastFilter对象,BroadcastFilter继承自IntentFilter。
    • 注释四:将客户端传递过来的IntentFilter也保存起来,这样整个广播注册过程就完成了。

    总结

    • 客户端:客户端广播注册的时候,loadedApk对应着多个context对象(一个进程对应多个activity和service以及一个application),每个context里面有一张hashmap存放注册的广播接收者(每个activity里面可以注册多个广播,都存放在hashmap里),每张hashmap里面包含许多ReceiverDispatcher(内含binder);
    • AMS:每个客户端的ReceiverDispatcher都对应一个ReceiverList,该ReceiverList中保存着可以启动该广播接收者的IntentFilter列表。而每一个ReceiverList都对应着接收者注册时候的一个Binder对象。

    (2)广播的发送与接收

    • 广播发送是从ContextWraper的sendBroadcast方法开始的
        @Override
        public void sendBroadcast(Intent intent) {
            mBase.sendBroadcast(intent);
        }
    
        //ContextImpl.java
        @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());
            } 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) {
                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;
            }
        }
    
    • 注释一:获取广播发送者的身份
    • 注释二:调用broadcastIntentLocked发送广播
    • broadcastIntentLocked方法主要用来查找目标广播接收者
        @GuardedBy("this")
        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);
            //code...
            //粘性广播
            if (sticky) {
               //code...
            }
            //code...
            int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
            if (!ordered && NR > 0) {
                if (isCallerSystem) {
                    checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                            isProtectedBroadcast, registeredReceivers);
                }
                //通过传递过来的Intent查找相匹配的的BroadcastReceiver并把它放入到广播队列BroadcastQueue中。
                final BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                        callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                        requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                        resultCode, resultData, resultExtras, ordered, sticky, false, userId);
                final boolean replaced = replacePending
                        && (queue.replaceParallelBroadcastLocked(r) != null);
                if (!replaced) {
                    queue.enqueueParallelBroadcastLocked(r);
                    //执行广播发送任务
                    queue.scheduleBroadcastsLocked();
                }
                registeredReceivers = null;
                NR = 0;
            }
            //code...
            return ActivityManager.BROADCAST_SUCCESS;
        }
    
    • 查看BroadcastQueue.scheduleBroadcastsLocked源码
        public void scheduleBroadcastsLocked() {
            if (mBroadcastsScheduled) {
                return;
            }
            //向消息管理器mHandler发送了一个BROADCAST_INTENT_MSG类型的消息
            mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
            mBroadcastsScheduled = true;
        }
    
    • handleMessage中调用processNextBroadcast(true)方法,processNextBroadcast()方法又调用processNextBroadcastLocked(fromMsg, false)方法。
        final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
            BroadcastRecord r;
            mService.updateCpuStats();
            //fromMsg表示是否为BROADCAST_INTENT_MSG类型的消息
            if (fromMsg) {
                mBroadcastsScheduled = false;
            }
            //处理mParallelBroadcasts中的广播转发任务
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();
                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                        System.identityHashCode(r));
                    Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                        System.identityHashCode(r));
                }
                final int N = r.receivers.size();
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    //注释一
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);
            }
            //code...
        }
    
    • 注释一:deliverToRegisteredReceiverLocked方法系统在检查广播发送者和接收者的权限之后,调用performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId);方法将BroadcastRecord对象r描述的广播交给BroadcastFilter处理。
        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) {
                if (app.thread != null) {
                    try {
                        //注释一
                        app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                                data, extras, ordered, sticky, sendingUser, app.repProcState);
                    } catch (RemoteException ex) {
                        synchronized (mService) {
                            app.scheduleCrash("can't deliver broadcast");
                        }
                        throw ex;
                    }
                } else {
                    throw new RemoteException("app.thread must not be null");
                }
            } else {
                receiver.performReceive(intent, resultCode, data, extras, ordered,
                        sticky, sendingUser);
            }
        }
    
    • 注释一:app.thread对象是ActivityThread的内部类对象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);
                //receiver指向一个InnerReceiver对象,每个InnerReceiver对象封装了一个广播接收者
                receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                        sticky, sendingUser);
            }
    
    • 查看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) {
                        rd = null;
                    } else {
                        rd = mDispatcher.get();
                    }
                    if (ActivityThread.DEBUG_BROADCAST) {
                        int seq = intent.getIntExtra("seq", -1);
                    }
                    if (rd != null) {
                        //rd是ReceiverDispatcher的对象,调用rd的performReceive
                        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();
                        }
                    }
                }
    
    • 查看ReceiverDispatcher中的performReceive方法
            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);
                //code...
                //注释一
                if (intent == null || !mActivityThread.post(args.getRunnable())) {
                    if (mRegistered && ordered) {
                        IActivityManager mgr = ActivityManager.getService();
                        args.sendFinished(mgr);
                    }
                }
            }
    
    • mActivityThread是一个Handler对象,该对象指向ActivityThread中的mH;因此此刻切换到广播接收者所在进程的主线程来执行args,args是一个Runnable对象。
                public final Runnable getRunnable() {
                    return () -> {
                        //code...
                        try {
                            ClassLoader cl = mReceiver.getClass().getClassLoader();
                            intent.setExtrasClassLoader(cl);
                            intent.prepareToEnterProcess();
                            setExtrasClassLoader(cl);
                            receiver.setPendingResult(this);
                            //广播接收器BroadcastReceiver的onReceive方法被回调
                            receiver.onReceive(mContext, intent);
                        } catch (Exception e) {
                           //code...
                        }
                        //code...
                    };
                }
            }
    

    总结

    发送广播会查找相应的BroadcastFilter,匹配就会调用相应的远程Binder代理对象通知客户端,最终由客户端的主线程来执行接受者的onReceiver()方法。

    相关文章

      网友评论

          本文标题:组件之BroadcastReceiver源码解析

          本文链接:https://www.haomeiwen.com/subject/vzmeoftx.html