广播相关学习-registerReceiver

广播主要分为两部分:广播发送者和广播接收者

广播接收者:分为静态注册和动态注册

静态注册:AndroidManifest中声明,PMS初始化时,通过解析AndroidManifest.xml,就能得到所有静态注册的BroadcastReceiver信息

当广播发送者需要向静态注册的BroadcastReceiver接收者发送信息时,如果接收者所在进程未启动,先启动进程,利用反射创建BroadcastReceiver对象,然后才能处理

动态注册:调用Context的registerReceiver函数注册BroadcastReceiver; 当应用程序不再需要监听广播时,则需要调用unregisterReceiver函数进行反注册

本文主要介绍动态注册的流程

Context#registerReceiver

2517    /**
2518     * Register a BroadcastReceiver to be run in the main activity thread.  The
2519     * <var>receiver</var> will be called with any broadcast Intent that
2520     * matches <var>filter</var>, in the main application thread. 
(receiver处理广播的地方;filter用于过滤,可以接收哪些广播;默认app主线程处理,注意ANR)
2521     *
2522     * <p>The system may broadcast Intents that are "sticky" -- these stay
2523     * around after the broadcast has finished, to be sent to any later
2524     * registrations. If your IntentFilter matches one of these sticky
2525     * Intents, that Intent will be returned by this function
2526     * <strong>and</strong> sent to your <var>receiver</var> as if it had just
2527     * been broadcast.
2528     *
2529     * <p>There may be multiple sticky Intents that match <var>filter</var>,
2530     * in which case each of these will be sent to <var>receiver</var>.  In
2531     * this case, only one of these can be returned directly by the function;
2532     * which of these that is returned is arbitrarily decided by the system.
2533     *
2534     * <p>If you know the Intent your are registering for is sticky, you can
2535     * supply null for your <var>receiver</var>.  In this case, no receiver is
2536     * registered -- the function simply returns the sticky Intent that
2537     * matches <var>filter</var>.  In the case of multiple matches, the same
2538     * rules as described above apply.
2539     *
2540     * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
2541     *
2542     * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
2543     * registered with this method will correctly respect the
2544     * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
2545     * Prior to that, it would be ignored and delivered to all matching registered
2546     * receivers.  Be careful if using this for security.</p>
2547     *
2548     * <p class="note">Note: this method <em>cannot be called from a
2549     * {@link BroadcastReceiver} component;</em> that is, from a BroadcastReceiver
2550     * that is declared in an application's manifest.  It is okay, however, to call
2551     * this method from another BroadcastReceiver that has itself been registered
2552     * at run time with {@link #registerReceiver}, since the lifetime of such a
2553     * registered BroadcastReceiver is tied to the object that registered it.</p>
2554     *
2555     * @param receiver The BroadcastReceiver to handle the broadcast.
2556     * @param filter Selects the Intent broadcasts to be received.
2557     *
2558     * @return The first sticky intent found that matches <var>filter</var>,
2559     *         or null if there are none.
2560     *
2561     * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
2562     * @see #sendBroadcast
2563     * @see #unregisterReceiver
2564     */
2565    @Nullable
2566    public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
2567                                            IntentFilter filter);

注册一个广播接受者,至少有两个条件;BroadcastReceiver实例(类比ServiceConnection),filter(可接收广播的过滤条件)

ContextImpl#registerReceiver

1445    @Override
1446    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1447        return registerReceiver(receiver, filter, null, null);
1448    }
1456    @Override
1457    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
1458            String broadcastPermission, Handler scheduler) {
              //broadcastPermission广播权限,当receiver注册了相应的广播权限后,只有发送方区有同样的权限才能传到相应的receiver中
            //scheduler默认是主线程Handler处理onReceive操作,如果指定了相应线程的Handler,onReceive函数由scheduler对应线程处理
1459        return registerReceiverInternal(receiver, getUserId(),
1460                filter, broadcastPermission, scheduler, getOuterContext(), 0);
1461    }

ContextImpl#registerReceiverInternal

