android中service的兩種實現方法(android中service的實現方法)
1:前言
Service是Android中的四大元件之一,日常開發中我們經常會使用startService之類的方法來啟動Service,那這個方法呼叫的底層原理是什麼呢?Android系統是如何啟動起來Service的呢?本文我們從原始碼出發,介紹一下Android中的Service是如何啟動Service的,本文的結構如下:
2:原始碼分析
2.1:ContextImpl.startService&startForegroundService:應用層呼叫的入口
我們呼叫
startService/startForegroundService之後,會呼叫到android.app.ContextImpl#
startService/startForegroundService:
class ContextImpl extends Context { @Override public ComponentName startService(Intent service) { return startServiceCommon(service, false, mUser); } @Override public ComponentName startForegroundService(Intent service) { return startServiceCommon(service, true, mUser); } private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { ... } }
可以看到,startService和startForegroundService最終呼叫的都是startServiceCommon這個方法,唯一不同的是第二個引數requireForeground的值不一樣,用來標識當前Service是否是前臺Serivice,我們來看startServiceCommon的具體實現:
class ContextImpl extends Context { private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( "Not allowed to start service " service " without permission " cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { throw new SecurityException( "Unable to start service " service ": " cn.getClassName()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " service ": " cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
可以看到,核心是呼叫到了
ActivityManager.getService().startService()方法進行Service的啟動,即AMS中,我們來看一下AMS中是如何啟動Service的.
2.2:ActivityManagerService.startService:執行前置判斷,滿足啟動service的條件的話觸發真正startService的邏輯
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public class ActivityManagerService extends IActivityManager.Stub{ final ActiveServices mServices; @Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, String callingFeatureId, int userId) throws TransactionTooLargeException { ... synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } } }
可以看到,最終呼叫到了
ActiveServices.startServiceLocked()中:
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java public final class ActiveServices { ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, callingPackage, callingFeatureId, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { /** *對當前Service的啟動進行判斷,看下Service啟動的限制(比如許可權、前後臺等是否滿足) **/ ... //啟動Service ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); if (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid, callingUid, service, r, allowBackgroundActivityStarts); } return cmp; } ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); ... return r.name; } }
核心是呼叫到了
ActiveServices.bringUpServiceLocked.
2.3:ActiveServices.bringUpServiceLocked:根據程序&執行緒是否存在執行不同操作
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java public final class ActiveServices { private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { //如果程序和執行緒已經不為空,說明該Service已經create了,直接呼叫sendServiceArgsLocked if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); return null; } ... final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; HostingRecord hostingRecord = new HostingRecord("service", r.instanceName); ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); //如果程序已經在了,呼叫realStartServiceLocked進行start service if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " r.shortInstanceName, e); } // If a dead object exception was thrown -- fall through to // restart the application. } } // 如果程序還沒啟動,呼叫mAm.startProcessLocked啟動程序 if (app == null && !permissionsReviewRequired) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) { //埋下異常 bringDownServiceLocked(r); ... } } //將當前ServiceRecord加到mPendingServices裡, if (!mPendingServices.contains(r)) { mPendingServices.add(r); } ... } }
在《Android的程序》一文中我們介紹過,最終程序起來之後會執行
ActivityManagerService.attachApplication-->
ActivityManagerService.attachApplicationLocked:
public class ActivityManagerService extends IActivityManager.Stub{ public ActivityTaskManagerInternal mAtmInternal; final ActiveServices mServices; private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { boolean badApp = false; boolean didSomething = false; // 先嚐試啟動Activity if (normalMode) { try { didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " app, e); badApp = true; } } //Activity啟動沒問題,嘗試啟動Service if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " app, e); badApp = true; } } } }
可以看到,先啟動了Activity,如果Activity的啟動過程中沒有出錯,就啟動Service即呼叫
ActiveServices.attachApplicationLocked.
2.4:ActiveServices.attachApplicationLocked:程序啟動完成,繼續啟動service
public final class ActiveServices { boolean attachApplicationLocked(ProcessRecord proc, String processName){ boolean didSomething = false; // Collect any services that are waiting for this process to come up. if (mPendingServices.size() > 0) { ServiceRecord sr = null; try { for (int i=0; i<mPendingServices.size(); i ) { sr = mPendingServices.get(i); if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } mPendingServices.remove(i); i--; proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode, mAm.mProcessStats); //核心操作是呼叫realStartServiceLocked realStartServiceLocked(sr, proc, sr.createdFromFg); didSomething = true; if (!isServiceNeededLocked(sr, false, false)) { // We were waiting for this service to start, but it is actually no // longer needed. This could happen because bringDownServiceIfNeeded // won't bring down a service that is pending... so now the pending // is done, so let's drop it. bringDownServiceLocked(sr); } } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting service " sr.shortInstanceName, e); throw e; } } // Also, if there are any services that are waiting to restart and // would run in this process, now is a good time to start them. It would // be weird to bring up the process but arbitrarily not let the services // run at this point just because their restart time hasn't come up. if (mRestartingServices.size() >0) { ServiceRecord sr; for (int i=0; i<mRestartingServices.size(); i ) { sr = mRestartingServices.get(i); if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } mAm.mHandler.removeCallbacks(sr.restarter); mAm.mHandler.post(sr.restarter); } } return didSomething; } }
可以看到最終呼叫到了realStartServiceLocked.
2.5:ActiveServices.realStartServiceLocked:先埋炸彈,然後觸發service啟動
public final class ActiveServices { /** * Note the name of this method should not be confused with the started services concept. * The "start" here means bring up the instance in the client, and this method is called * from bindService() as well. */ 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.setProcess(app); r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); //呼叫ProcessRecord.startService,實質是將此處的ServiceRecord add到ProcessRecord.mServices中 final boolean newService = app.startService(r); //埋下ANR炸彈 bumpServiceExecutingLocked(r, execInFg, "create"); //調整程序的優先順序 mAm.updateLruProcessLocked(app, false, null); updateServiceForegroundLocked(r.app, /* oomAdj= */ false); mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); boolean created = false; ... //最終觸發service.onCreate app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); ... //bind service requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); if (newService && created) { app.addBoundClientUidsOfNewService(r); } // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null, 0)); } //拉起timeout,最終呼叫Service.onStartCommand sendServiceArgsLocked(r, execInFg, true); if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " r); getServiceMapLocked(r.userId).mDelayedStartList.remove(r); r.delayed = false; } if (r.delayedStop) { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (from start): " r); stopServiceLocked(r); } } }
2.6:ActiveServices.bumpServiceExecutingLocked:埋下ANR炸彈(SERVICE_TIMEOUT_MSG)
public final class ActiveServices { // How long we wait for a service to finish executing. static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // How long the startForegroundService() grace period is to get around to // calling startForeground() before we ANR stop it. static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) { 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) { //啟動延遲炸彈(觸發ANR) 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; } 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; //前臺Service延遲SERVICE_TIMEOUT(20s),後臺Service延遲SERVICE_BACKGROUND_TIMEOUT(200s) mAm.mHandler.sendMessageDelayed(msg, proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT); } }
2.7:ActivityThread.scheduleCreateService:觸發Service.onCreate
可以看到這裡主要是傳送了一個CREATE_SERVICE的Message訊息:
//frameworks/base/core/java/android/app/ActivityThread.java public final class ActivityThread extends ClientTransactionHandler 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); } public void handleMessage(Message msg) { ... case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break; ... } public static final int SERVICE_DONE_EXECUTING_ANON = 0; @UnsupportedAppUsage private void handleCreateService(CreateServiceData data) { LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { ContextImpl context = ContextImpl.createAppContext(this, packageInfo); Application app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); //例項化Service的物件 service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); // Service resources must be initialized with the same loaders as the application // context. context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); context.setOuterContext(service); //呼叫Service.attach service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //呼叫Service.onCreate service.onCreate(); mServices.put(data.token, service); //通知ActivityManagerService,Service啟動完成,拆除預埋的炸彈,調整程序優先順序 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (Exception e) { } } } //frameworks/base/core/java/android/app/AppComponentFactory.java class AppComponentFactory{ public @NonNull Service instantiateService(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Service) cl.loadClass(className).newInstance(); } }
2.8:ActivityManagerService.serviceDoneExecuting:拆除預埋的炸彈
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public class ActivityManagerService extends IActivityManager.Stub{ final ActiveServices mServices; 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.serviceDoneExecutingLocked:
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java public final class ActiveServices { void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) { if (r != null) { ... serviceDoneExecutingLocked(r, inDestroying, inDestroying); } } private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying, boolean finishing) { //拆除預埋的SERVICE_TIMEOUT_MSG炸彈 mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); //調整程序優先順序 mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); } }
2.9:ActiveServices.sendServiceArgsLocked:啟動延遲任務,埋下ANR和崩潰炸彈、觸發onstartCommand
public final class ActiveServices { final ActivityManagerService mAm; private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException { final int N = r.pendingStarts.size(); if (N == 0) { return; } ArrayListargs = new ArrayList<>(); while (r.pendingStarts.size() > 0) { ServiceRecord.StartItem si = r.pendingStarts.remove(0); //核心操作,埋下ANR炸彈,上面介紹過了 bumpServiceExecutingLocked(r, execInFg, "start"); if (!oomAdjusted) { oomAdjusted = true; //更新程序優先順序 mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); } if (r.fgRequired && !r.fgWaiting) { if (!r.isForeground) { //對於前臺Service,啟動延遲任務,檢測Service呼叫了startForeground,否則會崩潰 scheduleServiceForegroundTransitionTimeoutLocked(r); } else { r.fgRequired = false; } } int flags = 0; if (si.deliveryCount > 1) { flags |= Service.START_FLAG_RETRY; } if (si.doneExecutingCount > 0) { flags |= Service.START_FLAG_REDELIVERY; } args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent)); } ParceledListSliceslice = new ParceledListSlice<>(args); slice.setInlineCountLimit(4); Exception caughtException = null; try { //呼叫ActivityThread.scheduleServiceArgs,最終執行Service.onstartCommand r.app.thread.scheduleServiceArgs(r, slice); } } // How long the startForegroundService() grace period is to get around to // calling startForeground() before we ANR stop it. static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) { if (r.app.executingServices.size() == 0 || r.app.thread == null) { return; } Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG); msg.obj = r; r.fgWaiting = true; //延遲10s傳送,埋下崩潰炸彈 mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT); } }
2.10:ActivityThread.scheduleServiceArgs:觸發onStartcommand
//frameworks/base/core/java/android/app/ActivityThread.java public final class ActivityThread extends ClientTransactionHandler public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) { Listlist = args.getList(); for (int i = 0; i < list.size(); i ) { ServiceStartArgs ssa = list.get(i); ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = ssa.taskRemoved; s.startId = ssa.startId; s.flags = ssa.flags; s.args = ssa.args; sendMessage(H.SERVICE_ARGS, s); } } public void handleMessage(Message msg) { ... case SERVICE_ARGS: handleServiceArgs((ServiceArgsData)msg.obj); break; ... } private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); ... //呼叫onStartcommand res = s.onStartCommand(data.args, data.flags, data.startId); //拆除預埋的炸彈 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); ... } }
核心是傳送了一個SERVICE_ARGS的message。
2.11:ActivityManagerService.handleMessage:處理不同的message(炸彈)
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public class ActivityManagerService extends IActivityManager.Stub{ final MainHandler mHandler; final ActiveServices mServices; final class MainHandler extends Handler { public MainHandler(Looper looper) { super(looper, null, true); } @Override public void handleMessage(Message msg) { switch (msg.what) { case SERVICE_TIMEOUT_MSG: { //丟擲anr mServices.serviceTimeout((ProcessRecord)msg.obj); } break; case SERVICE_FOREGROUND_TIMEOUT_MSG: { //丟擲anr mServices.serviceForegroundTimeout((ServiceRecord)msg.obj); } break; case SERVICE_FOREGROUND_CRASH_MSG: { //引發crash,報錯Context.startForegroundService() did not then call Service.startForeground() xxx mServices.serviceForegroundCrash( (ProcessRecord) msg.obj, msg.getData().getCharSequence(SERVICE_RECORD_KEY)); } break; } } } }
2.12:Service.startFroeground:前臺Service必須呼叫,展示通知,解除崩潰炸彈
對於前臺Service,必須在Service啟動之後手動呼叫Service.startFroeground,否則會觸發上文中的崩潰炸彈:
//frameworks/base/core/java/android/app/Service.java public abstract class Service extends ContextWrapper { public final void startForeground(int id, Notification notification) { try { mActivityManager.setServiceForeground( new ComponentName(this, mClassName), mToken, id, notification, 0, FOREGROUND_SERVICE_TYPE_MANIFEST); } catch (RemoteException ex) { } } }
最終呼叫到了AMS.setServiceForeground:
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public class ActivityManagerService extends IActivityManager.Stub{ final ActiveServices mServices; @Override public void setServiceForeground(ComponentName className, IBinder token, int id, Notification notification, int flags, int foregroundServiceType) { synchronized(this) { mServices.setServiceForegroundLocked(className, token, id, notification, flags, foregroundServiceType); } } }
核心是呼叫
ActiveServices.setServiceForegroundLocked.
2.13:ActiveServices.setServiceForegroundLocked:傳送通知,取消崩潰
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java public final class ActiveServices { public void setServiceForegroundLocked(ComponentName className, IBinder token, int id, Notification notification, int flags, int foregroundServiceType) { final int userId = UserHandle.getCallingUserId(); final long origId = Binder.clearCallingIdentity(); try { ServiceRecord r = findServiceLocked(className, token, userId); if (r != null) { setServiceForegroundInnerLocked(r, id, notification, flags, foregroundServiceType); } } finally { Binder.restoreCallingIdentity(origId); } } /** * @param id Notification ID. Zero === exit foreground state for the given service. */ private void setServiceForegroundInnerLocked(final ServiceRecord r, int id, Notification notification, int flags, int foregroundServiceType) { //id不可為0 if (id != 0) { //notification不可為空 if (notification == null) { throw new IllegalArgumentException("null notification"); } ... if (r.fgRequired) { if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) { Slog.i(TAG, "Service called startForeground() as required: " r); } r.fgRequired = false; r.fgWaiting = false; alreadyStartedOp = stopProcStatsOp = true; //移除SERVICE_FOREGROUND_TIMEOUT_MSG訊息,取消崩潰 mAm.mHandler.removeMessages( ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r); } } } }
3:整個Service啟動過程中涉及到的跨程序呼叫
3.1:ContextImpl -→ AMS:呼叫方程序→system_server程序
- 被呼叫方法:AMS中的startService()
ActivityManager.getService().startService()
3.2:ActivityThread -→ AMS:service所在程序→system_server程序
- 被呼叫方法:AMS中的attachApplication()
ActivityManager.getService().attachApplication()
- 拆除炸彈
ActivityManager.getService().serviceDoneExecuting()
3.3: AMS -→ ActivityThread:system_server程序→service所在程序
- 被呼叫方法:ApplicationThread中的scheduleCreateService()
app.thread.scheduleCreateService()
- 被呼叫方法:ApplicationThread中的scheduleServiceArgs()
app.threadscheduleServiceArgs()
4:總結
基於上述原始碼的分析,我們可以將Service的整體啟動流程總結為下圖:
Service啟動流程圖
以上就是Android中Service啟動的大致原理,如果覺得有收穫,歡迎關注點贊~