ANR原理和分析

背景

  ANR分析需要结合各个层面大量的数据,诸如堆栈信息、Android log等。可能是app出了问题,也可能是framwork出了问题,甚至是内核出了问题。那么理解anr的机制,才能分析好具体的ANR问题。

  ANR就是应用无响应,超过一定时间,由system server进程弹窗提示。
  ANR分类:1.Service(前台超时20s) 2. Broadcast(前台超时10s) 3. ContentProvider(前台超时10s) 4.InputDispatcing(超时5s)
  ANR过程:埋炸弹—>拆炸弹/引爆炸弹

ANR原理

  Sevice ANR原理:

    Service启动过程中:1、AMS收到启动请求,由ActiveServices埋炸弹。2、AMS资源处理完成通知app,app在service的onCreate()之后,请求AMS拆除炸弹,由ActiveServices拆除炸弹。3、如果启动超时,将由ActiveServices引爆炸弹
    1、埋炸弹
  /frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

final ActivityManagerService mAm;
//启动流程,经过层层函数到这儿
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,boolean enqueueOomAdj) throws RemoteException {
	bumpServiceExecutingLocked(r, execInFg, "create",OOM_ADJ_REASON_NONE /* use "none" to avoid extra oom adj */);
	//通知app走onCreate()
    thread.scheduleCreateService(r, r.serviceInfo,null,app.mState.getReportedProcState());
}
private boolean bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why, @OomAdjReason int oomAdjReason) {
	 scheduleServiceTimeoutLocked(r.app);
}
void scheduleServiceTimeoutLocked(ProcessRecord proc) {          
     //炸弹开始倒计时
     mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg()? mAm.mConstants.SERVICE_TIMEOUT :mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT);
}

    2、拆炸弹
    /frameworks/base/core/java/android/app/ActivityThread.java

//app接到通知
private class ApplicationThread extends IApplicationThread.Stub {
	 public final void scheduleCreateService(IBinder token,ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
	 	sendMessage(H.CREATE_SERVICE, s);
     }
}
class H extends Handler {//主线程
	public void handleMessage(Message msg) {
		switch (msg.what) {
			case CREATE_SERVICE:
				handleCreateService((CreateServiceData)msg.obj);
				break;
		}
	}
}
private void handleCreateService(CreateServiceData data) {
	service.onCreate();
	ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}

  /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final ActiveServices mServices;
public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    mServices.serviceDoneExecutingLocked((ServiceRecord) token, type, startId, res, false);
}

  /frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,boolean finishing, boolean enqueueOomAdj, @OomAdjReason int oomAdjReason) {
	//拆除炸弹
	mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
}

    3、引爆炸弹
    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final MainHandler mHandler;
final ActiveServices mServices;
final class MainHandler extends Handler {
		public void handleMessage(Message msg) {
			switch (msg.what) {
				 case SERVICE_TIMEOUT_MSG: {
                  		mServices.serviceTimeout((ProcessRecord) msg.obj);
              			} break;
              	 case SERVICE_FOREGROUND_TIMEOUT_MSG: {
                  		mServices.serviceForegroundTimeout((ServiceRecord) msg.obj);
              			} break;
			}
		}
}

  /frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

void serviceTimeout(ProcessRecord proc) {
	mAm.mAnrHelper.appNotResponding(proc, timeoutRecord);
}

  Broadcast ANR原理:

    发送广播的过程:1、AMS收到app请求,由BroadcastQueueImpl埋炸弹。2、AMS完成资源处理,通知app回调receiver的onReceive(),之后app请求AMS拆除炸弹 3、如果超时,由BroadcastQueueImpl引爆炸弹
    注意:串行广播才有ANR,并行广播没有。广播ANR细分为2种:1、broadcast的ANR,主要计算receiver数量的总时长。 2、BroadcastReceiver的ANR,主要计算单个receiver的时长。
    1、埋炸弹
    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

//app请求到这儿
public final int broadcastIntentWithFeature(IApplicationThread caller, .....) {
 	return broadcastIntentLocked(callerApp,...........);
}
final int broadcastIntentLocked(ProcessRecord callerApp,......){
	final int res = broadcastIntentLockedTraced(callerApp,........);
}
final int broadcastIntentLockedTraced(ProcessRecord callerApp,....){
 	BroadcastQueue queue = broadcastQueueForIntent(intent);
	queue.enqueueBroadcastLocked(r);
}

    /frameworks/base/services/core/java/com/android/server/am/BroadcastQueueImpl.java