1477    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
1478            IntentFilter filter, String broadcastPermission,
1479            Handler scheduler, Context context, int flags) {
1480        IIntentReceiver rd = null;
1481        if (receiver != null) {
1482            if (mPackageInfo != null && context != null) {
                       //mPackageInfo的类型为LoadedApk
1483                if (scheduler == null) {
                           //未设置scheduler时,将使用主线程的handler处理
                             //这就是默认情况下,Receiver的onReceive函数在主线程被调用的原因
1484                    scheduler = mMainThread.getHandler();
1485                }
            //getReceiverDispatcher函数的内部,利用BroadcastReceiver构造出ReceiverDispatcher
            //返回ReceiverDispatcher中的IIntentReceiver对象
            //IIntentReceiver是注册到AMS中,供AMS回调的Binder通信接口
1486                rd = mPackageInfo.getReceiverDispatcher(
1487                    receiver, context, scheduler,
1488                    mMainThread.getInstrumentation(), true);
1489            } else {
1490                if (scheduler == null) {
1491                    scheduler = mMainThread.getHandler();
1492                }
1493                rd = new LoadedApk.ReceiverDispatcher(
1494                        receiver, context, scheduler, null, true).getIIntentReceiver();
1495            }
1496        }
1497        try {
1498            final Intent intent = ActivityManager.getService().registerReceiver(
1499                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
1500                    broadcastPermission, userId, flags); //通过AMS来注册广播接收者
1501            if (intent != null) {
1502                intent.setExtrasClassLoader(getClassLoader());
1503                intent.prepareToEnterProcess();
1504            }
1505            return intent;
1506        } catch (RemoteException e) {
1507            throw e.rethrowFromSystemServer();
1508        }
1509    }

LoadedApk#getReceiverDispatcher

类似于LoadedApk#getServiceDispatcher,ServiceDispatcher

124    private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
125        = new ArrayMap<>();
1201    public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
1202            Context context, Handler handler,
1203            Instrumentation instrumentation, boolean registered) {
                //在receiver的注册端,保存<BroadcastReceiver实例对象,对应LoadedApk.ReceiverDispatcher>的一张表
1204        synchronized (mReceivers) {
1205            LoadedApk.ReceiverDispatcher rd = null;
1206            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
1207            if (registered) {
1208                map = mReceivers.get(context); 
1209                if (map != null) {
1210                    rd = map.get(r); //找到缓存中的ReceiverDispatcher对象了
1211                }
1212            }
1213            if (rd == null) {
1214                rd = new ReceiverDispatcher(r, context, handler,
1215                        instrumentation, registered); //创建一个
1216                if (registered) {
1217                    if (map == null) {
1218                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
1219                        mReceivers.put(context, map); //并保存在缓存中
1220                    }
1221                    map.put(r, rd);
1222                }
1223            } else {
1224                rd.validate(context, handler); //检查context和handler是否一致
1225            }
1226            rd.mForgotten = false;
1227            return rd.getIIntentReceiver(); //返回InnerReceiver,是一个binder对象,通过它AMS可以远程调用BroadcastReceiver中的onReceive方法
1228        }
1229    }

LoadedApk#ReceiverDispatcher相关结构

