前言:之前在(六十四)Android O Service启动流程梳理——startService 梳理了startService的一般流程,anr的没有涉及,本篇就以anr的为关注点梳理下流程。

参考

1. ANR源码分析之Service Timeout

2.(六十四)Android O Service启动流程梳理——startService

1. service anr关键方法

简单来说service调用onCreate或者onStartCommand之前会延迟发送一个timeout消息,延时为20s或者200s,然后执行完了之后会移除掉该timeout消息,如果不能及时移除,则处理timeout消息,导致service anr。

ActiveServices.java

bumpServiceExecutingLocked:发送timeout消息

    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "+ why + " of " + r + " in app " + r.app);else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "+ why + " of " + r.shortName);long now = SystemClock.uptimeMillis();if (r.executeNesting == 0) {r.executeFg = fg;ServiceState stracker = r.getTracker();if (stracker != null) {stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);}if (r.app != null) {r.app.executingServices.add(r);r.app.execServicesFg |= fg;if (r.app.executingServices.size() == 1) {scheduleServiceTimeoutLocked(r.app);}}} else if (r.app != null && fg && !r.app.execServicesFg) {r.app.execServicesFg = true;scheduleServiceTimeoutLocked(r.app);}r.executeFg |= fg;r.executeNesting++;r.executingStart = now;}
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {if (proc.executingServices.size() == 0 || proc.thread == null) {return;}Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);msg.obj = proc;mAm.mHandler.sendMessageDelayed(msg,proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);}

serviceDoneExecutingLocked:移除timeout消息

    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,boolean finishing) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r+ ": nesting=" + r.executeNesting+ ", inDestroying=" + inDestroying + ", app=" + r.app);else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,"<<< DONE EXECUTING " + r.shortName);r.executeNesting--;if (r.executeNesting <= 0) {if (r.app != null) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,"Nesting at 0 of " + r.shortName);r.app.execServicesFg = false;r.app.executingServices.remove(r);if (r.app.executingServices.size() == 0) {if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,"No more executingServices of " + r.shortName);mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);} else if (r.executeFg) {// Need to re-evaluate whether the app still needs to be in the foreground.for (int i=r.app.executingServices.size()-1; i>=0; i--) {if (r.app.executingServices.valueAt(i).executeFg) {r.app.execServicesFg = true;break;}}}if (inDestroying) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,"doneExecuting remove destroying " + r);mDestroyingServices.remove(r);r.bindings.clear();}mAm.updateOomAdjLocked(r.app, true);}r.executeFg = false;if (r.tracker != null) {r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),SystemClock.uptimeMillis());if (finishing) {r.tracker.clearCurrentOwner(r, false);r.tracker = null;}}if (finishing) {if (r.app != null && !r.app.persistent) {r.app.services.remove(r);if (r.whitelistManager) {updateWhitelistManagerLocked(r.app);}}r.app = null;}}}

这个移除timeout消息的方法会判断executeNesting这个值是否小于等于0,也就是说如果onStartCommand多次调用,多个任务加起来的延续时间也必须小于20s/200s,而不是累加的,待写个demo验证下。

2. 流程梳理完善

之前分析流程的时序图如下:

现在加上anr timeout相关的逻辑细化一下。

2.1 onCreate流程

2.1.1 发送timeout

ActiveServices.java

    private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {if (app.thread == null) {throw new RemoteException();}if (DEBUG_MU)Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid+ ", ProcessRecord.uid = " + app.uid);r.app = app;r.restartTime = r.lastActivity = SystemClock.uptimeMillis();final boolean newService = app.services.add(r);bumpServiceExecutingLocked(r, execInFg, "create");bumpServiceExecutingLocked(r, execInFg, "create");
    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "+ why + " of " + r + " in app " + r.app);else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "+ why + " of " + r.shortName);long now = SystemClock.uptimeMillis();if (r.executeNesting == 0) {r.executeFg = fg;ServiceState stracker = r.getTracker();if (stracker != null) {stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);}if (r.app != null) {r.app.executingServices.add(r);r.app.execServicesFg |= fg;if (r.app.executingServices.size() == 1) {scheduleServiceTimeoutLocked(r.app);}}} else if (r.app != null && fg && !r.app.execServicesFg) {r.app.execServicesFg = true;scheduleServiceTimeoutLocked(r.app);}r.executeFg |= fg;r.executeNesting++;r.executingStart = now;}
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {if (proc.executingServices.size() == 0 || proc.thread == null) {return;}Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);msg.obj = proc;mAm.mHandler.sendMessageDelayed(msg,proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);}

