1.前言
- 最近一直在看 《Android進(jìn)階解密》 的一本書恼布,這本書編寫邏輯耳贬、流程都非常好攒射,而且很容易看懂醋旦,非常推薦大家去看看(沒有收廣告費(fèi),單純覺得作者寫的很好)匆篓。
- 上一篇簡單的介紹了Android進(jìn)階(四):Activity啟動過程(最詳細(xì)&最簡單)浑度。
- 今天就介紹Service 2種啟動方式中:startService啟動 (基于Android 8.0 系統(tǒng))。
- 本文提供一種看源碼的思路鸦概,因此bindService啟動流程就沒有再本文展開(與startService流程類似)箩张。
- 文章中實例 linhaojian的Github
2.Context繼承關(guān)系
-
在講解Service啟動過程前,先了解一下它的繼承關(guān)系窗市,便于后續(xù)的源碼理解:
Context繼承關(guān)系.png - 從圖中先慷,可以發(fā)現(xiàn):
- Activity,Service,Application都是ContextWrapper的子類;
- ContextWrapper里面引用著一個ContextImpl實例咨察;
- ContextWrapper里所有的方法都是通過調(diào)用ContextImpl進(jìn)行實現(xiàn)论熙;
- 通過上述3點(diǎn)可以發(fā)現(xiàn),其他就是
[裝飾者模式](http://www.reibang.com/p/16e946f42ce1)
2.Service啟動過程的時序圖
Service啟動時序圖.png
3.源碼分析
3.1 startService()啟動分析
3.1.1 ContextImpl:
class ContextImpl extends Context {
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);// 1
}
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());// 2
// ....
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
- 注釋1:startService最終也是調(diào)用startServiceCommon函數(shù)摄狱;
- 注釋2:ActivityManager.getService()其實就是ActivityManagerService脓诡,調(diào)用ActivityManagerService類里面的startService方法无午;
3.1.2 ActivityManagerService:
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);// 1
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
- 注釋1:調(diào)用ActiveServices的startServiceLocked();
3.1.3 ActiveServices:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
//.....
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);// 1
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
//.....
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);// 2
return cmp;
}
- 注釋1:創(chuàng)建 & 封裝啟動Service的相關(guān)數(shù)據(jù)祝谚;
- 注釋2:調(diào)用自身的startServiceInnerLocked()宪迟;
ComponentName 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); // 3
if (error != null) {
return new ComponentName("!!", error);
}
//.....
return r.name;
}
- 注釋3:調(diào)用自身的bringUpServiceLocked();
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// ....
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
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);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);// 4
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
}
} else {
app = r.isolatedProc;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingType = "webview_service";
}
}
//.....
}
- 注釋4:調(diào)用自身的realStartServiceLocked()交惯;
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);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);// 5
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
//...
}
// 通知ActivityThread調(diào)用Service的onStartCommand方法
sendServiceArgsLocked(r, execInFg, true);// 6
//.....
}
- 注釋5:通知ActivityThread次泽,真正的創(chuàng)建Service;
- 注釋6:調(diào)用自身的sendServiceArgsLocked()啟動Service的其他生命周期方法席爽,下面會介紹意荤;
3.1.4 ActivityThread:
- scheduleCreateService()其實就是通過Handler機(jī)制進(jìn)行線程切換,最后會調(diào)用handleCreateService();
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);// 1
Service service = null;
try {
// 通過類加載器只锻,創(chuàng)建Service實例
java.lang.ClassLoader cl = packageInfo.getClassLoader();// 2
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);// 3
} 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);
//向Service對象中初始化基本設(shè)置
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());// 4
//調(diào)用service的onCreate生命周期函數(shù)
service.onCreate();// 5
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);
}
}
}
- 注釋1:獲取LoadedApk對象玖像,負(fù)責(zé)解析manifest文件;
- 注釋2:獲取ClassLoader類加載器炬藤,負(fù)責(zé)創(chuàng)建Service實例御铃;
- 注釋3:通過AppComponentFactory,創(chuàng)建Service對象沈矿;
- 注釋4:設(shè)置Service基礎(chǔ)參數(shù);
- 注釋5:調(diào)用Service的onCreate方法咬腋;
3.1.5 AppComponentFactory:
public 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();// 1
}
}
- 注釋1:通過類加載器羹膳,創(chuàng)建Service實例;
3.1.6 ActiveServices的sendServiceArgsLocked()函數(shù):
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
//...
Exception caughtException = null;
try {
r.app.thread.scheduleServiceArgs(r, slice);// 1
} 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;
}
//....
}
- 注釋1:調(diào)用ActivityThread的scheduleServiceArgs函數(shù)(在Service創(chuàng)建之后根竿,會調(diào)用sendServiceArgsLocked()陵像,實現(xiàn)其他的生命周期方法的調(diào)用);
3.1.7 ActivityThread的handleServiceArgs函數(shù):
- scheduleServiceArgs()最終通過Handler機(jī)制切換線程 & 調(diào)用handleServiceArgs()寇壳;
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);// 1
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
//...
} catch (Exception e) {
// ...
}
}
}
- 注釋1:調(diào)用Service的onStartCommand()醒颖;
4.類關(guān)系
Service啟動類結(jié)構(gòu).png
- 通過上圖發(fā)現(xiàn),Service啟動過程就是AMS與ActivityThread不同的進(jìn)程交互實現(xiàn)的壳炎。
5.總結(jié)
- 到此泞歉,
Service啟動過程
介紹完畢。 - 如果喜歡我的分享匿辩,可以點(diǎn)擊 關(guān)注 或者 贊腰耙,你們支持是我分享的最大動力 。
- linhaojian的Github
歡迎關(guān)注linhaojian_CSDN博客或者linhaojian_簡書铲球!
不定期分享關(guān)于安卓開發(fā)的干貨挺庞。
寫技術(shù)文章初心
- 技術(shù)知識積累
- 技術(shù)知識鞏固
- 技術(shù)知識分享
- 技術(shù)知識交流