29oneway interface IIntentReceiver { 
       //oneway interface AMS远程调用performReceive时不会阻塞,只是发送事务数据并立即返回
30    void performReceive(in Intent intent, int resultCode, String data,
31            in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
32}
1281    static final class ReceiverDispatcher {
1282
1283        final static class InnerReceiver extends IIntentReceiver.Stub {
1284            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; //指向ReceiverDispatcher 外部类的一个弱引用
1285            final LoadedApk.ReceiverDispatcher mStrongRef;
1286                  //InnerReceiver实现了IIntentReceiver的binder对象
1287            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1288                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1289                mStrongRef = strong ? rd : null;
1290            }
1291
1292            @Override
1293            public void performReceive(Intent intent, int resultCode, String data,
1294                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1295                final LoadedApk.ReceiverDispatcher rd;
1296                if (intent == null) {
1297                    Log.wtf(TAG, "Null intent received");
1298                    rd = null;
1299                } else {
1300                    rd = mDispatcher.get();
1301                }
1302                if (ActivityThread.DEBUG_BROADCAST) {
1303                    int seq = intent.getIntExtra("seq", -1);
1304                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1305                            + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
1306                }
1307                if (rd != null) { //指向外部对象的弱引用,先判断是否为null
1308                    rd.performReceive(intent, resultCode, data, extras,
1309                            ordered, sticky, sendingUser); //调用其外部类的performReceive方法,和bindService客户端的ServiceConnection一样
1310                } else {
                             //注册的broadcast实例提前被销毁的情况     
1311                    //   The activity manager dispatched a broadcast to a registered
1312                    // receiver in this process, but before it could be delivered the
1313                    // receiver was unregistered.  Acknowledge the broadcast on its
1314                    // behalf so that the system's broadcast sequence can continue.
1315                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1316                            "Finishing broadcast to unregistered receiver");
1317                    IActivityManager mgr = ActivityManager.getService();
1318                    try {
1319                        if (extras != null) {
1320                            extras.setAllowFds(false);
1321                        }
1322                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); //通篇了解后再回来看这个函数
1323                    } catch (RemoteException e) {
1324                        throw e.rethrowFromSystemServer();
1325                    }
1326                }
1327            }
1328        }
1329
1330        final IIntentReceiver.Stub mIIntentReceiver; //receiver  binder 对象
1331        final BroadcastReceiver mReceiver; //实例
1332        final Context mContext;
1333        final Handler mActivityThread;
1334        final Instrumentation mInstrumentation;
1335        final boolean mRegistered;
1336        final IntentReceiverLeaked mLocation;
1337        RuntimeException mUnregisterLocation;
1338        boolean mForgotten;
1339
1340        final class Args extends BroadcastReceiver.PendingResult {
1341            private Intent mCurIntent;
1342            private final boolean mOrdered;
1343            private boolean mDispatched;
1344            private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
1345
1346            public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
1347                    boolean ordered, boolean sticky, int sendingUser) {
1348                super(resultCode, resultData, resultExtras,
1349                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1350                        sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
1351                mCurIntent = intent;
1352                mOrdered = ordered;
1353            }
1354
1355            public final Runnable getRunnable() {
1356                return () -> {
1357                    final BroadcastReceiver receiver = mReceiver;
1358                    final boolean ordered = mOrdered;
1359
1360                    if (ActivityThread.DEBUG_BROADCAST) {
1361                        int seq = mCurIntent.getIntExtra("seq", -1);
1362                        Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1363                                + " seq=" + seq + " to " + mReceiver);
1364                        Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
1365                                + " mOrderedHint=" + ordered);
1366                    }
1367
1368                    final IActivityManager mgr = ActivityManager.getService();
1369                    final Intent intent = mCurIntent;
1370                    if (intent == null) {
1371                        Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
1372                                + ": run() previously called at "
1373                                + Log.getStackTraceString(mPreviousRunStacktrace));
1374                    }
1375
1376                    mCurIntent = null;
1377                    mDispatched = true;
1378                    mPreviousRunStacktrace = new Throwable("Previous stacktrace");
1379                    if (receiver == null || intent == null || mForgotten) {
1380                        if (mRegistered && ordered) {
1381                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1382                                    "Finishing null broadcast to " + mReceiver);
1383                            sendFinished(mgr);
1384                        }
1385                        return;
1386                    }
1387
1388                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
1389                    
1391                    try {
1392                        ClassLoader cl = mReceiver.getClass().getClassLoader();
1393                        intent.setExtrasClassLoader(cl);
1394                        intent.prepareToEnterProcess();
1395                        setExtrasClassLoader(cl);
1396                        receiver.setPendingResult(this);
1397                        receiver.onReceive(mContext, intent); //调用BroadcastReceiver的onReceive
1398                    } catch (Exception e) {
1399                        if (mRegistered && ordered) {
1400                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1401                                    "Finishing failed broadcast to " + mReceiver);
1402                            sendFinished(mgr);
1403                        }
1404                        if (mInstrumentation == null ||
1405                                !mInstrumentation.onException(mReceiver, e)) {
1406                            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1407                            throw new RuntimeException(
1408                                    "Error receiving broadcast " + intent
1409                                            + " in " + mReceiver, e);
1410                        }
1411                    }
1412
1413                    if (receiver.getPendingResult() != null) {
1414                        finish();
1415                    }
1416                   
1417                    
1418                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1419                };
1420            }
1421        }
1422
1423        ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1424                Handler activityThread, Instrumentation instrumentation,
1425                boolean registered) {
1426            if (activityThread == null) {
1427                throw new NullPointerException("Handler must not be null");
1428            }
1429
1430            mIIntentReceiver = new InnerReceiver(this, !registered);
1431            mReceiver = receiver;
1432            mContext = context;
1433            mActivityThread = activityThread; //执行onReceive任务的Handler
1434            mInstrumentation = instrumentation;
1435            mRegistered = registered;
1436            mLocation = new IntentReceiverLeaked(null);
1437            mLocation.fillInStackTrace();
1438        }
1439
1440        void validate(Context context, Handler activityThread) {
1441            if (mContext != context) {
1442                throw new IllegalStateException(
1443                    "Receiver " + mReceiver +
1444                    " registered with differing Context (was " +
1445                    mContext + " now " + context + ")");
1446            }
1447            if (mActivityThread != activityThread) {
1448                throw new IllegalStateException(
1449                    "Receiver " + mReceiver +
1450                    " registered with differing handler (was " +
1451                    mActivityThread + " now " + activityThread + ")");
1452            }
1453        }
1454
1455        IntentReceiverLeaked getLocation() {
1456            return mLocation;
1457        }
1458
1459        BroadcastReceiver getIntentReceiver() {
1460            return mReceiver;
1461        }
1462
1463        IIntentReceiver getIIntentReceiver() {
1464            return mIIntentReceiver;
1465        }
1466
1467        void setUnregisterLocation(RuntimeException ex) {
1468            mUnregisterLocation = ex;
1469        }
1470
1471        RuntimeException getUnregisterLocation() {
1472            return mUnregisterLocation;
1473        }
1474
1475        public void performReceive(Intent intent, int resultCode, String data,
1476                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1477            final Args args = new Args(intent, resultCode, data, extras, ordered,
1478                    sticky, sendingUser);
1479            if (intent == null) {
1480                Log.wtf(TAG, "Null intent received");
1481            } else {
1482                if (ActivityThread.DEBUG_BROADCAST) {
1483                    int seq = intent.getIntExtra("seq", -1);
1484                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1485                            + " seq=" + seq + " to " + mReceiver);
1486                }
1487            }
1488            if (intent == null || !mActivityThread.post(args.getRunnable())) { //Handler.post(Runnable) 相当于sendMessage,入队成功返回true
1489                if (mRegistered && ordered) {
1490                    IActivityManager mgr = ActivityManager.getService();
1491                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1492                            "Finishing sync broadcast to " + mReceiver);
1493                    args.sendFinished(mgr);
1494                }
1495            }
1496        }
1497
1498    }