final BroadcastHandler mHandler;
boolean mBroadcastsScheduled = false;//标志-有广播正在处理
public void enqueueBroadcastLocked(BroadcastRecord r) {
	enqueueOrderedBroadcastLocked(r);
	scheduleBroadcastsLocked();
}
public void scheduleBroadcastsLocked() {
	if (mBroadcastsScheduled) {//当前广播正在处理,拒绝下一个广播
         return;
    }
	mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
	mBroadcastsScheduled = true;
}
private final class BroadcastHandler extends Handler {
	public void handleMessage(Message msg) {
		switch (msg.what) {
                  case BROADCAST_INTENT_MSG: {
                      processNextBroadcast(true);
                     } break;
                  case BROADCAST_TIMEOUT_MSG: {
                      broadcastTimeoutLocked(true);
                  } break;
         }
	}
}
private void processNextBroadcast(boolean fromMsg) {
      processNextBroadcastLocked(fromMsg, false);
}
public void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
	 BroadcastRecord r;
	 if (fromMsg) {
	     mBroadcastsScheduled = false;
     }
     ................................//并行广播分发省略,不存在ANR 
     //处理串行广播
     do {
		r = mDispatcher.getNextBroadcastLocked(now);
		//广播分发,总时间超时,也会ANR。
     	if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
     		if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {
     		 	broadcastTimeoutLocked(false); // forcibly finish this broadcast,此处也会弹ANR,省略
     		}
     	} 
	 } while (r == null);
	 //准备分发给receiver了
	 int recIdx = r.nextReceiver++;
	 r.receiverTime = SystemClock.uptimeMillis();//更新 每个receiver分发 开始时间,用于判断单个receiver是否超时。
	 if (recIdx == 0) {//记录 第一个receiver 分发时间,控制分发总时间的ANR。埋了一个“总时长炸弹”
	 	r.dispatchTime = r.receiverTime;
	 }
	 //埋了“单个receiver炸弹”
	 setBroadcastTimeoutLocked(timeoutTime);
	 //分发receiver 
	 deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
}
//埋炸弹
final void setBroadcastTimeoutLocked(long timeoutTime) {
	if (! mPendingBroadcastTimeoutMessage) {//上一个receiver的炸弹,倒计时没结束,当前receiver暂不埋炸弹。
	   Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
       mHandler.sendMessageAtTime(msg, timeoutTime);
       mPendingBroadcastTimeoutMessage = true;
	}
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,BroadcastFilter filter, boolean ordered, int index) {
		performReceiveLocked(r,........);
}
//通知app走reciever的onRecieve()
public void performReceiveLocked(BroadcastRecord r,){
	final IApplicationThread thread = app.getThread();
	thread.scheduleRegisteredReceiver(......);
}

    2、拆炸弹
    /frameworks/base/core/java/android/app/ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
	public void scheduleRegisteredReceiver(IIntentReceiver receiver, ....){
		receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser);
	}
}

    /frameworks/base/core/java/android/app/LoadedApk.java

static final class ReceiverDispatcher {
	final static class InnerReceiver extends IIntentReceiver.Stub {
		public void performReceive(){
			final LoadedApk.ReceiverDispatcher rd;
			rd.performReceive(intent, resultCode, data, extras,ordered, sticky, assumeDelivered, sendingUser,sendingUid, sendingPackage);
		}
	}
	public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,int sendingUser, int sendingUid, String sendingPackage) {
		final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, assumeDelivered, sendingUser, sendingUid, sendingPackage);
		if (intent == null || !mActivityThread.post(args.getRunnable())) {//调用receiver的onReceive()
			IActivityManager mgr = ActivityManager.getService();
			args.sendFinished(mgr);
		}
	}
	final class Args extends BroadcastReceiver.PendingResult {
		public final Runnable getRunnable() {
			final BroadcastReceiver receiver = mReceiver;
			receiver.onReceive(mContext, intent);
		}
	}
}

    /frameworks/base/core/java/android/content/BroadcastReceiver.java

public static class PendingResult {
	public void sendFinished(IActivityManager am) {
		am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,mAbortBroadcast, mFlags);
	}
}

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void finishReceiver(IBinder caller, int resultCode, String resultData,Bundle resultExtras, boolean resultAbort, int flags) {
	queue.finishReceiverLocked(callerApp, resultCode,resultData, resultExtras, resultAbort, true);
}

/frameworks/base/services/core/java/com/android/server/am/BroadcastQueueImpl.java

