当前位置:   article > 正文

深度刨析Android ANR触发原理_android anr原理

android anr原理

一、概述

ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。

那么哪些场景会造成ANR呢?

  • Service Timeout:比如前台服务在20s内未执行完成;
  • BroadcastQueue Timeout:比如前台广播在10s内未执行完成
  • ContentProvider Timeout:内容提供者,在publish过超时10s;
  • InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。

触发ANR的过程可分为三个步骤: 埋炸弹, 拆炸弹, 引爆炸弹

二 Service

Service Timeout是位于”ActivityManager”线程中的AMS.MainHandler收到SERVICE_TIMEOUT_MSG消息时触发。

对于Service有两类:

  • 对于前台服务,则超时为SERVICE_TIMEOUT = 20s;
  • 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s

由变量ProcessRecord.execServicesFg来决定是否前台启动

2.1 埋雷

Service进程attach到system_server进程的过程中会调用realStartServiceLocked()方法来埋下炸弹.

2.1.1 AS.realStartServiceLocked

[-> ActiveServices.java]

  1. private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {
  2. ...
  3. //发送delay消息(SERVICE_TIMEOUT_MSG),【见小节2.1.2】
  4. bumpServiceExecutingLocked(r, execInFg, "create");
  5. try {
  6. ...
  7. //最终执行服务的onCreate()方法
  8. app.thread.scheduleCreateService(r, r.serviceInfo,
  9. mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
  10. app.repProcState);
  11. } catch (DeadObjectException e) {
  12. mAm.appDiedLocked(app);
  13. throw e;
  14. } finally {
  15. ...
  16. }
  17. }