注意这个实现,将业务接口与通信接口分离开来,BroadcastReceiver作为业务接口,InnerReceiver为通信接口,ReceiverDispatcher管理两者之间的联系

当AMS需要调用BroadcastReceiver实例时,其调用路径是:

InnerReceiver.performReceive
  ReceiverDispatcher.performReceive
   mActivityThread.post(args.getRunnable()) 
      receiver.onReceive(mContext, intent); 

mActivityThread = activityThread; 为执行onReceive任务的Handler,默认为主线程的handler,但可以是其他线程的Handler

非主线程调用onReceive中操作的方式

我们必须要明确,这和上文说的在其他线程的Handler中调用BroadcastReceiver的onReceive方法是两回事,比如静态注册的广播接收者,其onReceive必然执行在主线程;我们在主线程中调用onReceive时,如何将其中可能的耗时操作放到子线程中执行呢?

直接创建子线程会有问题;一旦BroadcastReceiver对象处理完广播,并将返回结果通知给AMS后,AMS就有可能清理掉对应进程。 因此,若在onReceive中创建线程处理问题,那么onReceive函数就可能在线程完成工作前返回,导致AMS提前销毁进程。 此时,线程也会消亡,使得工作并没有有效完成。

这样就用到BroadcastReceiver.PendingResult,见google的官方文档

