之前一篇介紹了《Activity 啟動(dòng)流程分析》,本篇繼續(xù)學(xué)習(xí) Android中Service的啟動(dòng)流程西采。
Service的啟動(dòng)方式
有兩種,分別是startService()僚稿,bindService()蹦掐,經(jīng)歷的生命周期也不太一樣。
通過
startService()
onCreate()
->onStartCommand()
->onDestroy()
建議不要在onStartCommand()做耗時(shí)操作通過
bindService()
onCreate()
->onbind()
->onUnbind()
->onDestroy()
Service的所有生命周期方法都是在主線程進(jìn)行的户辞,即ActivityThread啟動(dòng)的線程
onStartCommand()返回值種類:
- START_NOT_STICKY
- START_STRCKY
- START_REDELIVER_INTENT
Service以及四大組件多進(jìn)程泌类?
android的四大組件都可以開啟多進(jìn)程,通過manifest文件設(shè)置process屬性
可以同時(shí)startService()和bindService()時(shí)底燎?如何退出刃榨?
答案是可以的,參考 https://blog.csdn.net/qq_22804827/article/details/78609636
- service的onCreate只會(huì)執(zhí)行一次双仍,onBind也只會(huì)執(zhí)行一次枢希,onStartCommand可以執(zhí)行多次
- 無論多少個(gè)Activity綁定了Service,onBind()和onUnBind()只會(huì)執(zhí)行一次
- 多個(gè)Activity綁定Service朱沃,只有所有的Activity與Service綁定的Contxet失效后苞轿,Service才會(huì)執(zhí)行onUnbind(),最后onDestory()進(jìn)行銷毀
- 多個(gè)Activity綁定Service逗物,只有所有的Activity調(diào)用stopService()搬卒,或者在Service內(nèi)部調(diào)用stopSelf(),最后才會(huì)停止服務(wù)翎卓。
- 同時(shí)startService()和bindService()契邀,只有stopService() 加上unBindService()讓context失效,最后才會(huì)停止服務(wù)失暴。
涉及的類
- ContextImpl:Context的具體實(shí)現(xiàn)
- ActivityManagerService:四大組件的服務(wù)管理坯门,負(fù)責(zé)分發(fā)任務(wù)
- ActiveServices:實(shí)際負(fù)責(zé)Service啟動(dòng)綁定等事情
- ApplicationThread:表示APP的主線程,有main函數(shù)
- ActivityThread:ActivityThread的內(nèi)部類锐帜,是一個(gè)binder對(duì)象田盈,是ActivityManagerService向ActivityThread通信的橋梁
- LoadedApk:
StartService()
//ContextWrapper
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
我們通過Context.startService(),走到ContextWrapper缴阎,mBase是一個(gè)Context允瞧,具體實(shí)現(xiàn)在ContextImpl
// ContextImpl
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());
...
return cn;
}
}
-
validateServiceIntent()
是驗(yàn)證Intent是否合法 - AMS運(yùn)行在單獨(dú)的進(jìn)程,是一個(gè)binder蛮拔,ActivityManager.getService() 獲取得到是IActivityManager述暂,它是binder引用,供外部跨進(jìn)程調(diào)用建炫。
// ContextImpl
private void validateServiceIntent(Intent service) {
if (service.getComponent() == null && service.getPackage() == null) {
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
IllegalArgumentException ex = new IllegalArgumentException(
"Service Intent must be explicit: " + service);
throw ex;
} else {
Log.w(TAG, "Implicit intents with startService are not safe: " + service
+ " " + Debug.getCallers(2, 3));
}
}
}
從上面可以看出畦韭,service.getComponent() == null && service.getPackage() == null
說明是隱式啟動(dòng),5.0以后不支持隱式啟動(dòng)肛跌。
接著看AMS如何啟動(dòng)service
// 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);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
其中 mServices 是 ActiveServices艺配,他負(fù)責(zé)管理Service的活動(dòng)察郁,其實(shí)AMS就像一個(gè)橋梁,由他接收消息转唉,分派任務(wù)給指定的類負(fù)責(zé)皮钠,比如Activity啟動(dòng)就分發(fā)給ActivityStarter,Service的啟動(dòng)就分發(fā)ActiveServices赠法。
// 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);
// retrieveServiceLocked()獲取或者新建一個(gè)ServiceRecord
final boolean bgLaunch = !mAm.isUidActiveLocked(r.appInfo.uid);
// 調(diào)用了startServiceInnerLocked
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
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);
return r.name;
}
bringUpServiceLocked()是一個(gè)很重要的方法麦轰,startService()、bindService()都會(huì)走到砖织。
// ActiveServices
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
// Service在運(yùn)行
sendServiceArgsLocked(r, execInFg, false);
return null;
}
ProcessRecord app;// 獲取對(duì)應(yīng)的進(jìn)程ProcessRecord
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
// 將其加入到mPendingServices隊(duì)列
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// 真正啟動(dòng)Service
realStartServiceLocked(r, app, execInFg);
}
}
// 如果app進(jìn)程不存在款侵,則會(huì)AMS startProcessLocked()
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
}
如果Service目標(biāo)進(jìn)程不存在會(huì)走AMS startProcessLocked(),跟Activity開啟進(jìn)程一樣侧纯,Process.start創(chuàng)建一個(gè)新的進(jìn)程新锈,走到ActivityThread的main函數(shù),創(chuàng)建Application等眶熬。
// AcitveServices
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
requestServiceBindingsLocked(r, execInFg);
sendServiceArgsLocked(r, execInFg, true);
}
app.thread其實(shí)就是IApplicationThread壕鹉,它是一個(gè)binder,對(duì)應(yīng)的服務(wù)端就是ApplicationThread聋涨,它是ActivityThread的內(nèi)部類,對(duì)外提供跟ActivityThread通信的接口负乡。
最后會(huì)走到ActivityThread.scheduleCreateService()
requestServiceBindingsLocked()跟bindService()有關(guān)牍白,這里先不管
sendServiceArgsLocked()最后會(huì)走到onStartCommand()
// ActivityThread
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);
}
sendMessage(H.CREATE_SERVICE, s); 就是切換到主線程,因?yàn)閟cheduleCreateService運(yùn)行在binder線程池中抖棘,最后通過H handler處理
// ActivityThread
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 通過classLoader加載初始化Service
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
try {
// 創(chuàng)建context
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// 如果Application不存在茂腥,會(huì)創(chuàng)建Application
Application app = packageInfo.makeApplication(false, mInstrumentation);
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);
}
}
}
handleCreateService()負(fù)責(zé)實(shí)例化service,創(chuàng)建Context切省、Application等最岗,跟Activity的hanleLaunchActivity()很相似。最后調(diào)用Service的onCreate()
再看下onStartCommand()再哪里被調(diào)用朝捆?
// ActiveService
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
r.app.thread.scheduleServiceArgs(r, slice);
}
同樣利用ApplicationThread到達(dá)AcitivityThread所在的進(jìn)程般渡。
//ActivityThread
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);
}
}
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
...
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
}
}
}
最后切換到ActivityThread的主線程,調(diào)用onStartCommand()
bindService()
Service的bindService()跟startService()的流程很類似芙盘,但是他涉及到ServiceConnection的傳輸驯用,還要通過ServiceConnection返回binder的代理給客戶端,通知已經(jīng)綁定成功
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
// ContextImpl
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
// 轉(zhuǎn)化成IServiceConnection
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
...
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
return res != 0;
}
}
bindServiceCommon有兩個(gè)主要的任務(wù)儒老,
- 生成一個(gè)ServiceConnection的binder服務(wù)蝴乔,這樣當(dāng)Service綁定成功后就可以通過binder引用的接口調(diào)用ServiceConnection的onServiceConnected()。
- 將ServiceConnection的對(duì)應(yīng)binder的引用傳給AMS驮樊,并bindService()
其中binder服務(wù)就是LoadApk.ServiceDispatcher薇正,所以mPackageInfo.getServiceDispatcher()負(fù)責(zé)創(chuàng)建LoadApk.ServiceDispatcher片酝,并提供binder引用。
其實(shí)在同一進(jìn)程內(nèi)提供的binder實(shí)體挖腰,跨進(jìn)程之后會(huì)通過binder驅(qū)動(dòng)轉(zhuǎn)化為binder引用雕沿,這里通通叫binder,具體可以看Android的binder知識(shí)點(diǎn)
// LoadedApk
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
getServiceDispatcher()先查詢是否已經(jīng)存在已有的ServiceConnection對(duì)應(yīng)的LoadedApk.ServiceDispatcher曙聂,如果有就直接復(fù)用晦炊,不需要再建立LoadedApk.ServiceDispatcher,增加多一個(gè)binder了宁脊。否則就創(chuàng)建ServiceDispatcher断国。
//AMS
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
終于來到了AMS的bindService(),他還是分發(fā)給了ActiveServices負(fù)責(zé)bindServiceLocked()
// ActiveServices
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
// 獲取或創(chuàng)建一個(gè)ServiceRecord
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
}
// ActiveServices
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
}
}
}
在ActiveServices的部分流程上跟startService()沒有什么大的不同榆苞,同樣走到realStartServiceLocked()
// AcitveServices
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
requestServiceBindingsLocked(r, execInFg);
sendServiceArgsLocked(r, execInFg, true);
}
app.thread.scheduleCreateService()負(fù)責(zé)創(chuàng)建service稳衬,不在分析,這里講上面沒說到的requestServiceBindingsLocked()方法坐漏,最后怎么調(diào)用到了ServiceConnection的onServiceConnected()
// AcitveServices
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
}
利用IApplicationThread切換到ActivityThread薄疚,最后切換到主線程,調(diào)用handleBindService()赊琳。這部分基本上是一樣的街夭。
// ActivityThread
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
// 調(diào)用了onBind(),返回一個(gè)IBinder對(duì)象
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
}
}
}
}
IBinder binder = s.onBind(data.intent);
調(diào)用了Service的生命周期onBind()躏筏,還返回了一個(gè)binder(這里應(yīng)該是binder實(shí)體板丽,因?yàn)橥粋€(gè)進(jìn)程內(nèi)),本來開始以為這里會(huì)利用LoadedApk.ServiceDispatcher的binder引用調(diào)用ServiceConnection的onServiceConnected()趁尼,實(shí)際上并沒有埃碱,而是又跨進(jìn)程調(diào)用AMS的pubishService,由AMS回調(diào)ServiceConnection的onServiceConnected()
// AMS
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized(this) {
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
這里老規(guī)矩酥泞,AMS分發(fā)任務(wù)給ActiveServices
// ActiveServices
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
if (r != null) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
continue;
}
...
c.conn.connected(r.name, service, false);
}
}
...
}
}
}
這里知道為什么了ActivityThread沒有直接跨進(jìn)程調(diào)用ServiceConnection的onServiceConnected()砚殿,原來只有AMS保存了LoadedApk.ServiceDispatcher的binder引用,最后調(diào)用 c.conn.connected(r.name, service, false);
// LoadApk.InnerConnection
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
這里可以看出InnerConnection就是一個(gè)binder芝囤,他的作用就是讓其他進(jìn)程可以跨進(jìn)程調(diào)用到connected()似炎。
最后在 LoadApk.InnerConnection利用ServiceDispatcher 調(diào)用了onServiceConnected()方法。
流程圖
總結(jié)
(沒想好悯姊,待補(bǔ)上)