public boolean finishReceiverLocked(ProcessRecord app, int resultCode,String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
	return finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, waitForServices);
}
public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
	processNextBroadcastLocked(/* fromMsg= */ false, /* skipOomAdj= */ true);
}
public void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
	do {//处理串行广播
		//分发最后一个receiver时,拆掉 总时长炸弹。
		if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) {
			cancelBroadcastTimeoutLocked();
		}
	 } while (r == null);
}
//这里拆除单个receiver炸弹。这里的代码真的太骚了!!!我找了好久!!!
final void broadcastTimeoutLocked(boolean fromMsg) {
	if (fromMsg) {//从Handler倒计时满了过来的,才设置下面的标志位,表示允许埋 单个receiver炸弹
    	mPendingBroadcastTimeoutMessage = false;
    }
    if (fromMsg) {
    	long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
    	if (timeoutTime > now) {//下一个receiver开始分发了,r.receiverTime被更新,并且下一个receiver还没超时。那本次也没超时
    		setBroadcastTimeoutLocked(timeoutTime);//这里才开始埋下一个receiver的炸弹
    		return;//本次分发没超时,直接return了。惊不惊喜意不意外!
    	}
    }
}

    3、引爆炸弹
/frameworks/base/services/core/java/com/android/server/am/BroadcastQueueImpl.java

final void broadcastTimeoutLocked(boolean fromMsg) {
	 //前面的代码判断超时,会走到这一步
	 mService.appNotResponding(app, timeoutRecord);
}

  ContentProvider ANR原理:

    首先ContentProvider的启动过程,包含在app的启动过程中。AMS亲自埋炸弹。注意不会弹ANR弹窗,会直接杀死app。
    1、埋炸弹
    /frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
	ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
}
private void attach(boolean system, long startSeq) {
	final IActivityManager mgr = ActivityManager.getService();
	mgr.attachApplication(mAppThread, startSeq);
}

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final void attachApplication(IApplicationThread thread, long startSeq) {
	attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) {
	List<ProviderInfo> providers = normalMode ? mCpHelper.generateApplicationProvidersLocked(app) : null;
	//埋炸弹
    if (providers != null && mCpHelper.checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
    }
    //通知app处理ContentProvider流程
	thread.bindApplication(processName, appInfo, providerList,........);
}

    2、拆炸弹

    /frameworks/base/core/java/android/app/ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
	public final void bindApplication(String processName, ApplicationInfo appInfo, ProviderInfoList providerList, ...) {
		sendMessage(H.BIND_APPLICATION, data);
    }
}
class H extends Handler {
	public void handleMessage(Message msg) {
		switch (msg.what) {
			case BIND_APPLICATION:
			handleBindApplication(data);
			break;
		}
	}
}
private void handleBindApplication(AppBindData data) {
	installContentProviders(app, data.providers);
	mInstrumentation.callApplicationOnCreate(app);
}
private void installContentProviders(Context context, List<ProviderInfo> providers) {
	//创建ContentProvider
	ContentProviderHolder cph = installProvider(context, null, cpi,false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
	results.add(cph);
	ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
}

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final void publishContentProviders(IApplicationThread caller,List<ContentProviderHolder> providers) {
	 mCpHelper.publishContentProviders(caller, providers);
}

    /frameworks/base/services/core/java/com/android/server/am/ContentProviderHelper.java

void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
	//拆除炸弹
	mService.mHandler.removeMessages( ActivityManagerService.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
}

    3、引爆炸弹
    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final class MainHandler extends Handler {
	public void handleMessage(Message msg) {
		switch (msg.what) {
			case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
                mCpHelper.processContentProviderPublishTimedOutLocked(app);
            } break;
		}
	}
}

    /frameworks/base/services/core/java/com/android/server/am/ContentProviderHelper.java

void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
	cleanupAppInLaunchingProvidersLocked(app, true);
	mService.mProcessList.removeProcessLocked(app,.....);
}

    /frameworks/base/services/core/java/com/android/server/am/ProcessList.java

boolean removeProcessLocked(ProcessRecord app,.....) {
	 //直接干掉app
	 app.killLocked(reason, reasonCode, subReason, true, async);
}

  InputDispatching ANR原理:

    EventHub负责监听/dev/input产生的input事件,InputReader负责从EventHub读取事件,并将事件分发给InputDispatcher,InputDispatcher分发给当前获取到焦点的Window。ANR在InputDispatcher的流程里面。
    埋炸弹
    /frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

// 超时时间
const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::milliseconds( android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *HwTimeoutMultiplier());