State for a result that is pending for a broadcast receiver. Returned by goAsync() while in BroadcastReceiver.onReceive(). This allows you to return from onReceive() without having the broadcast terminate; you must call finish() once you are done with the broadcast. This allows you to process the broadcast off of the main thread of your app.
Note on threading: the state inside of this class is not itself thread-safe, however you can use it from any thread if you properly sure that you do not have races. Typically this means you will hand the entire object to another thread, which will be solely responsible for setting any results and finally calling finish().

示例如下:

private class MyBroadcastReceiver extends BroadcastReceiver {
    ..................
    public void onReceive(final Context context, final Intent intent) {
        //得到PendingResult
        final PendingResult result = goAsync();   //用来保证receiver端的主线程快速返回

        //放到异步线程中执行
        AsyncHandler.post(new Runnable() {  
            @Override  
            public void run() {  
                handleIntent(context, intent);//可进行一些耗时操作  
                result.finish();  
            }  
        });  
    } 
}

final class AsyncHandler {  
    private static final HandlerThread sHandlerThread = new HandlerThread("AsyncHandler");  
    private static final Handler sHandler;  

    static {  
        sHandlerThread.start();  
        sHandler = new Handler(sHandlerThread.getLooper());  
    }  

    public static void post(Runnable r) {  
        sHandler.post(r);  
    }  

    private AsyncHandler() {}  
}  

首先执行一个goAsync(),返回PendingResult对象,并将mPendingResult置为0

401     * @return Returns a {@link PendingResult} representing the result of
402     * the active broadcast.  The BroadcastRecord itself is no longer active;
403     * all data and other interaction must go through {@link PendingResult}
404     * APIs.  The {@link PendingResult#finish PendingResult.finish()} method
405     * must be called once processing of the broadcast is done.
406     */
407    public final PendingResult goAsync() {
408        PendingResult res = mPendingResult;
409        mPendingResult = null;
410        return res;
411    }

我们在Args中的getRunnable方法中可以看到如下逻辑

1413                    if (receiver.getPendingResult() != null) {
1414                        finish();
1415                    }
647    public final PendingResult getPendingResult() {
648        return mPendingResult;
649    }

普通情况下,在Args的getRunnable方法中调用receiver.onReceive()之前,会调用

1391                    try {
1392                        ClassLoader cl = mReceiver.getClass().getClassLoader();
1393                        intent.setExtrasClassLoader(cl);
1394                        intent.prepareToEnterProcess();
1395                        setExtrasClassLoader(cl);
1396                        receiver.setPendingResult(this);
1397                        receiver.onReceive(mContext, intent); //调用BroadcastReceiver的onReceive
1398                    } catch (Exception e) {
1399                        if (mRegistered && ordered) {
1400                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1401                                    "Finishing failed broadcast to " + mReceiver);
1402                            sendFinished(mgr);
1403                        }
1404                        if (mInstrumentation == null ||
1405                                !mInstrumentation.onException(mReceiver, e)) {
1406                            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1407                            throw new RuntimeException(
1408                                    "Error receiving broadcast " + intent
1409                                            + " in " + mReceiver, e);
1410                        }
1411                    }

会将Broadcast实例中的mPendingResult设为Args对象

640    public final void setPendingResult(PendingResult result) {
641        mPendingResult = result;
642    }

这样,在调用完onReceive之后,就会走到 finish();

BroadcastReceiver.PendingResult

