个人博客
http://www.milovetingting.cn
Android中ANR的触发机制-BroadcastReceiver篇 上一篇分析了Service中的ANR触发机制,这一篇来分析BroadcastReceiver的ANR触发机制。
触发机制分析 附上时序图
注册过程 要分析BroadcastReceiver的ANR机制,先来看BroadcastReceiver的register过程,静态注册这里不作分析。
不管Activity还是Service中的registerReceiver,最终都是调用ContextWrapper中的registerReceiver方法
1 2 3 4 5 @Override public Intent registerReceiver ( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
看下ContextImpl的registerReceiver方法
1 2 3 4 5 @Override public Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null , null ); }
这个方法调用另一个重载方法
1 2 3 4 5 6 7 @Override public Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext(), 0 ); }
这个方法调用registerReceiverInternal方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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(); } }
调用AMS的registerReceiver方法,这里传入了LoadedAPK$ReceiverDispatcher类型的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public Intent registerReceiver (IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { 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); } }
在这里将信息保存
发送广播过程 在ContextImpl中调用sendBroadcast方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @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(); } }
这个方法中调用AMS的broadcastIntent方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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:
1 2 3 4 5 6 7 8 9 10 11 12 @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) { queue.scheduleBroadcastsLocked(); }
调用BroadcastQueue的scheduleBroadcastsLocked方法
1 2 3 4 5 6 7 8 9 10 11 12 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 ; }
这个方法里通过BroadcastHandler发送了一个BROADCAST_INTENT_MSG消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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: { if (DEBUG_BROADCAST) Slog.v( TAG_BROADCAST, "Received BROADCAST_INTENT_MSG" ); processNextBroadcast(true ); } break ; } } }
在handleMessage方法中调用processNextBroadcast方法
1 2 3 4 5 6 final void processNextBroadcast (boolean fromMsg) { synchronized (mService) { processNextBroadcastLocked(fromMsg, false ); } }
这个方法调用processNextBroadcastLocked方法:
1 2 3 4 5 6 7 8 9 final void processNextBroadcastLocked (boolean fromMsg, boolean skipOomAdj) { setBroadcastTimeoutLocked(timeoutTime); deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx); cancelBroadcastTimeoutLocked(); }
首先调用setBroadcastTimeoutLocked方法来设置超时时间
BroadcastReceiver超时时间,前台广播10秒,后台广播60秒。
1 2 3 // How long we allow a receiver to run before giving up on it. static final int BROADCAST_FG_TIMEOUT = 10*1000; static final int BROADCAST_BG_TIMEOUT = 60*1000;
1 2 3 4 5 6 7 8 final void setBroadcastTimeoutLocked (long timeoutTime) { if (! mPendingBroadcastTimeoutMessage) { Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this ); mHandler.sendMessageAtTime(msg, timeoutTime); mPendingBroadcastTimeoutMessage = true ; } }
在handleMessage中,如果执行超时,则会回调
1 2 3 4 5 6 7 8 9 10 11 @Override public void handleMessage (Message msg) { switch (msg.what) { case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true ); } } break ; } }
设置超时的部分,先看到这里。接下来看deliverToRegisteredReceiverLocked
1 2 3 4 5 6 7 8 9 private void deliverToRegisteredReceiverLocked (BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent (r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); }
这个方法会调用performReceiveLocked方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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) { Slog.w(TAG, "Can't deliver broadcast to " + app.processName + " (pid " + app.pid + "). Crashing it." ); 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); } }
调用Activity中的ApplicationThread的scheduleRegisteredReceiver方法
1 2 3 4 5 6 7 8 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); }
调用BroadcastQueue的ReceiverDispatcher的InnerReceiver的performReceive方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @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 ) { Log.wtf(TAG, "Null intent received" ); rd = null ; } else { rd = mDispatcher.get(); } if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq" , -1 ); Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null )); } if (rd != null ) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to unregistered receiver" ); 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(); } } }
调用BroadcastQueue的ReceiverDispatcher的performReceive方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 ) { 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())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } }
这里调用了ReceiverDispatcher的Handler类型的mActivityThread的post方法,将一个runnable发送出去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public final Runnable getRunnable () { return () -> { try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this ); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing failed broadcast to " + mReceiver); sendFinished(mgr); } if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException ( "Error receiving broadcast " + intent + " in " + mReceiver, e); } } if (receiver.getPendingResult() != null ) { finish(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); }; }
在这里回调onReceive
接下来看cancelBroadcastTimeoutLocked
1 2 3 4 5 6 7 final void cancelBroadcastTimeoutLocked () { if (mPendingBroadcastTimeoutMessage) { mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this ); mPendingBroadcastTimeoutMessage = false ; } }
移除了超时检测的消息,ANR不会触发。
如果没有在规定时间完成,则会处理BROADCAST_TIMEOUT_MSG消息
1 2 3 4 5 6 7 8 9 10 11 12 @Override public void handleMessage (Message msg) { switch (msg.what) { case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true ); } } break ; } }
调用broadcastTimeoutLocked,触发ANR
1 2 3 4 5 6 7 8 9 final void broadcastTimeoutLocked (boolean fromMsg) { if (!debugging && anrMessage != null ) { mHandler.post(new AppNotResponding (app, anrMessage)); } }