2.1.2 移除timeout消息

realStartServiceLocked->scheduleCreateService->handleCreateService->onCreate就不重复梳理了,看onCreate方法。

ActivityThread.java

        private void handleCreateService(CreateServiceData data) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);Service service = null;try {java.lang.ClassLoader cl = packageInfo.getClassLoader();service = (Service) cl.loadClass(data.info.name).newInstance();} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to instantiate service " + data.info.name+ ": " + e.toString(), e);}}try {if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);ContextImpl context = ContextImpl.createAppContext(this, packageInfo);context.setOuterContext(service);Application app = packageInfo.makeApplication(false, mInstrumentation);service.attach(context, this, data.info.name, data.token, app,ActivityManager.getService());service.onCreate();mServices.put(data.token, service);try {ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to create service " + data.info.name+ ": " + e.toString(), e);}}}service.onCreate();mServices.put(data.token, service);try {ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to create service " + data.info.name+ ": " + e.toString(), e);}}}

ActivityManagerService

    public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {synchronized(this) {if (!(token instanceof ServiceRecord)) {Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);throw new IllegalArgumentException("Invalid service token");}mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);}} 

ActiveServices.java

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {boolean inDestroying = mDestroyingServices.contains(r);if (r != null) {if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {// This is a call from a service start...  take care of// book-keeping.r.callStart = true;switch (res) {case Service.START_STICKY_COMPATIBILITY:case Service.START_STICKY: {// We are done with the associated start arguments.r.findDeliveredStart(startId, true);// Don't stop if killed.r.stopIfKilled = false;break;}case Service.START_NOT_STICKY: {// We are done with the associated start arguments.r.findDeliveredStart(startId, true);if (r.getLastStartId() == startId) {// There is no more work, and this service// doesn't want to hang around if killed.r.stopIfKilled = true;}break;}case Service.START_REDELIVER_INTENT: {// We'll keep this item until they explicitly// call stop for it, but keep track of the fact// that it was delivered.ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);if (si != null) {si.deliveryCount = 0;si.doneExecutingCount++;// Don't stop if killed.r.stopIfKilled = true;}break;}case Service.START_TASK_REMOVED_COMPLETE: {// Special processing for onTaskRemoved().  Don't// impact normal onStartCommand() processing.r.findDeliveredStart(startId, true);break;}default:throw new IllegalArgumentException("Unknown service start result: " + res);}if (res == Service.START_STICKY_COMPATIBILITY) {r.callStart = false;}} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {// This is the final call from destroying the service...  we should// actually be getting rid of the service at this point.  Do some// validation of its state, and ensure it will be fully removed.if (!inDestroying) {// Not sure what else to do with this...  if it is not actually in the// destroying list, we don't need to make sure to remove it from it.// If the app is null, then it was probably removed because the process died,// otherwise wtfif (r.app != null) {Slog.w(TAG, "Service done with onDestroy, but not inDestroying: "+ r + ", app=" + r.app);}} else if (r.executeNesting != 1) {Slog.w(TAG, "Service done with onDestroy, but executeNesting="+ r.executeNesting + ": " + r);// Fake it to keep from ANR due to orphaned entry.r.executeNesting = 1;}}final long origId = Binder.clearCallingIdentity();serviceDoneExecutingLocked(r, inDestroying, inDestroying);Binder.restoreCallingIdentity(origId);} else {Slog.w(TAG, "Done executing unknown service from pid "+ Binder.getCallingPid());}}
    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,boolean finishing) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r+ ": nesting=" + r.executeNesting+ ", inDestroying=" + inDestroying + ", app=" + r.app);else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,"<<< DONE EXECUTING " + r.shortName);r.executeNesting--;if (r.executeNesting <= 0) {if (r.app != null) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,"Nesting at 0 of " + r.shortName);r.app.execServicesFg = false;r.app.executingServices.remove(r);if (r.app.executingServices.size() == 0) {if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,"No more executingServices of " + r.shortName);mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);} else if (r.executeFg) {// Need to re-evaluate whether the app still needs to be in the foreground.for (int i=r.app.executingServices.size()-1; i>=0; i--) {if (r.app.executingServices.valueAt(i).executeFg) {r.app.execServicesFg = true;break;}}}if (inDestroying) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,"doneExecuting remove destroying " + r);mDestroyingServices.remove(r);r.bindings.clear();}mAm.updateOomAdjLocked(r.app, true);}r.executeFg = false;if (r.tracker != null) {r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),SystemClock.uptimeMillis());if (finishing) {r.tracker.clearCurrentOwner(r, false);r.tracker = null;}}if (finishing) {if (r.app != null && !r.app.persistent) {r.app.services.remove(r);if (r.whitelistManager) {updateWhitelistManagerLocked(r.app);}}r.app = null;}}}mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);} else if (r.executeFg) {// Need to re-evaluate whether the app still needs to be in the foreground.for (int i=r.app.executingServices.size()-1; i>=0; i--) {if (r.app.executingServices.valueAt(i).executeFg) {r.app.execServicesFg = true;break;}}}if (inDestroying) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,"doneExecuting remove destroying " + r);mDestroyingServices.remove(r);r.bindings.clear();}mAm.updateOomAdjLocked(r.app, true);}r.executeFg = false;if (r.tracker != null) {r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),SystemClock.uptimeMillis());if (finishing) {r.tracker.clearCurrentOwner(r, false);r.tracker = null;}}if (finishing) {if (r.app != null && !r.app.persistent) {r.app.services.remove(r);if (r.whitelistManager) {updateWhitelistManagerLocked(r.app);}}r.app = null;}}}

2.2 onStartCommand流程

流程和onCreate类似,不赘述了。

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {final int N = r.pendingStarts.size();if (N == 0) {return;}ArrayList<ServiceStartArgs> args = new ArrayList<>();while (r.pendingStarts.size() > 0) {ServiceRecord.StartItem si = r.pendingStarts.remove(0);if (DEBUG_SERVICE) {Slog.v(TAG_SERVICE, "Sending arguments to: "+ r + " " + r.intent + " args=" + si.intent);}if (si.intent == null && N > 1) {// If somehow we got a dummy null intent in the middle,// then skip it.  DO NOT skip a null intent when it is// the only one in the list -- this is to support the// onStartCommand(null) case.continue;}si.deliveredTime = SystemClock.uptimeMillis();r.deliveredStarts.add(si);si.deliveryCount++;if (si.neededGrants != null) {mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,si.getUriPermissionsLocked());}mAm.grantEphemeralAccessLocked(r.userId, si.intent,r.appInfo.uid, UserHandle.getAppId(si.callingId));bumpServiceExecutingLocked(r, execInFg, "start");bumpServiceExecutingLocked(r, execInFg, "start");

...

    private void handleServiceArgs(ServiceArgsData data) {Service s = mServices.get(data.token);if (s != null) {try {if (data.args != null) {data.args.setExtrasClassLoader(s.getClassLoader());data.args.prepareToEnterProcess();}int res;if (!data.taskRemoved) {res = s.onStartCommand(data.args, data.flags, data.startId);} else {s.onTaskRemoved(data.args);res = Service.START_TASK_REMOVED_COMPLETE;}QueuedWork.waitToFinish();try {
                    ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}ensureJitEnabled();} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to start service " + s+ " with " + data.args + ": " + e.toString(), e);}}}}res = s.onStartCommand(data.args, data.flags, data.startId);} else {s.onTaskRemoved(data.args);res = Service.START_TASK_REMOVED_COMPLETE;}QueuedWork.waitToFinish();try {
                    ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}ensureJitEnabled();} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to start service " + s+ " with " + data.args + ": " + e.toString(), e);}}}}

2.3 AMS如何处理timeout消息

AMS:

            case SERVICE_TIMEOUT_MSG: {mServices.serviceTimeout((ProcessRecord)msg.obj);}

ActiveServices.java

    void serviceTimeout(ProcessRecord proc) {String anrMessage = null;synchronized(mAm) {if (proc.executingServices.size() == 0 || proc.thread == null) {return;}final long now = SystemClock.uptimeMillis();final long maxTime =  now -(proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);ServiceRecord timeout = null;long nextTime = 0;for (int i=proc.executingServices.size()-1; i>=0; i--) {ServiceRecord sr = proc.executingServices.valueAt(i);if (sr.executingStart < maxTime) {timeout = sr;break;}if (sr.executingStart > nextTime) {nextTime = sr.executingStart;}}if (timeout != null && mAm.mLruProcesses.contains(proc)) {Slog.w(TAG, "Timeout executing service: " + timeout);StringWriter sw = new StringWriter();PrintWriter pw = new FastPrintWriter(sw, false, 1024);pw.println(timeout);timeout.dump(pw, "    ");pw.close();mLastAnrDump = sw.toString();mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);anrMessage = "executing service " + timeout.shortName;} else {Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);msg.obj = proc;mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));}}if (anrMessage != null) {mAm.mAppErrors.appNotResponding(proc, null, null, false, anrMessage);}}

