Android中ANR的触发机制-Service篇 (2)

这个方法里调用realStartServiceLocked方法:

//ActiveServices private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //... bumpServiceExecutingLocked(r, execInFg, "create"); //... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); //... }

这里先调用了bumpServiceExecutingLocked方法用来设置超时消息:

//ActiveServices 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); // For b/34123235: Services within the system server won\'t start until SystemServer // does Looper.loop(), so we shouldn\'t try to start/bind to them too early in the boot // process. However, since there\'s a little point of showing the ANR dialog in that case, // let\'s suppress the timeout until PHASE_THIRD_PARTY_APPS_CAN_START. // // (Note there are multiple services start at PHASE_THIRD_PARTY_APPS_CAN_START too, // which technically could also trigger this timeout if there\'s a system server // that takes a long time to handle PHASE_THIRD_PARTY_APPS_CAN_START, but that shouldn\'t // happen.) boolean timeoutNeeded = true; if ((mAm.mBootPhase < SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) && (r.app != null) && (r.app.pid == android.os.Process.myPid())) { Slog.w(TAG, "Too early to start/bind service in system_server: Phase=" + mAm.mBootPhase + " " + r.getComponentName()); timeoutNeeded = false; } 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 (timeoutNeeded && r.app.executingServices.size() == 1) { scheduleServiceTimeoutLocked(r.app); } } } else if (r.app != null && fg && !r.app.execServicesFg) { r.app.execServicesFg = true; if (timeoutNeeded) { scheduleServiceTimeoutLocked(r.app); } } r.executeFg |= fg; r.executeNesting++; r.executingStart = now; }

这个方法中调用scheduleServiceTimeoutLocked方法:

//ActiveServices 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); }

调用ActivityManagerService的MainHandler发送一个SERVICE_TIMEOUT消息,这里具体根据是否为前台消息发送的消息不同。

前台服务超时时间:20s,后台服务超时时间:200s

// How long we wait for a service to finish executing. static final int SERVICE_TIMEOUT = 20*1000; // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

设置超时消息就先看到这里,接着看启动Service

调用ProcessRecord中的IApplicationThread类型的thread属性的scheduleCreateService方法,即调用到了ActivityThread的内部类ApplicationThread的scheduleCreateService方法:

//ActivityThread$ApplicationThrad public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }

这个方法里调用了ActivityThread的sendMessage方法:

//ActivityThread void sendMessage(int what, Object obj) { sendMessage(what, obj, 0, 0, false); }

最终通过Handler发送了一个消息出去

//Handler private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }

在mH的handleMessage中回调处理:

//ActivityThread$H.handleMessage case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; //ActivityThread 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 = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); } 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方法 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); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgggzd.html