1.Service生命周期
前面已經(jīng)分析了Activity
的啟動(dòng)流程。這里篇開始分析常用組件Service
供鸠。Service的生命周期如下畦贸。這篇從源碼角度,分析startService
的啟動(dòng)流程楞捂。
2.StartService時(shí)序圖
老規(guī)矩薄坏,看代碼前先放圖。相較Activity的生命周期流程寨闹,這個(gè)就比較簡(jiǎn)單胶坠。
3.源碼分析
并沒有多涉及新增類。直接從源碼開始看吧繁堡。
這里還是使用Android P的源碼沈善,好找。Android Q的代碼并沒有很大的差異椭蹄。
startService
事實(shí)上通過mBase
調(diào)用到ContextImpl的startService
闻牡。一路調(diào)用到ActivityManager.getService().startService
。前篇已經(jīng)說過绳矩,這個(gè)通過IPC調(diào)用到System_service進(jìn)程的ActivityManagerService罩润。
ContextImpl
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
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(), user.getIdentifier());
...
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
ActivityManagerService就比較輕松了,直接調(diào)用ActiveServices的startServiceLocked
方法埋酬。
ActivityManagerService
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, 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, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
ActiveServices
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
...
//需要注意哨啃,從這里看,這里構(gòu)建了一個(gè)res.record.bindings為空的ServiceLookupResult写妥。
//這也就是startService為什么不會(huì)調(diào)用到onBInd的原因拳球。
//這里面還做了權(quán)限檢測(cè),有興趣的朋友可以細(xì)看
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
...
ServiceRecord r = res.record;
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
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);
...
//后面是一些超時(shí)檢測(cè)
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
//看到這珍特,如果Service已經(jīng)在運(yùn)行狀態(tài)祝峻,則調(diào)用sendServiceArgsLocked,
//也就是說只觸發(fā)onStartCommond
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
...
//眼熟,如果Service有自己的獨(dú)立進(jìn)程莱找,需要在它的進(jìn)程啟動(dòng)酬姆。
//這里需要走到else去等待。否則的話奥溺,走進(jìn)if邏輯辞色。
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
//如果Serice所在進(jìn)程已啟動(dòng),直接調(diào)用realStartServiceLocked
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.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;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingType = "webview_service";
}
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
//如果進(jìn)程還沒啟動(dòng)浮定,通過startProcessLocked去啟動(dòng)對(duì)應(yīng)的進(jìn)程相满,
//然后在AMS的attachApplicationLocked方法里,
//通過mServices.attachApplicationLocked又調(diào)用到了realStartServiceLocked桦卒。
//這里我在之前的這篇[新app進(jìn)程創(chuàng)建過程](http://www.reibang.com/p/6af5667c2d30)
//已經(jīng)詳細(xì)描述立美,這里不再贅述
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, 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;
}
}
...
}
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
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);
//你看,這里調(diào)用了ApplicationThread的scheduleCreateService方灾。
//又是我們熟悉的ActvityThread的調(diào)用流程
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
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;
}
//因?yàn)閞.bindings為空建蹄,所以這個(gè)沒有調(diào)用onBind
requestServiceBindingsLocked(r, execInFg);
...
//這里面會(huì)去調(diào)用onStartCommond
sendServiceArgsLocked(r, execInFg, true);
...
}
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
...
try {
//同樣的,這里調(diào)用了ApplicationThread的scheduleServiceArgs裕偿。
//又是我們熟悉的ActvityThread的調(diào)用流程
r.app.thread.scheduleServiceArgs(r, slice);
}
...
}
上面的流程洞慎,已經(jīng)可以清晰的看出了,關(guān)鍵的是击费,調(diào)用了ApplicationThread的scheduleCreateService
和scheduleServiceArgs
方法拢蛋。
熟悉的ApplicationThread->H->ActivityThread
三連招。
ApplicationThread
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);
}
H
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
ActvityThread
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//創(chuàng)建Service對(duì)象
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
//調(diào)用Service的attach方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//調(diào)用Service的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
上面可以看到蔫巩,Service
已經(jīng)創(chuàng)建并且調(diào)用onCreate
方法谆棱。下面我們看下scheduleServiceArgs
做了什么。
ApplicationThread
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
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
ActvityThread
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) {
//這里調(diào)用了onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManager.getService().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);
}
}
}
}
這篇的話圆仔,是基于之前Activity啟動(dòng)流程分析進(jìn)行的垃瞧,默認(rèn)朋友們已經(jīng)看過了。所以像ApplicationThread->H->ActivityThread
三連招坪郭,從App->Service和Service->app个从,和Service所在進(jìn)程未啟動(dòng)的話,啟動(dòng)對(duì)應(yīng)進(jìn)程的流程歪沃,都一筆帶過了嗦锐。因?yàn)檫@個(gè)在之前幾篇都已經(jīng)熟悉介紹過。
如果是沒有看過的朋友沪曙,可以著重看這兩篇奕污。
Activity啟動(dòng)源碼分析--總篇
Activity啟動(dòng)源碼分析(3)-- 新app進(jìn)程創(chuàng)建過程
參考文檔: