android 9.0 广播的注册,发送,接收过程分析

广播的注册分为静态注册和动态注册,静态注册是通过PackageManagerService(PMS)来完成整个的注册过程的,当然,除了广播外,其它三个组件也是在应用安装时通过PMS来完成解析和注册的。下面已动态注册为例分析广播的注册过程。在Activity中动态注册广播的代码如下:

IntentFilter intentFilter = new IntentFilter("com.android.skill");
myBroadcastReceiverFive = new MyBroadcastReceiverFive();
registerReceiver(myBroadcastReceiverFive,intentFilter);

private class MyBroadcastReceiverFive extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        LogUtil.e("动态注册  MyBroadcastReceiverFive");
    }
}

在Activity中动态注册广播时,调用registerReceiver方法,会调用到ContextWrapper的registerReceiver方法

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java

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

这个方法内部,mBase其实就是一个ContextImpl类型的对象,所以会执行ContextImpl类的registerReceiver方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/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) {
	    //传入的 broadcastPermission 为null,scheduler 也是null,flags的值是0
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
	        // 满足条件,创建handler对象赋值给scheduler
            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();
    }
}

registerReceiver方法进过调用其重载方法,最后调用了registerReceiverInternal方法,这个方法中,会通过mPackageInfo.getReceiverDispatcher()方法创建一个IIntentReceiver类型的对象,这个对象其实就是一个LoadedApk.ReceiverDispatcher.InnerReceiver类型的对象,由于InnerReceiver是继承IIntentReceiver.Stub,所以这个InnerReceiver类型的对象其实就是一个Binder,它后面作为app进程和system_server进程进行通信的桥梁。mPackageInfo是LoadedApk类型的对象,下面看看LoadedApk类的getReceiverDispatcher方法的具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java

public final class LoadedApk {

    public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
            Context context, Handler handler,
            Instrumentation instrumentation, boolean registered) {
        synchronized (mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            // ...
            if (rd == null) {
	    // 关键代码
                rd = new ReceiverDispatcher(r, context, handler,
                // ...
            } else {
                rd.validate(context, handler);
            }
            // ...
	    // 关键代码
            return rd.getIIntentReceiver();
        }
    }

    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;
    	// ...
    	//构造方法
    	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);
    		 // ...
    	}
    	// ...
    	IIntentReceiver getIIntentReceiver() {
    		return mIIntentReceiver;
    	}
    	// ...
    }
}

通过LoadedApk的getReceiverDispatcher方法,可以看出,它里面调用了LoadedApk.ReceiverDispatcher的构造方法,从上面贴出的代码可以看到,这个构造方法里面创建了一个InnerReceiver的对象,并将这个对象赋值给mIIntentReceiver这个变量,后面通过getIIntentReceiver方法获取的就是这个InnerReceiver类型的对象。下面接着看ContextImpl类的registerReceiverInternal方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
	    //传入的 broadcastPermission 为null,scheduler 也是null,flags的值是0
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
	        // 满足条件,创建handler对象赋值给scheduler
            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 {
	  // 关键代码 2
        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();
    }
}

在完成了mPackageInfo.getReceiverDispatcher()创建InnerReceiver对象后,关键代码2 处,继续调用了AMS的registerReceiver方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
        // ...
 
        synchronized (this) {
            // ...
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                // ...
		//关键代码 1
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            } 
	    // ...
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
		// ...
            } else {
                rl.add(bf);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
		//关键代码 2
                mReceiverResolver.addFilter(bf);
            }

            // ...

            return sticky;
        }
}

这个方法内部,进行将recevier和filter进行了保存,这样注册过程就完成了。


接下来看看广播的发送过程(本例按照,广播是动态注册的,并且发送的是普通的广播,未指定广播接收者,未指定权限,来分析广播的发送和接收过程):
在Activity中发送广播,sendBroadCast方法其实是调用了ContextWrapper的sendBroadcast方法,ContextWrapper类中的sendBroadcast方法,其实也是调用了ContextImpl的sendBroadcast方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/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();
    }
}

这个方法中,通过进程间通信的的方式,调用了system_server进程的ActivityServiceManager的broadcastIntent方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/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) {

    //传入的 serialized 为false 表示发送的是无序广播, sticky 表示发送的是粘性广播
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        intent = verifyBroadcastLocked(intent);

        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        // ...
	// 关键代码
        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;
    }
}


@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) {

     //传入的 serialized 为false 表示发送的是无序广播, sticky 表示发送的是粘性广播
    intent = new Intent(intent);
    // ...
    // By default broadcasts do not go to stopped apps.
     // Android系统对所有app的运行状态进行了跟踪
    // 当应用第一次安装但未使用过,或从程序管理器被强行关闭后,将处于停止状态
    // 在发送广播时,不管是什么广播类型,系统默认增加了FLAG_EXCLUDE_STOPPED_PACKAGES的flag
    // 使得对于所有BroadcastReceiver而言,如果其所在进程的处于停止状态,该BroadcastReceiver将无法接收到广播
    intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

    // ...
    //粘性广播由于在Android5.0 & API 21中已经失效,这里就不分析了
    if (sticky) {
       // ...
    }
    //广播没有指定特定接收者时
    if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                //这里的要求比较特殊,针对所有user,且从shell发送的广播
                //即处理调试用的广播
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    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);
            }
        }
    // ...
    //由于分析的例子是不指定接收者,不需要权限的广播,所以,上面registeredReceivers赋值了,
    //下面的NR这个变量的值是大于0的
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    //由于发送的是普通广播,这里的order传入的值是false,所以,这个if判断条件成立
    if (!ordered && NR > 0) {
        //非系统广播
        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, registeredReceivers);
        }
        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) {
	    //没有替换时,才需要将新的广播加入到BroadcastQueue.mParallelBroadcasts队列中
	    //这里非常重要,也就是说动态广播都放在了BroadcastQueue.mParallelBroadcasts中
            queue.enqueueParallelBroadcastLocked(r);
 
            //1  触发广播发送流程  
            queue.scheduleBroadcastsLocked();

        }
        registeredReceivers = null;
        NR = 0;
    }

    //如果是发送的普通广播,则上面的NR 重新赋值为 0,由于分析的示例前提是,没有静态注册广播,所以这里
    //的receivers为null(这个receiver为null的分析过程,需要结合PackageManagerService类的queryIntentReceiversInternal方法,
    //  读者可以自己去分析,限于篇幅的原因,这里就不做详细的分析)
    //所以下面这个判断就不成立,(如果是静态注册的广播,则会走下面的广播发送流程,本例是动态注册的广播,所以不走这个流程)
    if ((receivers != null && receivers.size() > 0)
            || resultTo != null) {
        BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                resultData, resultExtras, ordered, sticky, false, userId);

        final BroadcastRecord oldRecord =
                replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
        if (oldRecord != null) {
            if (oldRecord.resultTo != null) {
                final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                try {
                    oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                            oldRecord.intent,
                            Activity.RESULT_CANCELED, null, null,
                            false, false, oldRecord.userId);
                } 
		// ...
            }
        } else {
	    //关键代码
	    //这里非常重要,如果发送的是有序广播,则所有的广播接收者都放在了BroadcastQueue.mOrderedBroadcasts中
	    //这个和上面如果发送的是普通广播时,将动态注册的广播存储在BroadcastQueue.mParallelBroadcasts中是不同的。
            queue.enqueueOrderedBroadcastLocked(r);
	    // 2 触发广播发送流程
            queue.scheduleBroadcastsLocked();
        }
    }
    // ...

    return ActivityManager.BROADCAST_SUCCESS;
}

这个方法内部,主要做了如下事情:

1.先获取动态注册的广播和静态注册的广播,并将这些广播分别存储到两个不同的列表中

2.判断是否是发送的普通广播,如果是,并且动态注册的广播,则先将动态注册的广播发送, 走后续的广播发送流程,接着判断是否有静态广播,如果有静态广播,则发送静态广播。(从源码代码逻辑可以知道,普通广播的发送,是动态广播优先静态广播发送)如果发送的是有序广播,则会将第一步的两个列表合并到receivers列表中,并按照优先级对广播进行排序,具体的排序规则是,优先级高的排前面,对于相同优先级的,动态优先静态,对于优先级相同,广播类型相同,如果都是动态广播类型,则先注册的优先后注册的,对于都是静态广播类型,则先扫描的由于后扫描的。

3.将广播将第二步的广播列表,添加到BroadcastQueue的mParallelBroadcasts或者mOrderedBroadcasts中,如果广播按照普通方式发送,则将广播存储在mParallelBroadcasts列表中,如果是静态广播存储在mOrderedBroadcasts列表中,如果发送方式是有序广播,则将所有的广播(不管是静态注册的还是动态注册的)都存储在mOrderedBroadcasts列表中。

4.调用BroadcastQueue的scheduleBroadcastsLocked方法发送广播。

由于前提是发送动态广播,并未注册静态广播,所以执行到关键代码1处,通过调用BroadcastQueue的enqueueOrderedBroadcastLocked方法将发送的广播存储在BroadcastQueue的mParallelBroadcasts列表中,然后通过
scheduleBroadcastsLocked方法发送广播。下面看看scheduleBroadcastsLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

public void scheduleBroadcastsLocked() {

    if (mBroadcastsScheduled) {
        return;
    }
    // 关键代码
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

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: {
                    //关键代码
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
}


final void processNextBroadcast(boolean fromMsg) {
    synchronized (mService) {
        processNextBroadcastLocked(fromMsg, false);
    }
}


final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
	//传入的参数 fromMsg 为true ,skipOomAdj 为 false
        BroadcastRecord r;
        // ...
        if (fromMsg) {
            mBroadcastsScheduled = false;
        }
	//处理无序广播
        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);
		//发送无序广播
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }
            // ...
        }

      // 对于有序或静态广播而言,需要依次向每个BroadcastReceiver发送广播,前一个处理完毕后才能发送下一个广播
      // 如果BroadcastReceiver对应的进程还未启动,则需要等待
      // mPendingBroadcast就是用于保存,因为对应进程还未启动,而处于等待状态的BroadcastRecord
      if (mPendingBroadcast != null) {    
	// ... 这里省略的代码是处理要触发的广播的进程还未启动的广播
      }
      boolean looped = false;
      //如果发送的是有序广播,则将执行下面的逻辑
      do {
	//这块省略的逻辑是:处理有序广播
      }while(r == null;
     
      // ...

      //中间进行很多的权限检查

        // Is this receiver's application already running?
        if (app != null && app.thread != null && !app.killed) {
            try {
                app.addPackage(info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                processCurBroadcastLocked(r, app, skipOomAdj);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when sending broadcast to "
                      + r.curComponent, e);
            } catch (RuntimeException e) {

                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r, r.resultCode, r.resultData,
                        r.resultExtras, r.resultAbort, false);
                scheduleBroadcastsLocked();
                r.state = BroadcastRecord.IDLE;
                return;
            }

        }

	//如果要启动的广播的进程为创建,则要创建一个新的进程,mService.startProcessLocked()方法
	//就是AMS中的startProcessLocked(),这个方法是用于新建一个进程

        if ((r.curApp=mService.startProcessLocked(targetProcess,
                info.activityInfo.applicationInfo, true,
                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                "broadcast", r.curComponent,
                (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                        == null) {
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, false);
            //在次重复发送过程,为什么要这么处理呢,这是因为,新建的进程中也可能存在
	    // 其它注册的广播,所以要在次执行这个广播的发送流程
            scheduleBroadcastsLocked();
            r.state = BroadcastRecord.IDLE;
            return;
        }
        // ...
}

无序广播,并调用deliverToRegisteredReceiverLocked方法发送无序广播。如果是发送的有序广播,则判断广播所属的进程是否存在,并且进程未被kill,则执行processCurBroadcastLocked处理后续的流程,如果广播所属的进程不存在,则新建一个进程,并重复广播的发送过程,这些情况的后续流程,读者可以自己去分析。本例中,只是发送普通股广播,并且广播就所属当前进程,所以直接执行deliverToRegisteredReceiverLocked方法,下面看看这个方法的具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/a

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
	// ...
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
	    //关键代码
                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;
            }
        } catch (RemoteException e) {
            if (ordered) {
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
                if (filter.receiverList.app != null) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
        }
}


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

