文章目錄
回顧
Activity啓動系列總結:
Activity啓動流程總結-ActivityThread
Activity啓動流程總結-生命週期
Activity啓動流程總結-超時判定機制
在Activity啓動流程中對APP進程和ActivityManagerService的交互過程以及應用進程啓動初始化過程做了簡單總結。Service作爲四大組件之一,它的啓動過程大體相似。
概述
在開發中我們使用context.startService(intent)和context.stopService(intent)來啓動和停止Service,Service的啓動和停止也是由ActivityManagerService來進行調度,本文通過跟蹤源碼來看看它的啓動和停止過程。
源碼探究
文中源碼基於 Android 10.0
startService過程
當執行context.startService(intent),將開始Service的啓動過程:
[ContextImpl#startService]
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
public ComponentName startForegroundService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, true, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
// ···
// 請求AMS啓動Service
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
if (cn != null) {
// 省略檢查異常部分 ···
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
可以看到通過IActivityManager調用ActivityManagerService進行startService。
接下來從APP進程來到ActivityManagerService:
[ActivityManagerService#startService]
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
// 省略參數異常檢查 ···
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
// mServices實例是ActiveServices
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
該方法中調用ActiveServices的startServiceLocked方法進一步處理。
ActiveServices的startServiceLocked方法中又調用了另一個重載方法:
[ActiveServices#startServiceLocked]
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
final int userId, boolean allowBackgroundActivityStarts)
throws TransactionTooLargeException {
// 省略變量callerFg部分(用於標記調用方進程是否屬於前臺)···
// 查找或新建可用ServiceRecord
ServiceLookupResult res =
retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
// 省略對res結果檢查部分 ···
ServiceRecord r = res.record;
// 省略後臺啓動檢查和啓動權限檢查部分 ···
// 創建startCommand參數添加到pendingStarts集合中保存
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants, callingUid));
// 調用startServiceInnerLocked進一步處理
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
這裏獲取一個ServiceRecord(被包裝在ServiceLookupResult中),ServiceRecord用於保存Service信息,一個ServiceRecord對應一個運行Service。然後調用startServiceInnerLocked方法進一步執行啓動流程。
retrieveServiceLocked方法中,首先獲取userId對應的ServiceMap緩存集合,根據ComponentName(顯式意圖)或IntentFilter(隱式意圖)查找ServiceRecord。不存在的話,則從PackageManagerService查找匹配的ServiceInfo,之後創建ServiceRecord並保存在集合中。在返回結果前還會判斷是否允許不同應用和不同userId間的調用和啓動權限檢查。
接下來進入startServiceInnerLocked方法:
[ActiveServices#startServiceInnerLocked]
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
// ···
// 進一步執行啓動
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
// 省略添加後臺啓動服務集合和啓動前臺服務判斷部分 ···
return r.name;
}
進入bringUpServiceLocked方法:
[ActiveServices#bringUpServiceLocked]
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// 判斷目標Service是否已啓動,首次將要啓動時ServiceRecord中還未設置IApplicationThread
if (r.app != null && r.app.thread != null) {
// 調度應用進程觸發onStartCommand回調
sendServiceArgsLocked(r, execInFg, false);
return null;
}
// 判斷目標Service是否等待重啓
if (!whileRestarting && mRestartingServices.contains(r)) {
// If waiting for a restart, then do nothing.
return null;
}
// ···
// 重置目標Service的延遲啓動標識 ···
// 檢查目標Service的userId對應用戶是否已啓動 ···
// ···
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) {
// 查找對應進程的ProcessRecord
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
// 通過ProcessRecord的的IApplicationThread判斷進程是否啓動
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.
}
} else {
// 省略ISOLATED PROCESS SERVICE部分 ···
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
// 省略啓動進程部分,會調用mAm.startProcessLocked方法 ···
}
// ···
// 將ServiceRecord添加至待啓動集合緩存,等待進場啓動後再執行啓動流程
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
// 省略延遲啓動但是Service又被要求停止,會調用stopServiceLocked方法 ···
return null;
}
該方法中首先判斷目標Service是否已啓動,如果已經啓動則會調度onStartCommand回調。接着判斷目標Service所屬進程是否啓動,如果已經啓動則進一步執行Service啓動流程,否則將ServiceRecord添加到待啓動集合,等待目標進程啓動完成後再執行啓動流程。
PS:這裏通過ProcessRecord是否持有IApplicationThread來判斷目標Service和目標進程是否啓動。當目標Service啓動後,會爲對應ServiceRecord設置ProcessRecord和IApplicationThread。當目標進程啓動後,會爲對應ProcessRecord設置IApplicationThread。可參考《Activity啓動流程總結-ActivityThread》。
接下來進入關鍵方法realStartServiceLocked:
[ActiveServices#realStartServiceLocked]
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
// ···
// 這裏給ServiceRecord設置了ProcessRecord,便可通過ServiceRecord判斷目標Service是否已啓動
r.setProcess(app);
// ···
// ProcessRecord的services集合保存對應進程中所有運行的Service信息
final boolean newService = app.services.add(r);
// 超時設置相關
bumpServiceExecutingLocked(r, execInFg, "create");
// ···
boolean created = false;
try {
// 調度應用進程啓動Service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
// 前臺Service前臺通知相關
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// 省略Service啓動失敗異常處理部分 ···
}
}
// ···
// 省略bind Service相關流程部分 ···
// ···
// 發送參數到應用進程,將觸發onStartCommand回調
sendServiceArgsLocked(r, execInFg, true);
// ···
}
這裏會先後兩次調度應用進程,應用側會先後往應用主進程消息隊列添加兩條任務消息,AMS側繼續往下執行它的其餘邏輯,下面需要到應用側看創建Service的過程。
在看create Service流程前,先看看sendServiceArgsLocked方法:
[ActiveServices#sendServiceArgsLocked]
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
// pendingStarts保存待派發執行startCommand的命令參數
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
ArrayList<ServiceStartArgs> args = new ArrayList<>();
while (r.pendingStarts.size() > 0) {
// 封裝參數保存在args中 ···
}
// ParceledListSlice用於跨IPC傳輸大量Parcelable對象,可拆分爲多個binder_transact事務傳輸。
ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4);
Exception caughtException = null;
try {
// 調度應用進程執行onStartCommand回調
r.app.thread.scheduleServiceArgs(r, slice);
} catch (TransactionTooLargeException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()
+ " args, first: " + args.get(0).args);
Slog.w(TAG, "Failed delivering service starts", e);
caughtException = e;
} catch (RemoteException e) {
// Remote process gone... we'll let the normal cleanup take care of this.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
Slog.w(TAG, "Failed delivering service starts", e);
caughtException = e;
} catch (Exception e) {
Slog.w(TAG, "Unexpected exception", e);
caughtException = e;
}
if (caughtException != null) {
// Keep nesting count correct
// 省略異常處理部分 ···
}
}
該方法中進行封裝批量StartCommand參數,然後調度應用進程執行scheduleServiceArgs方法。
接下來在應用側將會先後執行Service的create和start兩個消息任務。
onCreate階段
app.thread.scheduleCreateService將執行應用進程ActivityThread的scheduleCreateService方法,該方法中會發生H.CREATE_SERVICE消息至主線程,將執行handleCreateService方法。
[ActivityThread#handleCreateService]
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.
// 移除請求GC的消息
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 通過反射實例化目標Service
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {
// 省略異常處理 ···
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
// 創建上下文ContextImpl
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
// context持有service實例
context.setOuterContext(service);
// 獲取應用進程Application實例
Application app = packageInfo.makeApplication(false, mInstrumentation);
// service中保存傳入的參數,會調用attachBaseContext方法使mBase持有ContextImpl
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 調用Service的onCreate生命週期回調方法
service.onCreate();
// 以token爲key,添加service實例至集合緩存(token是AMS傳來的ServiceRecord客戶端代理,ServiceRecord繼承自Binder)
mServices.put(data.token, service);
try {
// 通知AMS創建完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
// 省略異常處理 ···
}
}
首先通過反射創建目標Service,之後創建ContextImpl並使ContextImpl和Service互相持有對方引用,獲取應用Application實例並使Service持有其引用。接着便調用onCreate生命週期回調方法。最後再通知AMS創建完成。
再來到ActivityManagerService,在它的serviceDoneExecuting方法中又調用了ActiveServices的serviceDoneExecutingLocked方法:
[ActiveServices#serviceDoneExecutingLocked]
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
// mDestroyingServices保存執行銷燬的Service
boolean inDestroying = mDestroyingServices.contains(r);
if (r != null) {
// 判斷type類型。
// 剛create時是SERVICE_DONE_EXECUTING_ANON,startCommand時是SERVICE_DONE_EXECUTING_START,stop時是SERVICE_DONE_EXECUTING_STOP。
if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
// 設置ServiceRecord相關參數,主要設置stopIfKilled(異常殺死是否不能夠重啓) ···
} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
// ···
}
final long origId = Binder.clearCallingIdentity();
// 更新ServiceRecord中的狀態,移除超時消息
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
+ Binder.getCallingPid());
}
該方法主要是處理ServiceRecord中的參數和狀態更新設置,以及移除超時消息。
onStartCommand階段
app.thread.scheduleServiceArgs將會執行ActivityThread的scheduleServiceArgs方法:
[ActivityThread#scheduleServiceArgs]
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = 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);
}
}
H.SERVICE_ARGS消息將會執行handleServiceArgs方法:
[ActivityThread#handleServiceArgs]
private void handleServiceArgs(ServiceArgsData data) {
// 取出create階段創建並緩存的Service實例
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
// 給Intent設置ClassLoader
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
// 觸發Service的onStartCommand生命週期回調
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
// 這裏會阻塞當前線程,直到QueuedWork中的Runnable執行完畢。(SharedPreference會用到)
QueuedWork.waitToFinish();
try {
// 通知AMS執行完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
這裏取出緩存的Service實例,然後便調用其onStartCommand生命週期回調方法。最後也會通知AMS進行狀態更新操作。
到這裏,Service的啓動流程便完成,先後經過了onCreate和onStartCommand生命週期回調。
Service超時機制
在Service啓動過程中,AMS會進行超時機制相關設置,包括設置超時時間、觸發超時處理、移除超時處理。
設置超時
回到ActiveServices#realStartServiceLocked方法中,在調度應用進程創建Service前,會先執行bumpServiceExecutingLocked方法,在該方法中會調用scheduleServiceTimeoutLocked方法進行超時監聽的設置。
[ActiveServices#scheduleServiceTimeoutLocked]
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
// 獲取SERVICE_TIMEOUT_MSG消息
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
// 發送延遲消息
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}
該方法中發送一個延遲消息SERVICE_TIMEOUT_MSG,當20s(啓動前臺服務)或200s(啓動後臺服務)後仍沒有執行完,則會觸發超時處理。
移除超時
當應用進程側完成Service啓動後,便會調用AMS側的ActiveServices#serviceDoneExecutingLocked方法,其中會進行超時消息的移除:
[ActiveServices#serviceDoneExecutingLocked]
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
// ···
// 移除SERVICE_TIMEOUT_MSG消息
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
// ···
}
觸發超時
若在規定時間內,應用側沒有及時完成啓動流程和通知AMS,則會觸發超時邏輯,將會執行ActiveServices的serviceTimeout方法。
[ActiveServices#serviceTimeout]
void serviceTimeout(ProcessRecord proc) {
// ···
if (anrMessage != null) {
// dump ANR信息和觸發ANR彈窗
proc.appNotResponding(null, null, null, null, false, anrMessage);
}
}
當觸發超時後,將會觸發ANR。
當目標Service進程未啓動時
在前面的ActiveServices#bringUpServiceLocked方法中,會首先判斷若目標Service進程尚未已經啓動,則會先啓動應用進程,然後將ServiceRecord保存在mPendingServices集合中。
當應用進程啓動後,會調用ActivityManagerService的attachApplicationLocked方法,在該方法中會執行待啓動的Service。
[ActivityManagerService#attachApplicationLocked]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// ···
// thread.bindApplication
// ···
// Find any services that should be running in this process...
if (!badApp) {
try {
// 啓動等待對應進程啓動的Service
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// ···
}
調用了ActiveServices的attachApplicationLocked方法:
[ActiveServices#attachApplicationLocked]
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
// 遍歷待啓動ServiceRecord
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) {
// 省略待重啓Service部分 ···
}
return didSomething;
}
可以看到,當應用進程啓動完成通知AMS後,會再進行Service啓動流程。
stopService過程
停止Service通過調用context.stopService方法:
[ContextImpl#stopService]
public boolean stopService(Intent service) {
warnIfCallingFromSystemProcess();
return stopServiceCommon(service, mUser);
}
private boolean stopServiceCommon(Intent service, UserHandle user) {
try {
// ···
// 請求AMS執行stopService調度
int res = ActivityManager.getService().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
// ···
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
和startService一樣,也是調用ActivityManagerService的方法,在stopService中又會調用ActiveServices的stopServiceLocked方法:
[ActiveServices#stopServiceLocked]
int stopServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
// ···
// If this service is active, make sure it is stopped.
ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
try {
stopServiceLocked(r.record);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
return -1;
}
return 0;
}
首先查找目標ServiceRecord,然後調用stopServiceLocked方法。
stopServiceLocked方法最終會調用bringDownServiceLocked方法:
[ActiveServices#bringDownServiceLocked]
private final void bringDownServiceLocked(ServiceRecord r) {
// ···
if (r.app != null) {
if (r.app.thread != null) {
try {
// ···
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
// ···
}
} else {
// ···
}
} else {
// ···
}
// ···
}
調度應用進程執行stop操作。
scheduleStopService將發送H.STOP_SERVICE消息,最終將執行handleStopService方法:
[ActivityThread#handleStopService]
private void handleStopService(IBinder token) {
// 獲取緩存的Service實例
Service s = mServices.remove(token);
if (s != null) {
try {
if (localLOGV) Slog.v(TAG, "Destroying service " + s);
// 執行onDestroy回調
s.onDestroy();
s.detachAndCleanUp();
Context context = s.getBaseContext();
if (context instanceof ContextImpl) {
final String who = s.getClassName();
((ContextImpl) context).scheduleFinalCleanup(who, "Service");
}
QueuedWork.waitToFinish();
try {
// 通知AMS
ActivityManager.getService().serviceDoneExecuting(
token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
// ···
}
} else {
Slog.i(TAG, "handleStopService: token=" + token + " not found.");
}
//Slog.i(TAG, "Running services: " + mServices);
}
應用側stopService就是從mServices集合中移除Service實例,並執行它的onDestroy生命週期回調方法,最後通知AMS。
總結
Service的啓動和停止都是通過發請求給ActivityManagerService,由AMS來進行調度分發。AMS側通過ServiceRecord記錄運行Service的信息,應用側通過mServices集合保存反射創建的Service實例。AMS發送啓動或停止指令到應用側後,由應用側對Service實例執行對應的生命週期回調。
下面用時序圖總結這兩個流程。
啓動流程:
停止流程: