Android -- 系統start Service流程簡要分析
Service是Android系統四大組件之一,它主要被用來在後臺處理一些耗時操作,也會被設計成對Client提供業務的服務模塊。Activity組件主要用來和用戶進行交互,Service組件則可以在後臺處理用戶觸發的一些請求操作,然後直接在Activity中展現請求結果。Activity和Service組件結合使用,能讓我們設計出模塊更清晰的應用。
Service有兩種啓動方式,一種是Start方式;一種是Bind方式。兩種方式的使用細節可以參照之前轉載的Service官方文檔。此次,我們就先分析start Service的系統流程,Binde Service的分析會在下一篇講述。
start Service,實際調用的是ContextImpl::startService()函數:
@Override
public ComponentName ContextImpl::startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
private ComponentName ContextImpl::startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread()/*AMS可以通過該ApplicationThread的Binder對象跟當前的應用進程通信*/, service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());//進入AMS::startService()
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());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
參數mMainThread指向啓動該服務的應用進程,參數intent中一般會指定Service的class信息,或者服務的類型全限定名稱。之後,實際調用AMS::startService(),返回值是啓動的Service組件的名稱。我們進入AMS分析:
@Override
public ComponentName AMS::startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startService: " + service + " type=" + resolvedType);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);//調用startServiceLocked()
Binder.restoreCallingIdentity(origId);
return res;
}
}
mService是AMS內部,類型爲ActiveService的實例對象;它是AMS啓動一個服務的輔助類,封裝了很多啓動Service的業務函數。收下判斷傳參的合法性,隨後調用ActiveService::startServiceLocked():
ComponentName ActiveService::startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
//ServiceRecord是AMS中描述一個Service組件的類型
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);//查找AMS中是否存在與參數service對應的ServiceRecord對象;如果不存在,則會通過PMS去獲取與service對應的Service組件信息,並封裝成ServiceLookupResult對象返回
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
...
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants));
final ServiceMap smap = getServiceMap(r.userId);
...
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);//調用startServiceInnerLocked()去bring up一個Service
}
一個服務的啓動必須由一個應用組件去觸發,所以啓動Service的應用組件進程是不能不存在的。接着根據參數,檢查AMS中是否已經這個服務的信息,即是否已經啓動過它;如果AMS不存在當前需要啓動的Service組件的信息,則去PMS查詢,因爲PMS會掃描所有Apk中的組件,根據參數從PMS查詢,就會得到當前需要啓動的Service對應的ServiceRecord對象,隨後將它封裝成ServiceLookupResult對象返回。
ServiceRecord是AMS用於管理Service的類型,每一個啓動的Service,在AMS中都以ServiceRecord對象描述;就如ActivityRecord一樣。
隨後調用ActiveService::startServiceInnerLocked():
ComponentName ActiveService::startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);//調用bringUpServiceLocked()去啓動服務
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
smap.ensureNotStartingBackground(r);
}
return r.name;
}
主要處理就是調用bringUpServiceLocked()函數去啓動當前的服務: private String ActiveService::bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);//如果該Service已經啓動,則直接傳遞Service參數到進程的主線程中,此時會觸發調用onStartCommand();此次Service啓動已經完成
return null;
}
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
return null;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);
// We are now bringing the service up, so no longer in the
// restarting state.
if (mRestartingServices.remove(r)) {
r.resetRestartCounter();
clearRestartingIfNeededLocked(r);
}
// Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) {
...
}
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": user " + r.userId + " is stopped";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
// Service is now being launched, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;//表示當前Service組件想要運行在其中的進程的名字
ProcessRecord app;
if (!isolated) {//isolated表示是否要求一個單獨的進程來運行服務;TRUE爲需要
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//根據這個進程名字在AMS中查找該進程是否已經存在
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) {//如果進程已經啓動,調用realStartServiceLocked()直接去啓動Service
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);//該service想運行的進程已經存在,此時直接去啓動該Service即可
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {
// If this service runs in an isolated process, then each time
// we call startProcessLocked() we will get a new isolated
// process, starting another process if we are currently waiting
// for a previous process to come up. To deal with this, we store
// in the service any current isolated process it is running in or
// waiting to have come up.
app = r.isolatedProc;//得到運行Service的單獨的進程,第一次爲null
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {//如果該服務想要運行的進程還沒有啓動,則調用startProcessLocked()先去啓動進程,再去啓動Service
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;//進程啓動失敗,退出
}
if (isolated) {
r.isolatedProc = app;
}
}
if (!mPendingServices.contains(r)) {//將當前需要啓動Service的ServcieRecord對象加入到mPendingServices
mPendingServices.add(r);
}
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 (in bring up): " + r);
stopServiceLocked(r);
}
}
return null;
}
與Activity的啓動類似,我們啓動一個Service時,也需要判斷當前Service是否已經啓動過。結合Service的生命週期,如果該Service已經啓動過,則直接去啓動Service即可(即調用Service::onStartCommnad()函數),但Service::onCreate()不會被調用,因爲onCreate()只在Service第一次創建時纔會被調用;如果Service的宿主進程不存在,我們就先爲該Service創建運行所需要的進程,然後再去啓動它。爲Service創建進程的流程與之前Activity啓動時創建進程的過程基本一致,此處就不再分析。
我們假設此時我們是第一次啓動該Service,此時需要爲它創建進程。結合代碼可知,在AMS發出了爲Service創建進程的請求之後,會將當前的Service添加到mPendingServices集合中,它保存了所有需要去的Service的ServiceRecord對象。在進程創建完畢後,AMS就會遍歷mPendingServices,去啓動服務。
由Activity的啓動過程分析可知,應用進程的入口函數是ActivityThread::main();應用進程啓動完畢後,就會給AMS發送一個通知,告知AMS進程已經創建好了,可以去啓動組件了。這個動作是在AMS::attachApplication(IApplicationThread)中處理的,參數是IApplicationThread類型;它用於AMS與當前應用進程的主線程交互。
集合之前分析Activity啓動部分的內容,最終是在AMS::attachApplicationLocked(IApplicationThread, int)中處理:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);//創建應用進程時,會將進程對象和pid保存到mPidsSelfLocked集合中,所以此時可以取出對應的進程對象
}
} else {
app = null;
}
...
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {//如果app中已經有線程,說明app以前存在,現在是重啓;先清理掉這些信息
handleAppDiedLocked(app, true, true);
}
// Tell the process all about itself.
if (DEBUG_ALL) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app);
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);//創建app死亡監聽對象
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
app.makeActive(thread, mProcessStats);//會將創建的ActivityThread對應的ApplicationThread對象的Binder實例保存到該ProcessRecord對象的thread成員中,用以和該進程的主線程交互
...
try {
...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());//調用bindApplication()方法
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
// todo: Yikes! What should we do? For now we will try to
// start another process, but that could easily get us in
// an infinite loop of restarting processes...
Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
startProcessLocked(app, "bind fail", processName);
return false;
}
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app);
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {//調用attachApplicationLocked(),去啓動當前Activity組件堆棧最頂端的Activity
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);//檢查mPendingServices中是否有Service組件需要在該新創建的進程中啓動;在此之前,我們會把需要啓動的Service組件添加到mPendingServices中
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
...
return true;
}
與之前一樣,先得到爲當前Service啓動而創建的新應用進程的ProcessRecord對象;調用ActivityThread::bindApplication()綁定應用信息,創建Instrumentation、LoadedApk和Application等對象。接着調用ActiveService::boolean attachApplicationLocked(ProcessRecord proc, String processName)啓動服務: boolean ActiveService::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 {
for (int i=0; i<mPendingServices.size(); i++) {//在mPendingServices中找到需要在當前新創建進程中運行的Service組件
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);//先從mPendingServices中移除它
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, sr.createdFromFg);//調用realStartServiceLocked,在新創建的進程中啓動該Service
didSomething = true;
if (!isServiceNeeded(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.shortName, 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;
}
從mPendingServices中找到和當前進程匹配的ServiceRecord對象,即需要運行在當前新建進程的服務。調整mPendingServices集合,並調用ActiveService::realStartServiceLocked()去啓動Service。除此之外,還會處理需要重啓的Service。
分析ActiveService::realStartServiceLocked():
private final void ActiveService::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;//將Service運行的進程信息保存到對應的ServiceRecord對象中
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);//調用scheduleCreateService在服務進程中創建Service對象,它會發送CREATE_SERVICE消息,最終在該進程的ActivityThread中處理會觸發調用onCreate()
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);//處理bind service的情況:會將Service組件連接到請求綁定它的Activity中;內部會調用scheduleBindService()->handleBindService() -> onBind()被調用
updateServiceClientActivitiesLocked(app, null, true);
// 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));
}
sendServiceArgsLocked(r, execInFg, true);//會觸發調用Service::onStartCommand()
...
}
首先,調用ActivityThread::scheduleCreateService()函數去創建當前啓動的Service;中間的Binder調用關係就不再描述,之前已有過類似分析。直接看它的處理: private void ActivityThread::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);//得到進程中加載的應用程序,以LoadedApk描述
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();//加載此時要啓動的Service類,並創建其Servcie實例
} 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);
//爲該Service設置Context上下文環境
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);//創建一個Application對象,用來描述該Service所屬的應用程序;
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());//將一些信息與該Service組件進行綁定
service.onCreate();//調用Service的onCreate()
mServices.put(data.token, service);//token指向AMS中管理Service的ServiceRecord對象,保存到mService集合中
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);//通知AMS服務已經創建
} 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);
}
}
}
CreateServiceData封裝了AMS傳遞的參數信息。首先,是去加載這個需要啓動的Service。LoadedApk實例代表了一個被加載的應用信息,它與Application實例一樣,都是在進程創建後的bindApplication()調用中被創建的;且進程內部,所有組件都共用這些對象。加載Service類之後,便會爲Service設置當前Context信息;之後便將一些信息綁定到Service中,隨後就會觸發Service::onCreate()被調用,這時服務就已經創建完成,它的整個生命週期也就開始了。
再回到ActiveService::realStartServiceLocked()中,Service創建完畢後,start Service又會調用sendServiceArgsLocked()函數:
private final void ActiveService::sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
while (r.pendingStarts.size() > 0) {
Exception caughtException = null;
ServiceRecord.StartItem si = null;
try {
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());
}
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
mAm.updateOomAdjLocked(r.app);
}
int flags = 0;
if (si.deliveryCount > 1) {
flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {
flags |= Service.START_FLAG_REDELIVERY;
}
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);//最終會調用Service::onStartCommand()
} catch (TransactionTooLargeException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent="
+ si.intent);
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);
caughtException = e;
} catch (Exception e) {
Slog.w(TAG, "Unexpected exception", e);
caughtException = e;
}
if (caughtException != null) {
// Keep nesting count correct
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
if (caughtException instanceof TransactionTooLargeException) {
throw (TransactionTooLargeException)caughtException;
}
break;
}
}
}
如果這次Service start過程有參數(如參數intent中會封裝一些指令)需要投遞,則會觸發ActivityThread::scheduleServiceArgs()將參數投遞到Service中,觸發一些後臺執行流程: 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);//此處會調用Service::onStartCommand()函數
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManagerNative.getDefault().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);
}
}
}
}
ServiceArgsData封裝了AMS傳遞的參數信息,我們的分析場景中不會牽扯到設置taskRemoved,所以這時就會觸發調用Service::onStartCommand()調用,此時我們可以通過讀取參數,來啓動一些我們需要在該Service中執行的操作;至此,Service的有效生命週期就開始了。
回顧之前的分析,如果當時判斷該Service已經啓動過,即onCreate()已經調用過;則此時會直接調用sendServiceArgsLocked()函數,向Service中投遞傳入的參數,觸發Service::onStartCommand()調用,而不會再去觸發Service::onCreate()。這與我們所瞭解的Service的start生命週期是一致的。