202        /**
203         * Finish the broadcast.  The current result will be sent and the
204         * next broadcast will proceed.
205         */
206        public final void finish() {
207            if (mType == TYPE_COMPONENT) {
208                final IActivityManager mgr = ActivityManager.getService();
209                if (QueuedWork.hasPendingWork()) {
210                    // If this is a broadcast component, we need to make sure any
211                    // queued work is complete before telling AM we are done, so
212                    // we don't have our process killed before that.  We now know
213                    // there is pending work; put another piece of work at the end
214                    // of the list to finish the broadcast, so we don't block this
215                    // thread (which may be the main thread) to have it finished.
216                    //
217                    // Note that we don't need to use QueuedWork.addFinisher() with the
218                    // runnable, since we know the AM is waiting for us until the
219                    // executor gets to it.
238                    QueuedWork.queue(new Runnable() {
239                        @Override public void run() {
240                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
241                                    "Finishing broadcast after work to component " + mToken);
243                            sendFinished(mgr);
254                        }
255                    }, false);
256                } else {
257                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
258                            "Finishing broadcast to component " + mToken);
259                    sendFinished(mgr);
260                }
261            } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
262                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
263                        "Finishing broadcast to " + mToken);
264                final IActivityManager mgr = ActivityManager.getService();
265                sendFinished(mgr);
266            }
267        }
276        /** @hide */
277        public void sendFinished(IActivityManager am) {
278            synchronized (this) {
279                if (mFinished) {
280                    throw new IllegalStateException("Broadcast already finished");
281                }
282                mFinished = true;
283
284                try {
285                    if (mResultExtras != null) {
286                        mResultExtras.setAllowFds(false);
287                    }
288                    if (mOrderedHint) {
289                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
290                                mAbortBroadcast, mFlags);
291                    } else {
292                        // This broadcast was sent to a component; it is not ordered,
293                        // but we still need to tell the activity manager we are done.
294                        am.finishReceiver(mToken, 0, null, null, false, mFlags);
295                    }
296                } catch (RemoteException ex) {
297                }
298            }
299        }
300

调用AMS中的finishReceiver

ActivityManagerService#finishReceiver

22678    public void finishReceiver(IBinder who, int resultCode, String resultData,
22679            Bundle resultExtras, boolean resultAbort, int flags) {
22680        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + who);
22681
22682        // Refuse possible leaked file descriptors
22683        if (resultExtras != null && resultExtras.hasFileDescriptors()) {
22684            throw new IllegalArgumentException("File descriptors passed in Bundle");
22685        }
22686
22687        final long origId = Binder.clearCallingIdentity();
22688        try {
22689            boolean doNext = false;
22690            BroadcastRecord r;
22691
22692            synchronized(this) {
22693                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
22694                        ? mFgBroadcastQueue : mBgBroadcastQueue;
22703                r = queue.getMatchingOrderedReceiver(who);
22704                if (r != null) {
22705                    doNext = r.queue.finishReceiverLocked(r, resultCode,
22706                        resultData, resultExtras, resultAbort, true);
22707                }
22708                if (doNext) {
22709                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
22710                }
22711                // updateOomAdjLocked() will be done here
22712                trimApplicationsLocked();
22713            }
22714
22715        } finally {
22716            Binder.restoreCallingIdentity(origId);
22717        }
22718    }

用于处理完相应的Broadcast,执行下一个广播

而当我们用了goAsync时,因为BroadcastReceiver实例中的mPendingResult成员变量被置为null,因此不会自动调用finish了,就像上面的例子一样,等到执行完耗时操作后,手动调用finish;

可见,在onReceive函数中执行异步操作,主要目的是避免一些操作阻塞了主线程, 但整个操作仍然需要保证在10s内返回结果,尤其是处理有序广播和静态广播时。 毕竟AMS必须要收到返回结果后,才能向下一个BroadcastReceiver发送广播

得到可以用来binder call BroadcastReceiver实例的IIntentReceiver对象后,将其作为参数传递给AMS;

ActivityManagerService#registerReceiver

21342    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
21343            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
21344            int flags) {
21345        enforceNotIsolatedCaller("registerReceiver");
21346        ArrayList<Intent> stickyIntents = null;
21347        ProcessRecord callerApp = null;
21348        final boolean visibleToInstantApps
21349                = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
21350        int callingUid;
21351        int callingPid;
21352        boolean instantApp;
21353        synchronized(this) {
21354            if (caller != null) {
21355                callerApp = getRecordForAppLocked(caller); //callerApp代表客户端进程
21356                if (callerApp == null) {
21357                    throw new SecurityException(
21358                            "Unable to find app for caller " + caller
21359                            + " (pid=" + Binder.getCallingPid()
21360                            + ") when registering receiver " + receiver);
21361                }
21362                if (callerApp.info.uid != SYSTEM_UID &&
21363                        !callerApp.pkgList.containsKey(callerPackage) &&
21364                        !"android".equals(callerPackage)) {
21365                    throw new SecurityException("Given caller package " + callerPackage
21366                            + " is not running in process " + callerApp);
21367                }
21368                callingUid = callerApp.info.uid;
21369                callingPid = callerApp.pid;
21370            } else {
21371                callerPackage = null;
21372                callingUid = Binder.getCallingUid();
21373                callingPid = Binder.getCallingPid();
21374            }
21375
21376            instantApp = isInstantApp(callerApp, callerPackage, callingUid);
21377            userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
21378                    ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
21379
21380            Iterator<String> actions = filter.actionsIterator(); //从filter中获取action
21381            if (actions == null) {
21382                ArrayList<String> noAction = new ArrayList<String>(1);
21383                noAction.add(null);
21384                actions = noAction.iterator();
21385            }
21386
21387            // Collect stickies of users
21388            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) }; //UserHandle.getUserId(callingUid) 从uid换算出userId
21389            while (actions.hasNext()) {
21390                String action = actions.next();
21391                for (int id : userIds) {
21392                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id); //action对应的Intent list
21393                    if (stickies != null) {
                                 //从mStickyBroadcasts中查看用户的sticky Intent
21394                        ArrayList<Intent> intents = stickies.get(action);
21395                        if (intents != null) {
21396                            if (stickyIntents == null) {
21397                                stickyIntents = new ArrayList<Intent>();
21398                            }
21399                            stickyIntents.addAll(intents); //得到系统保存的所有sticky broadcast对应的Intent
21400                        }
21401                    }
21402                }
21403            }
21404        }
21405
21406        ArrayList<Intent> allSticky = null;
21407        if (stickyIntents != null) {
21408            final ContentResolver resolver = mContext.getContentResolver();
21409            // Look for any matching sticky broadcasts...
21410            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
21411                Intent intent = stickyIntents.get(i);
21412                // Don't provided intents that aren't available to instant apps.
21413                if (instantApp &&
21414                        (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
21415                    continue;
21416                }
21417                // If intent has scheme "content", it will need to acccess
21418                // provider that needs to lock mProviderMap in ActivityThread
21419                // and also it may need to wait application response, so we
21420                // cannot lock ActivityManagerService here.
21421                if (filter.match(resolver, intent, true, TAG) >= 0) {
                           //匹配发起的Intent数据是否匹配成功,匹配项共有4项action, type, data, category,任何一项匹配不成功都会失败
21422                    if (allSticky == null) {
21423                        allSticky = new ArrayList<Intent>();
21424                    }
21425                    allSticky.add(intent); //找到该次注册的广播接收者所有对应的(可响应的)sticky broadcast (Intent)
21426                }
21427            }
21428        }
21429
21430        // The first sticky in the list is returned directly back to the client.
21431        Intent sticky = allSticky != null ? allSticky.get(0) : null; //返回所有匹配队列中的第一个
21432        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
21433        if (receiver == null) {
                      //当IIntentReceiver为空,则直接返回第一个sticky Intent
21434            return sticky;
21435        }
21436
21437        synchronized (this) {
21438            if (callerApp != null && (callerApp.thread == null
21439                    || callerApp.thread.asBinder() != caller.asBinder())) {
21440                // Original caller already died
                         //注册receiver进程已经死亡
21441                return null;
21442            }
21443            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
21444            if (rl == null) {
21445                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
21446                        userId, receiver); 
                           //receiver:IIntentReceiver的binder对象,AMS可以用来调用caller进程中的broadcastReceiver中的方法
                         //ReceiverList在AMS中可以代表一个broadcatstReceiver,接收一个或多个broadcast对象
21447                if (rl.app != null) {
21448                    final int totalReceiversForApp = rl.app.receivers.size(); //ProcessRecord中保存了receivers对象,代表这个进程中有多少个动态注册的receiver
21449                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                                 //一个进程中注册的receiver不能超过1000
21450                        throw new IllegalStateException("Too many receivers, total of "
21451                                + totalReceiversForApp + ", registered for pid: "
21452                                + rl.pid + ", callerPackage: " + callerPackage);
21453                    }
21454                    rl.app.receivers.add(rl);
21455                } else {
21456                    try {
21457                        receiver.asBinder().linkToDeath(rl, 0); //为IIntentReceiver注册死亡回调
21458                    } catch (RemoteException e) {
21459                        return sticky;
21460                    }
21461                    rl.linkedToDeath = true;
21462                }
21463                mRegisteredReceivers.put(receiver.asBinder(), rl); //将创建的接收者队列ReceiverList保存在AMS中的mRegisteredReceivers
21464            } else if (rl.uid != callingUid) {
21465                throw new IllegalArgumentException(
21466                        "Receiver requested to register for uid " + callingUid
21467                        + " was previously registered for uid " + rl.uid
21468                        + " callerPackage is " + callerPackage);
21469            } else if (rl.pid != callingPid) {
21470                throw new IllegalArgumentException(
21471                        "Receiver requested to register for pid " + callingPid
21472                        + " was previously registered for pid " + rl.pid
21473                        + " callerPackage is " + callerPackage);
21474            } else if (rl.userId != userId) {
21475                throw new IllegalArgumentException(
21476                        "Receiver requested to register for user " + userId
21477                        + " was previously registered for user " + rl.userId
21478                        + " callerPackage is " + callerPackage);
21479            }
                      //创建新的BroadcastFilter,用于添加的ReceiverList中
                      (注册一个广播接收者与两个参数有关,一个是用于处理广播的BroadcastReceiver实例,另一个是filter
                     BroadcastReceiver在AMS中用ReceiverList表示,BroadcastReceiver+filter用 BroadcastFilter表示)
21480            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
21481                    permission, callingUid, userId, instantApp, visibleToInstantApps);
21482            if (rl.containsFilter(filter)) {
21483                Slog.w(TAG, "Receiver with filter " + filter
21484                        + " already registered for pid " + rl.pid
21485                        + ", callerPackage is " + callerPackage);
21486            } else {
21487                rl.add(bf);
21488                if (!bf.debugCheck()) {
21489                    Slog.w(TAG, "==> For Dynamic broadcast");
21490                }
21491                mReceiverResolver.addFilter(bf);
21492            }
21493
21494            // Enqueue broadcasts for all existing stickies that match
21495            // this filter.
                      //所有匹配该filter的sticky广播执行入队操作
                       //如果注册的该BroadcastReceiver广播接收者所能响应的filter中没有粘性广播,则allSticky == null
                     //不为null,说明该BroadcastReceiver有粘性广播待响应,所以注册的流程中也有发送广播的流程,构造广播并加入到广播处理队列
21496            if (allSticky != null) {
21497                ArrayList receivers = new ArrayList();
21498                receivers.add(bf);
21499
21500                final int stickyCount = allSticky.size();
21501                for (int i = 0; i < stickyCount; i++) {
21502                    Intent intent = allSticky.get(i);
                            //当intent为前台广播,则返回mFgBroadcastQueue
                            //当intent为后台广播,则返回mBgBroadcastQueue
21503                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                              //创建broadcastRecord
21504                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
21505                            null, -1, -1, false, null, null, OP_NONE, null, receivers,
21506                            null, 0, null, null, false, true, true, -1);
21507                    queue.enqueueParallelBroadcastLocked(r); //添加到并行队列中
                           //调度广播,发送BROADCAST_INTENT_MSG消息,触发处理下一个广播
21508                    queue.scheduleBroadcastsLocked();
21509                }
21510            }
21511
21512            return sticky;
21513        }
21514    }
registerReceiver.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355

推荐阅读更多精彩内容