AppErrors

   final void appNotResponding(ProcessRecord app, ActivityRecord activity,ActivityRecord parent, boolean aboveSystem, final String annotation) {ArrayList<Integer> firstPids = new ArrayList<Integer>(5);SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);if (mService.mController != null) {try {// 0 == continue, -1 = kill process immediatelyint res = mService.mController.appEarlyNotResponding(app.processName, app.pid, annotation);if (res < 0 && app.pid != MY_PID) {app.kill("anr", true);}} catch (RemoteException e) {mService.mController = null;Watchdog.getInstance().setActivityController(null);}}long anrTime = SystemClock.uptimeMillis();if (ActivityManagerService.MONITOR_CPU_USAGE) {mService.updateCpuStatsNow();}// Unless configured otherwise, swallow ANRs in background processes & kill the process.boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;boolean isSilentANR;synchronized (mService) {// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.if (mService.mShuttingDown) {Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);return;} else if (app.notResponding) {Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);return;} else if (app.crashing) {Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);return;} else if (app.killedByAm) {Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);return;} else if (app.killed) {Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);return;}// In case we come through here for the same app before completing// this one, mark as anring now so we will bail out.app.notResponding = true;// Log the ANR to the event log.EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,app.processName, app.info.flags, annotation);// Dump thread traces as quickly as we can, starting with "interesting" processes.firstPids.add(app.pid);// Don't dump other PIDs if it's a background ANRisSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);if (!isSilentANR) {int parentPid = app.pid;if (parent != null && parent.app != null && parent.app.pid > 0) {parentPid = parent.app.pid;}if (parentPid != app.pid) firstPids.add(parentPid);if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {ProcessRecord r = mService.mLruProcesses.get(i);if (r != null && r.thread != null) {int pid = r.pid;if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {if (r.persistent) {firstPids.add(pid);if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);} else if (r.treatLikeActivity) {firstPids.add(pid);if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);} else {lastPids.put(pid, Boolean.TRUE);if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);}}}}}}// Log the ANR to the main log.StringBuilder info = new StringBuilder();info.setLength(0);info.append("ANR in ").append(app.processName);if (activity != null && activity.shortComponentName != null) {info.append(" (").append(activity.shortComponentName).append(")");}info.append("\n");info.append("PID: ").append(app.pid).append("\n");if (annotation != null) {info.append("Reason: ").append(annotation).append("\n");}if (parent != null && parent != activity) {info.append("Parent: ").append(parent.shortComponentName).append("\n");}ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);// don't dump native PIDs for background ANRs unless it is the process of interestString[] nativeProcs = null;if (isSilentANR) {for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {nativeProcs = new String[] { app.processName };break;}}} else {nativeProcs = NATIVE_STACKS_OF_INTEREST;}int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);ArrayList<Integer> nativePids = null;if (pids != null) {nativePids = new ArrayList<Integer>(pids.length);for (int i : pids) {nativePids.add(i);}}// For background ANRs, don't pass the ProcessCpuTracker to// avoid spending 1/2 second collecting stats to rank lastPids.File tracesFile = ActivityManagerService.dumpStackTraces(true, firstPids,(isSilentANR) ? null : processCpuTracker,(isSilentANR) ? null : lastPids,nativePids);String cpuInfo = null;if (ActivityManagerService.MONITOR_CPU_USAGE) {mService.updateCpuStatsNow();synchronized (mService.mProcessCpuTracker) {cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);}info.append(processCpuTracker.printCurrentLoad());info.append(cpuInfo);}info.append(processCpuTracker.printCurrentState(anrTime));Slog.e(TAG, info.toString());if (tracesFile == null) {// There is no trace file, so dump (only) the alleged culprit's threads to the logProcess.sendSignal(app.pid, Process.SIGNAL_QUIT);}mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,cpuInfo, tracesFile, null);if (mService.mController != null) {try {// 0 == show dialog, 1 = keep waiting, -1 = kill process immediatelyint res = mService.mController.appNotResponding(app.processName, app.pid, info.toString());if (res != 0) {if (res < 0 && app.pid != MY_PID) {app.kill("anr", true);} else {synchronized (mService) {mService.mServices.scheduleServiceTimeoutLocked(app);}}return;}} catch (RemoteException e) {mService.mController = null;Watchdog.getInstance().setActivityController(null);}}synchronized (mService) {mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);if (isSilentANR) {app.kill("bg anr", true);return;}// Set the app's notResponding state, and look up the errorReportReceivermakeAppNotRespondingLocked(app,activity != null ? activity.shortComponentName : null,annotation != null ? "ANR " + annotation : "ANR",info.toString());// Bring up the infamous App Not Responding dialogMessage msg = Message.obtain();HashMap<String, Object> map = new HashMap<String, Object>();msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;msg.obj = map;msg.arg1 = aboveSystem ? 1 : 0;map.put("app", app);if (activity != null) {map.put("activity", activity);}mService.mUiHandler.sendMessage(msg);}}info.append("ANR in ").append(app.processName);if (activity != null && activity.shortComponentName != null) {info.append(" (").append(activity.shortComponentName).append(")");}info.append("\n");info.append("PID: ").append(app.pid).append("\n");if (annotation != null) {info.append("Reason: ").append(annotation).append("\n");}if (parent != null && parent != activity) {info.append("Parent: ").append(parent.shortComponentName).append("\n");}ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);// don't dump native PIDs for background ANRs unless it is the process of interestString[] nativeProcs = null;if (isSilentANR) {for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {nativeProcs = new String[] { app.processName };break;}}} else {nativeProcs = NATIVE_STACKS_OF_INTEREST;}int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);ArrayList<Integer> nativePids = null;if (pids != null) {nativePids = new ArrayList<Integer>(pids.length);for (int i : pids) {nativePids.add(i);}}// For background ANRs, don't pass the ProcessCpuTracker to// avoid spending 1/2 second collecting stats to rank lastPids.File tracesFile = ActivityManagerService.dumpStackTraces(true, firstPids,(isSilentANR) ? null : processCpuTracker,(isSilentANR) ? null : lastPids,nativePids);String cpuInfo = null;if (ActivityManagerService.MONITOR_CPU_USAGE) {mService.updateCpuStatsNow();synchronized (mService.mProcessCpuTracker) {cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);}info.append(processCpuTracker.printCurrentLoad());info.append(cpuInfo);}info.append(processCpuTracker.printCurrentState(anrTime));Slog.e(TAG, info.toString());if (tracesFile == null) {// There is no trace file, so dump (only) the alleged culprit's threads to the logProcess.sendSignal(app.pid, Process.SIGNAL_QUIT);}mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,cpuInfo, tracesFile, null);if (mService.mController != null) {try {// 0 == show dialog, 1 = keep waiting, -1 = kill process immediatelyint res = mService.mController.appNotResponding(app.processName, app.pid, info.toString());if (res != 0) {if (res < 0 && app.pid != MY_PID) {app.kill("anr", true);} else {synchronized (mService) {mService.mServices.scheduleServiceTimeoutLocked(app);}}return;}} catch (RemoteException e) {mService.mController = null;Watchdog.getInstance().setActivityController(null);}}synchronized (mService) {mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);if (isSilentANR) {app.kill("bg anr", true);return;}// Set the app's notResponding state, and look up the errorReportReceivermakeAppNotRespondingLocked(app,activity != null ? activity.shortComponentName : null,annotation != null ? "ANR " + annotation : "ANR",info.toString());// Bring up the infamous App Not Responding dialogMessage msg = Message.obtain();HashMap<String, Object> map = new HashMap<String, Object>();msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;msg.obj = map;msg.arg1 = aboveSystem ? 1 : 0;map.put("app", app);if (activity != null) {map.put("activity", activity);}mService.mUiHandler.sendMessage(msg);}}

(六十五)Android O StartService的 anr timeout 流程分析相关推荐

  1. 六十五、Spark-综合案例(搜狗搜索日志分析)

    搜狗实验室:搜索引擎查询日志库设计为包括约1个月(2008年6月)Sogou搜索引擎部分网页查询需求及用户点击情况的网页查询日志数据集合.为进行中文搜索引擎用户行为分析的研究者提供基准研究语料 目录 ...

  2. 六十五、Leetcode数组系列(上篇)

    @Author:Runsen @Date:2020/6/5 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

  3. 六十五年来,他的祖国向他道歉了三次

    △ "人工智能之父"艾伦 · 麦席森 · 图灵 (Alan Mathison Turing,1912-1954) 2021年6月23日是英国科学家."人工智能之父&quo ...

  4. JavaScript学习(六十五)—数组知识点总结

    JavaScript学习(六十五)-数组 学习内容 一.什么是数组 二.数组的分类 三.数组的创建方式 四.数组元素 五.数组的操作 六.数组元素遍历的四种方法 七.随机数为数组赋值 八.数组的比较 ...

  5. 信息系统项目管理师核心考点(六十五)信息安全基础知识网络安全

    科科过为您带来软考信息系统项目管理师核心重点考点(六十五)信息安全基础知识网络安全,内含思维导图+真题 [信息系统项目管理师核心考点]信息安全基础知识网络安全 1.拒绝服务攻击(Dos) 一种利用合理 ...

  6. C语言/C++常见习题问答集锦(六十五) 之彩票幸运星

    C语言/C++常见习题问答集锦(六十五) 之彩票幸运星 程序之美 1.L1-062 幸运彩票 (15 分) 彩票的号码有 6 位数字,若一张彩票的前 3 位上的数之和等于后 3 位上的数之和,则称这张 ...

  7. Android 源码 Camera2 预览流程分析四

    <Android 源码 Camera2 预览流程分析二>中进行了流启动,这是调用 QCamera3Channel start() 方法实现的,对应于 HAL_PIXEL_FORMAT_YC ...

  8. 问题六十五:二叉查找树的一个应用实例——求解一元十次方程时单实根区间的划分

    65.1 概述 回忆一下: "问题五十九:怎么求一元六次方程在区间内的所有不相等的实根"和"问题六十二:怎么求一元十次方程在区间内的所有不相等的实根"中求一元六 ...

  9. 如何选择适合你的兴趣爱好(六十五),文学

    围城网的摇摇今天给大家带来了"如何选择适合你的兴趣爱好"系列专辑的第六十五讲--文学. 文学是语言文字的艺术,包括小说.诗歌.散文等.相信我们经常看小说的朋友对唐家三少肯定不陌生吧 ...

最新文章

  1. windos10下编译opencv_4.0.1+opencv-contrib_4.0.1
  2. 理解Asp.Net自定义控件的生命周期
  3. Postman系列之发送不同HTTP类型请求
  4. ubuntu + usb转RS232驱动
  5. 合成PDF(多文件变一文件、多页变一页)
  6. 逆向-IDA工具的基本使用
  7. 数据结构与算法(一):时间复杂度和空间复杂度
  8. 高校大数据教学实训平台以及实验室建设解决方案-美林数据
  9. 数字转人民币大写(SQL SERVER)
  10. java 点击叉号_怎么设置点击叉号然后内容消失,这是自己写的不知道哪里有问题?...
  11. 网页上打印PDF文件
  12. 9x07-usb state拔出usb线后状态仍为CONFIGURED,影响休眠(已解决)
  13. win2008服务器系统升级,Windows Server 安装和升级
  14. linux下安装blas和lapack
  15. pytorch tensor求向量的模长
  16. 怎样解决南北互通的难题?
  17. 前端学习--js.2
  18. AcWing 188. 武士风度的牛(BFS,C++)
  19. 数据结构与算法python语言实现答案_数据结构与算法:Python语言实现 源代码 PPT 练习答案 源码.zip...
  20. 【git系列】从远端仓库获取最新代码合并到本地分支里

热门文章

  1. java版我的世界附魔指令_我的世界手机版附魔指令 怎么使用附魔指令大全
  2. this关键字的四种用法
  3. 重新安装Windows应用商店
  4. 第八章-数据处理的两个基本问题
  5. phpstorm License Server激活 官网下载版本直接激活
  6. 2021秋招IC验证面经-华为/英伟达/兆易创新/ZeKu
  7. reco-fetch
  8. Deepin安装python3
  9. linux启动菜单ubuntu,在Ubuntu上用BURG来美化开机选择菜单
  10. 【AP/AR】借项通知单和贷项通知单的区别