status_t InputDispatcher::start() {
      mThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
}
void InputDispatcher::dispatchOnce() {
	dispatchOnceInnerLocked(&nextWakeupTime);
	//检查ANR
	const nsecs_t nextAnrCheck = processAnrsLocked();
}
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
	//mInboundQueue取出一个Event
	mPendingEvent = mInboundQueue.front();
	switch (mPendingEvent->type) {
		case EventEntry::Type::KEY: {//按键
			done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
			break;
		}
		case EventEntry::Type::MOTION: {//手势
			done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
		}
	}
}
// 分发按键
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
	// 找到focusedWindow,这里 会埋下 noFocusedWindow超时时间
	sp<WindowInfoHandle> focusedWindow =findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime,injectionResult);
	dispatchEventLocked(currentTime, entry, inputTargets);
}
// 分发手势
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,DropReason* dropReason, nsecs_t* nextWakeupTime) {
	if (isPointerEvent) {
	}else{// 找到focusedWindow,这里 会埋下 noFocusedWindow超时时间
		sp<WindowInfoHandle> focusedWindow = findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime, injectionResult);
	}
	dispatchEventLocked(currentTime, entry, inputTargets);
}
sp<WindowInfoHandle> InputDispatcher::findFocusedWindowTargetLocked(){
	// 有focused的app,但没有focused的window
	if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
		if (!mNoFocusedWindowTimeoutTime.has_value()) {
			 std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
			 //埋炸弹--noFocusedWindow类型ANR
			 mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
			 return nullptr;
		}
	}
	// 有focusedWindow取消ANR计时
	resetNoFocusedWindowTimeoutLocked();
}
// 不管是按键还是手势,都到分发事件函数
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,std::shared_ptr<EventEntry> eventEntry, const std::vector<InputTarget>& inputTargets) {
	for (const InputTarget& inputTarget : inputTargets) {
		prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
	}
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget) {
	enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,const std::shared_ptr<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget) {
	//将dispatchEntry放入connection->outboundQueue
	enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::Flags::DISPATCH_AS_HOVER_EXIT);
	startDispatchCycleLocked(currentTime, connection);
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection>& connection) {
	while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
		DispatchEntry* dispatchEntry = connection->outboundQueue.front();
		const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
		//设置超时时间
		dispatchEntry->timeoutTime = currentTime + timeout.count();
		switch (eventEntry.type) {
			case EventEntry::Type::KEY: {//将按键事件分发给Java层
				status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,...);
				break;
			}
			case EventEntry::Type::MOTION: {//将手势事件分发给Java层
				status = publishMotionEvent(*connection, *dispatchEntry);
				break;
			}
		}
		//为了表示正在分发中,event重新入队wait queue.
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),connection->outboundQueue.end(),dispatchEntry));
        connection->waitQueue.push_back(dispatchEntry);
		//埋炸弹--分发超时ANR
		mAnrTracker.insert(dispatchEntry->timeoutTime, connection->inputChannel->getConnectionToken());
	}
}
std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked(const std::shared_ptr<Connection>& connection) {
	return DEFAULT_INPUT_DISPATCHING_TIMEOUT;
}
status_t InputDispatcher::publishMotionEvent(Connection& connection,DispatchEntry& dispatchEntry) const {
	return connection.inputPublisher.publishMotionEvent(dispatchEntry.seq,...);
}

    /frameworks/native/libs/input/android/os/IInputConstants.aidl

	const int UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS = 5000; // 5 seconds

    拆炸弹

    引爆炸弹
    /frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

nsecs_t InputDispatcher::processAnrsLocked() {
	nsecs_t nextAnrCheck = LLONG_MAX; // 下一次检查anr的时间
	// 检查 是否在等待 聚焦窗口出现。如果超时 报ANR
	if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
		if (currentTime >= *mNoFocusedWindowTimeoutTime) {
			//场景1:noFocusedWindow的ANR
			processNoFocusedWindowAnrLocked();
		}
	}
	// 检查分发类型 ANRs 是否超时
	nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
	if (currentTime < nextAnrCheck) {
          return nextAnrCheck;        
    }
	// 分发 超时了
	std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
	//删除记录的超时 
	mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
	// 场景2:分发超时ANR
	onAnrLocked(connection);
}
void InputDispatcher::processNoFocusedWindowAnrLocked() {
	// 没有焦点app 或 焦点app不是我们等的那个
	if (focusedApplication == nullptr || focusedApplication->getApplicationToken() != mAwaitedFocusedApplication->getApplicationToken()) {
		return;//直接返回,因为焦点app已经变更
	}
	// 再次检查焦点app,是否焦点window
	const sp<WindowInfoHandle>& focusedWindowHandle = getFocusedWindowHandleLocked(mAwaitedApplicationDisplayId);
	if (focusedWindowHandle != nullptr) {
          return; // 有focused window了. 无需触发ANR了.
    }
    onAnrLocked(mAwaitedFocusedApplication);
}
void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) {
	// 之前将正在分发的event放到了waitQueue,现在它空了,那就不弹ANR了
	if (connection->waitQueue.empty()) {
		return;
	}
	processConnectionUnresponsiveLocked(*connection, std::move(reason));
}
void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection,std::string reason) {
	sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
}

ANR分析步骤

源码

参考版本:14.0.0
http://aospxref.com/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值