deliverToRegisteredReceiverLocked方法中,又会调用到performReceiveLocked方法,performReceiveLocked方法中,会调用app.thread.scheduleRegisteredReceiver方法,app.thread其实是ApplicationThread类型的对象,这个在之前就分析过,代码的执行又回到了ApplicationThread类中


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/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);
}

这个方法中的receiver其实就是之前分析的LoadedApk.ReceiverDispatcher.InnerReceiver类型的对象,下面看看LoadedApk.ReceiverDispatcher.InnerReceiver的performReceive方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java

final static class InnerReceiver extends IIntentReceiver.Stub {
            // ...

            @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 (rd != null) {
		//关键代码
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } 
		// ...
            }
}

这个方法内部又调用了LoadedApk.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);
    // 关键代码
    if (intent == null || !mActivityThread.post(args.getRunnable())) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManager.getService();
            args.sendFinished(mgr);
        }
    }
}

LoadedApk.ReceiverDispatcher的performReceive方法内部,调用了mActivityThread这个handler发送一个Runnable,下面看看这个Runnable的run方法

public final Runnable getRunnable() {
                return () -> {
                    final BroadcastReceiver receiver = mReceiver;
		    // ...
                    final IActivityManager mgr = ActivityManager.getService();
                    //...
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
			//关键代码
                        receiver.onReceive(mContext, intent);
                    } 
		    // ...
                };
}

可以看到,这里调用了receiver的onReceive方法,至此,广播的onReceive方法就执行了。

总结:
1.动态广播的注册过程其实就是通过binder将BroadcastReceiver(广播接收者)保存AMS中。
2.当发送广播时,也是通过binder,在system_server进程中,将发送的广播保存到BroadcastQueue的广播列表中。
3.通过AMS在BroadcastQueue的广播列表中查找与之匹配的BroadcastReceiver,在将广播发送给BroadcastReceiver
所在的进程的消息队列中。
4.BroadcastReceiver所在的进程处理消息,并回调BroadcastReceiver中的onReceive方法。
5.处理完广播后,BroadcastReceiver进程按需将执行结果通知给AMS,以便触发下一次广播发送。

广播按照发送方式可以分为:
1.有序广播:一旦发送了无序广播,所有监听此广播的接收者都能接收到。
2.普通广播:广播接收者按照优先级顺序,可以中断广播,也可以对广播进行修改,如果优先级相同,则动态注册的广播优先于静态注册的广播。
3.粘性广播:当广播发出后,如果系统没有接受者,会一直等待,直到有接收者接收为止。由于在Android5.0 & API 21中已经失效

按照应用内外:
1.分为本地广播:只在app内发送和接收广播。
2.非本地广播

建议动态注册个广播,最好在Activity的onPause方法中进行unRegister,因为Activity在执行完onPause方法后,在系统内存不足的情况下,就可能被销毁,如果放到onStop后者onDestroy方法中,此时这两个方法都可能未执行,这样会导致内存泄漏。

广播的注册方式,不管是静态注册,还是动态注册,他们是按照有序执行还是无序执行,不是根据它的注册方式决定的,而是根据发送广播的方式决定,如果是发送普通广播,则每个广播接收者都能够接收到广播,广播不能够被其它广播中断。如果是发送的有序广播,则广播接收者按照优先级来接收广播,具体的接收顺序是,优先级高的先接收,如果优先级相同,动态注册的广播优先静态注册的广播,对于动态广播,如果优先级相同,先注册的优先于后注册的,对于优先级相同的静态广播,先扫描的优先于后扫描的。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值