2.1.2 AS.bumpServiceExecutingLocked
  1. private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
  2. ...
  3. scheduleServiceTimeoutLocked(r.app);
  4. }
  5. void scheduleServiceTimeoutLocked(ProcessRecord proc) {
  6. if (proc.executingServices.size() == 0 || proc.thread == null) {
  7. return;
  8. }
  9. long now = SystemClock.uptimeMillis();
  10. Message msg = mAm.mHandler.obtainMessage(
  11. ActivityManagerService.SERVICE_TIMEOUT_MSG);
  12. msg.obj = proc;
  13. //当超时后仍没有remove该SERVICE_TIMEOUT_MSG消息,则执行service Timeout流程【见2.3.1】
  14. mAm.mHandler.sendMessageAtTime(msg,
  15. proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
  16. }

该方法的主要工作发送delay消息(SERVICE_TIMEOUT_MSG). 炸弹已埋下, 我们并不希望炸弹被引爆, 那么就需要在炸弹爆炸之前拆除炸弹.

2.2 拆雷

在system_server进程AS.realStartServiceLocked()调用的过程会埋下一颗炸弹, 超时没有启动完成则会爆炸. 那么什么时候会拆除这颗炸弹的引线呢? 经过Binder等层层调用进入目标进程的主线程handleCreateService()的过程.

2.2.1 AT.handleCreateService

[-> ActivityThread.java]

  1. private void handleCreateService(CreateServiceData data) {
  2. ...
  3. java.lang.ClassLoader cl = packageInfo.getClassLoader();
  4. Service service = (Service) cl.loadClass(data.info.name).newInstance();
  5. ...
  6. try {
  7. //创建ContextImpl对象
  8. ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
  9. context.setOuterContext(service);
  10. //创建Application对象
  11. Application app = packageInfo.makeApplication(false, mInstrumentation);
  12. service.attach(context, this, data.info.name, data.token, app,
  13. ActivityManagerNative.getDefault());
  14. //调用服务onCreate()方法 
  15. service.onCreate();
  16. //拆除炸弹引线[见小节2.2.2]
  17. ActivityManagerNative.getDefault().serviceDoneExecuting(
  18. data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
  19. } catch (Exception e) {
  20. ...
  21. }
  22. }

在这个过程会创建目标服务对象,以及回调onCreate()方法, 紧接再次经过多次调用回到system_server来执行serviceDoneExecuting.

2.2.2 AS.serviceDoneExecutingLocked
  1. private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying, boolean finishing) {
  2. ...
  3. if (r.executeNesting <= 0) {
  4. if (r.app != null) {
  5. r.app.execServicesFg = false;
  6. r.app.executingServices.remove(r);
  7. if (r.app.executingServices.size() == 0) {
  8. //当前服务所在进程中没有正在执行的service
  9. mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
  10. ...
  11. }
  12. ...
  13. }

该方法的主要工作是当service启动完成,则移除服务超时消息SERVICE_TIMEOUT_MSG

2.3 引爆

前面介绍了埋炸弹和拆炸弹的过程, 如果在炸弹倒计时结束之前成功拆卸炸弹,那么就没有爆炸的机会, 但是世事难料. 总有些极端情况下无法即时拆除炸弹,导致炸弹爆炸, 其结果就是App发生ANR. 接下来,带大家来看看炸弹爆炸的现场:

在system_server进程中有一个Handler线程, 名叫”ActivityManager”.当倒计时结束便会向该Handler线程发送 一条信息SERVICE_TIMEOUT_MSG,

2.3.1 MainHandler.handleMessage

[-> ActivityManagerService.java ::MainHandler]

  1. final class MainHandler extends Handler {
  2. public void handleMessage(Message msg) {
  3. switch (msg.what) {
  4. case SERVICE_TIMEOUT_MSG: {
  5. ...
  6. //【见小节2.3.2】
  7. mServices.serviceTimeout((ProcessRecord)msg.obj);
  8. } break;
  9. ...
  10. }
  11. ...
  12. }
  13. }
2.3.2 AS.serviceTimeout
  1. void serviceTimeout(ProcessRecord proc) {
  2. String anrMessage = null;
  3. synchronized(mAm) {
  4. if (proc.executingServices.size() == 0 || proc.thread == null) {
  5. return;
  6. }
  7. final long now = SystemClock.uptimeMillis();
  8. final long maxTime = now -
  9. (proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
  10. ServiceRecord timeout = null;
  11. long nextTime = 0;
  12. for (int i=proc.executingServices.size()-1; i>=0; i--) {
  13. ServiceRecord sr = proc.executingServices.valueAt(i);
  14. if (sr.executingStart < maxTime) {
  15. timeout = sr;
  16. break;
  17. }
  18. if (sr.executingStart > nextTime) {
  19. nextTime = sr.executingStart;
  20. }
  21. }
  22. if (timeout != null && mAm.mLruProcesses.contains(proc)) {
  23. Slog.w(TAG, "Timeout executing service: " + timeout);
  24. StringWriter sw = new StringWriter();
  25. PrintWriter pw = new FastPrintWriter(sw, false, 1024);
  26. pw.println(timeout);
  27. timeout.dump(pw, " ");
  28. pw.close();
  29. mLastAnrDump = sw.toString();
  30. mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
  31. mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
  32. anrMessage = "executing service " + timeout.shortName;
  33. }
  34. }
  35. if (anrMessage != null) {
  36. //当存在timeout的service,则执行appNotResponding
  37. mAm.appNotResponding(proc, null, null, false, anrMessage);
  38. }
  39. }

其中anrMessage的内容为”executing service [发送超时serviceRecord信息]”;

三 BroadcastReceiver

BroadcastReceiver Timeout是位于”ActivityManager”线程中的BroadcastQueue.BroadcastHandler收到BROADCAST_TIMEOUT_MSG消息时触发。

对于广播队列有两个: foreground队列和background队列:

  • 对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;
  • 对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s

3.1 埋雷

广播启动通过调用 processNextBroadcast来处理广播.其流程为先处理并行广播,再处理当前有序广播,最后获取并处理下条有序广播.

3.1.1 processNextBroadcast

[-> BroadcastQueue.java]

  1. final void processNextBroadcast(boolean fromMsg) {
  2. synchronized(mService) {
  3. ...
  4. //part 2: 处理当前有序广播
  5. do {
  6. r = mOrderedBroadcasts.get(0);
  7. //获取所有该广播所有的接收者
  8. int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
  9. if (mService.mProcessesReady && r.dispatchTime > 0) {
  10. long now = SystemClock.uptimeMillis();
  11. if ((numReceivers > 0) &&
  12. (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
  13. //当广播处理时间超时,则强制结束这条广播【见小节3.3.2】
  14. broadcastTimeoutLocked(false);
  15. ...
  16. }
  17. }
  18. if (r.receivers == null || r.nextReceiver >= numReceivers
  19. || r.resultAbort || forceReceive) {
  20. if (r.resultTo != null) {
  21. //处理广播消息消息
  22. performReceiveLocked(r.callerApp, r.resultTo,
  23. new Intent(r.intent), r.resultCode,
  24. r.resultData, r.resultExtras, false, false, r.userId);
  25. r.resultTo = null;
  26. }
  27. //拆炸弹【见小节3.2.2】
  28. cancelBroadcastTimeoutLocked();
  29. }
  30. } while (r == null);
  31. ...
  32. //part 3: 获取下条有序广播
  33. r.receiverTime = SystemClock.uptimeMillis();
  34. if (!mPendingBroadcastTimeoutMessage) {
  35. long timeoutTime = r.receiverTime + mTimeoutPeriod;
  36. //埋炸弹【见小节3.1.2】
  37. setBroadcastTimeoutLocked(timeoutTime);
  38. }
  39. ...
  40. }
  41. }

对于广播超时处理时机:

  1. 首先在part3的过程中setBroadcastTimeoutLocked(timeoutTime) 设置超时广播消息;
  2. 然后在part2根据广播处理情况来处理:
    • 当广播接收者等待时间过长,则调用broadcastTimeoutLocked(false);
    • 当执行完广播,则调用cancelBroadcastTimeoutLocked;
3.1.2 setBroadcastTimeoutLocked
  1. final void setBroadcastTimeoutLocked(long timeoutTime) {
  2. if (! mPendingBroadcastTimeoutMessage) {
  3. Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
  4. mHandler.sendMessageAtTime(msg, timeoutTime);
  5. mPendingBroadcastTimeoutMessage = true;
  6. }
  7. }

设置定时广播BROADCAST_TIMEOUT_MSG,即当前往后推mTimeoutPeriod时间广播还没处理完毕,则进入广播超时流程。

3.2 拆雷

broadcast跟service超时机制大抵相同,但有一个非常隐蔽的技能点,那就是通过静态注册的广播超时会受SharedPreferences(简称SP)的影响。

3.2.1 sendFinished

关于广播是否考虑SP的情况取决于如下代码:

  1. public final void finish() {
  2. if (mType == TYPE_COMPONENT) {
  3. final IActivityManager mgr = ActivityManager.getService();
  4. if (QueuedWork.hasPendingWork()) {
  5. //当SP有未同步到磁盘的工作,则需等待其完成,才告知系统已完成该广播
  6. QueuedWork.queue(new Runnable() {
  7. public void run() {
  8. sendFinished(mgr);
  9. }
  10. }, false);
  11. } else {
  12. sendFinished(mgr);
  13. }
  14. } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
  15. final IActivityManager mgr = ActivityManager.getService();
  16. sendFinished(mgr);
  17. }
  18. }

可见,只有XML静态注册的广播超时检测过程会考虑是否有SP尚未完成,动态广播并不受其影响。

3.2.2 cancelBroadcastTimeoutLocked
  1. final void cancelBroadcastTimeoutLocked() {
  2. if (mPendingBroadcastTimeoutMessage) {
  3. mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
  4. mPendingBroadcastTimeoutMessage = false;
  5. }
  6. }

移除广播超时消息BROADCAST_TIMEOUT_MSG

3.3 引爆

3.3.1 BroadcastHandler.handleMessage

[-> BroadcastQueue.java ::BroadcastHandler]

  1. private final class BroadcastHandler extends Handler {
  2. public void handleMessage(Message msg) {
  3. switch (msg.what) {
  4. case BROADCAST_TIMEOUT_MSG: {
  5. synchronized (mService) {
  6. //【见小节3.3.2】
  7. broadcastTimeoutLocked(true);
  8. }
  9. } break;
  10. ...
  11. }
  12. ...
  13. }
  14. }
3.3.2 broadcastTimeoutLocked

[-> BroadcastRecord.java]

  1. //fromMsg = true
  2. final void broadcastTimeoutLocked(boolean fromMsg) {
  3. if (fromMsg) {
  4. mPendingBroadcastTimeoutMessage = false;
  5. }
  6. if (mOrderedBroadcasts.size() == 0) {
  7. return;
  8. }
  9. long now = SystemClock.uptimeMillis();
  10. BroadcastRecord r = mOrderedBroadcasts.get(0);
  11. if (fromMsg) {
  12. if (mService.mDidDexOpt) {
  13. mService.mDidDexOpt = false;
  14. long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
  15. setBroadcastTimeoutLocked(timeoutTime);
  16. return;
  17. }
  18. if (!mService.mProcessesReady) {
  19. return; //当系统还没有准备就绪时,广播处理流程中不存在广播超时
  20. }
  21. long timeoutTime = r.receiverTime + mTimeoutPeriod;
  22. if (timeoutTime > now) {
  23. //如果当前正在执行的receiver没有超时,则重新设置广播超时
  24. setBroadcastTimeoutLocked(timeoutTime);
  25. return;
  26. }
  27. }
  28. BroadcastRecord br = mOrderedBroadcasts.get(0);
  29. if (br.state == BroadcastRecord.WAITING_SERVICES) {
  30. //广播已经处理完成,但需要等待已启动service执行完成。当等待足够时间,则处理下一条广播。
  31. br.curComponent = null;
  32. br.state = BroadcastRecord.IDLE;
  33. processNextBroadcast(false);
  34. return;
  35. }
  36. r.receiverTime = now;
  37. //当前BroadcastRecord的anr次数执行加1操作
  38. r.anrCount++;
  39. if (r.nextReceiver <= 0) {
  40. return;
  41. }
  42. ...
  43. Object curReceiver = r.receivers.get(r.nextReceiver-1);
  44. //查询App进程
  45. if (curReceiver instanceof BroadcastFilter) {
  46. BroadcastFilter bf = (BroadcastFilter)curReceiver;
  47. if (bf.receiverList.pid != 0
  48. && bf.receiverList.pid != ActivityManagerService.MY_PID) {
  49. synchronized (mService.mPidsSelfLocked) {
  50. app = mService.mPidsSelfLocked.get(
  51. bf.receiverList.pid);
  52. }
  53. }
  54. } else {
  55. app = r.curApp;
  56. }
  57. if (app != null) {
  58. anrMessage = "Broadcast of " + r.intent.toString();
  59. }
  60. if (mPendingBroadcast == r) {
  61. mPendingBroadcast = null;
  62. }
  63. //继续移动到下一个广播接收者
  64. finishReceiverLocked(r, r.resultCode, r.resultData,
  65. r.resultExtras, r.resultAbort, false);
  66. scheduleBroadcastsLocked();
  67. if (anrMessage != null) {
  68. // [见小节3.3.3]
  69. mHandler.post(new AppNotResponding(app, anrMessage));
  70. }
  71. }
  1. mOrderedBroadcasts已处理完成,则不会anr;
  2. 正在执行dexopt,则不会anr;
  3. 系统还没有进入ready状态(mProcessesReady=false),则不会anr;
  4. 如果当前正在执行的receiver没有超时,则重新设置广播超时,不会anr;
3.3.3 AppNotResponding

[-> BroadcastQueue.java]

  1. private final class AppNotResponding implements Runnable {
  2. ...
  3. public void run() {
  4. // 进入ANR处理流程
  5. mService.appNotResponding(mApp, null, null, false, mAnnotation);
  6. }
  7. }

四 ContentProvider

ContentProvider Timeout是位于”ActivityManager”线程中的AMS.MainHandler收到CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息时触发。

ContentProvider 超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s. 这个跟前面的Service和BroadcastQueue完全不同, 由Provider进程启动过程相关.

4.1 埋雷

 埋炸弹的过程 其实是在进程创建的过程,进程创建后会调用attachApplicationLocked()进入system_server进程.

4.1.1 AMS.attachApplicationLocked
  1. private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
  2. ProcessRecord app;
  3. if (pid != MY_PID && pid >= 0) {
  4. synchronized (mPidsSelfLocked) {
  5. app = mPidsSelfLocked.get(pid); // 根据pid获取ProcessRecord
  6. }
  7. }
  8. ...
  9. //系统处于ready状态或者该app为FLAG_PERSISTENT进程则为true
  10. boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
  11. List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
  12. //app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
  13. if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
  14. Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
  15. msg.obj = app;
  16. mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
  17. }
  18. thread.bindApplication(...);
  19. ...
  20. }

10s之后引爆该炸弹

4.2 拆雷

当provider成功publish之后,便会拆除该炸弹.

4.2.1 AMS.publishContentProviders
  1. public final void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
  2. ...
  3. synchronized (this) {
  4. final ProcessRecord r = getRecordForAppLocked(caller);
  5. final int N = providers.size();
  6. for (int i = 0; i < N; i++) {
  7. ContentProviderHolder src = providers.get(i);
  8. ...
  9. ContentProviderRecord dst = r.pubProviders.get(src.info.name);
  10. if (dst != null) {
  11. ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
  12. mProviderMap.putProviderByClass(comp, dst); //将该provider添加到mProviderMap
  13. String names[] = dst.info.authority.split(";");
  14. for (int j = 0; j < names.length; j++) {
  15. mProviderMap.putProviderByName(names[j], dst);
  16. }
  17. int launchingCount = mLaunchingProviders.size();
  18. int j;
  19. boolean wasInLaunchingProviders = false;
  20. for (j = 0; j < launchingCount; j++) {
  21. if (mLaunchingProviders.get(j) == dst) {
  22. //将该provider移除mLaunchingProviders队列
  23. mLaunchingProviders.remove(j);
  24. wasInLaunchingProviders = true;
  25. j--;
  26. launchingCount--;
  27. }
  28. }
  29. //成功pubish则移除该消息
  30. if (wasInLaunchingProviders) {
  31. mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
  32. }
  33. synchronized (dst) {
  34. dst.provider = src.provider;
  35. dst.proc = r;
  36. //唤醒客户端的wait等待方法
  37. dst.notifyAll();
  38. }
  39. ...
  40. }
  41. }
  42. }
  43. }

4.3 引爆

在system_server进程中有一个Handler线程, 名叫”ActivityManager”.当倒计时结束便会向该Handler线程发送 一条信息CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG,

4.3.1 MainHandler.handleMessage

[-> ActivityManagerService.java ::MainHandler]

  1. final class MainHandler extends Handler {
  2. public void handleMessage(Message msg) {
  3. switch (msg.what) {
  4. case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
  5. ...
  6. ProcessRecord app = (ProcessRecord)msg.obj;
  7. synchronized (ActivityManagerService.this) {
  8. //【见小节4.3.2】
  9. processContentProviderPublishTimedOutLocked(app);
  10. }
  11. } break;
  12. ...
  13. }
  14. ...
  15. }
  16. }
