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程序

  1. 被呼叫方法:AMS中的startService()

ActivityManager.getService().startService()

3.2:ActivityThread -→ AMS:service所在程序→system_server程序

  1. 被呼叫方法:AMS中的attachApplication()

ActivityManager.getService().attachApplication()

  1. 拆除炸彈

ActivityManager.getService().serviceDoneExecuting()

3.3: AMS -→ ActivityThread:system_server程序→service所在程序

  1. 被呼叫方法:ApplicationThread中的scheduleCreateService()

app.thread.scheduleCreateService()

  1. 被呼叫方法:ApplicationThread中的scheduleServiceArgs()

app.threadscheduleServiceArgs()

4:總結

基於上述原始碼的分析,我們可以將Service的整體啟動流程總結為下圖:

   

Service啟動流程圖

以上就是Android中Service啟動的大致原理,如果覺得有收穫,歡迎關注點贊~

5:參考

  1. Android原始碼
  2. Android service 啟動篇之 startService
  3. Android 從程序角度看Service啟動流程