4.3.2 AMS.processContentProviderPublishTimedOutLocked
  1. private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
  2. //[见4.3.3]
  3. cleanupAppInLaunchingProvidersLocked(app, true);
  4. //[见小节4.3.4]
  5. removeProcessLocked(app, false, true, "timeout publishing content providers");
  6. }
4.3.3 AMS.cleanupAppInLaunchingProvidersLocked
  1. boolean cleanupAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
  2. boolean restart = false;
  3. for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
  4. ContentProviderRecord cpr = mLaunchingProviders.get(i);
  5. if (cpr.launchingApp == app) {
  6. if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
  7. restart = true;
  8. } else {
  9. //移除死亡的provider
  10. removeDyingProviderLocked(app, cpr, true);
  11. }
  12. }
  13. }
  14. return restart;
  15. }

removeDyingProviderLocked()的功能跟进程的存活息息相关:详见ContentProvider引用计数 []小节4.5]

  • 对于stable类型的provider(即conn.stableCount > 0),则会杀掉所有跟该provider建立stable连接的非persistent进程.
  • 对于unstable类的provider(即conn.unstableCount > 0),并不会导致client进程被级联所杀.
4.3.4 AMS.removeProcessLocked
  1. private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, String reason) {
  2. final String name = app.processName;
  3. final int uid = app.uid;
  4. //移除mProcessNames中的相应对象
  5. removeProcessNameLocked(name, uid);
  6. if (mHeavyWeightProcess == app) {
  7. mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
  8. mHeavyWeightProcess.userId, 0));
  9. mHeavyWeightProcess = null;
  10. }
  11. boolean needRestart = false;
  12. if (app.pid > 0 && app.pid != MY_PID) {
  13. int pid = app.pid;
  14. synchronized (mPidsSelfLocked) {
  15. mPidsSelfLocked.remove(pid);
  16. mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
  17. }
  18. ...
  19. boolean willRestart = false;
  20. if (app.persistent && !app.isolated) {
  21. if (!callerWillRestart) {
  22. willRestart = true;
  23. } else {
  24. needRestart = true;
  25. }
  26. }
  27. app.kill(reason, true); //杀进程
  28. handleAppDiedLocked(app, willRestart, allowRestart);
  29. if (willRestart) {
  30. removeLruProcessLocked(app);
  31. addAppLocked(app.info, false, null /* ABI override */);
  32. }
  33. } else {
  34. mRemovedProcesses.add(app);
  35. }
  36. return needRestart;
  37. }

五、总结

当出现ANR时,都是调用到AMS.appNotResponding()方法手机信息

Timeout时长
  • 对于前台服务,则超时为SERVICE_TIMEOUT = 20s;
  • 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s
  • 对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;
  • 对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s;
  • ContentProvider超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;
超时检测

Service超时检测机制:

  • 超过一定时间没有执行完相应操作来触发移除延时消息,则会触发anr;

BroadcastReceiver超时检测机制:

  • 有序广播的总执行时间超过 2* receiver个数 * timeout时长,则会触发anr;
  • 有序广播的某一个receiver执行过程超过 timeout时长,则会触发anr;

另外:

  • 对于Service, Broadcast, Input发生ANR之后,最终都会调用AMS.appNotResponding;
  • 对于provider,在其进程启动时publish过程可能会出现ANR, 则会直接杀进程以及清理相应信息,而不会弹出ANR的对话框. appNotRespondingViaProvider()过程会走appNotResponding(), 这个就不介绍了,很少使用,由用户自定义超时时间.
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/989632
推荐阅读
相关标签
  

闽ICP备14008679号