Android?Service啟動(dòng)流程刨析
強(qiáng)調(diào)一下閱讀系統(tǒng)源碼,起碼要對(duì)進(jìn)程間通信要了解,對(duì)binder機(jī)制非常非常清楚,binder就是指南針,要不然你會(huì)暈頭轉(zhuǎn)向;強(qiáng)行閱讀,就容易睡著。
Service啟動(dòng)先來(lái)一張圖感受一下
這張圖能夠說(shuō)明一個(gè)大致的流程,但是服務(wù)的啟動(dòng)肯定不是這么簡(jiǎn)單,但是我們先簡(jiǎn)單的總結(jié)一下,逐漸深入。服務(wù)的啟動(dòng)形式有兩種,startService()和 binderService(),我們看startService()這一種。startService是ContextWrapper里面的方法。
ContextWrapper.java
@Override public ComponentName startService(Intent service) { return mBase.startService(service);//mBase這里指的是ContextImpl類 }
ContextImpl.java
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); }
private ComponentName startServiceCommon(Intent service, UserHandle user) { try { //檢驗(yàn)Intent validateServiceIntent(service); ...... ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), getOpPackageName(), user.getIdentifier()); ...... return cn; } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }
校驗(yàn)完Intent后,就調(diào)用ActivityManagerNative.getDefault(),獲取一個(gè)IActivityManager對(duì)象,將啟動(dòng)Service這件事情交給了IActivityManager。我們看一下ActivityManagerNative的類定義
public abstract class ActivityManagerNative extends Binder implements IActivityManager
這種模式是不是非常熟悉??? 繼承了Binder,實(shí)現(xiàn)了一個(gè)IActivityManager接口,這個(gè)跟我們生成了遠(yuǎn)程服務(wù)通信生成的AIDL的java文件怎么那么像,現(xiàn)在告訴你,這就是為了遠(yuǎn)程服務(wù)通信做準(zhǔn)備的,只是一般這種類我們都是自動(dòng)生成的,ActivityManagerNative 是谷歌的人自己寫
一個(gè)完整的AID L有兩部分,一個(gè)是個(gè)跟服務(wù)端通信的Stub,一個(gè)是跟客戶端通信的Proxy; ActivityManagerNative就是Stub,閱讀源碼發(fā)現(xiàn)在ActivityManagerNative 文件中還有個(gè)ActivityManagerProxy,那么跟客戶端通信的Proxy也有了。先看IActivityManager怎么獲取的
ActivityManagerNative.java
static public IActivityManager getDefault() { return gDefault.get(); }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { //獲取名為"activity"的服務(wù),服務(wù)都注冊(cè)到ServiceManager來(lái)統(tǒng)一管理 IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } };
就是一個(gè)單例設(shè)計(jì)模式,獲取到服務(wù)對(duì)象IBinder,把這個(gè)IBinder轉(zhuǎn)換成IActivityManager返回了?,F(xiàn)在由IActivityManager啟動(dòng)服務(wù)。
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); service.writeToParcel(data, 0); data.writeString(resolvedType); data.writeString(callingPackage); data.writeInt(userId); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); ComponentName res = ComponentName.readFromParcel(reply); data.recycle(); reply.recycle(); return res; }
上面說(shuō)了ActivityManagerProxy作為binder通信的客戶端,ActivityManagerNative 作為binder通信的服務(wù)端; mRemote.transact()是binder通信的客戶端發(fā)起方法,經(jīng)過(guò)binder驅(qū)動(dòng),最后回到binder服務(wù)端ActivityManagerNative的onTransact()方法。
@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ....... switch (code) { case START_SERVICE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); String callingPackage = data.readString(); int userId = data.readInt(); ComponentName cn = startService(app, service, resolvedType, callingPackage, userId); reply.writeNoException(); ComponentName.writeToParcel(cn, reply); return true; } } ....... }
ActivityManagerNative的真正實(shí)現(xiàn)是ActivityManagerService,所以binder通信的服務(wù)端的ActivityManagerService,ActivityManagerProxy.startService()最終調(diào)用ActivityManagerService.startService()。注意這就跨進(jìn)程了,ActivityManagerService是一個(gè)服務(wù)端的進(jìn)程??碅ctivityManagerService中的startService方法。
ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException { ...... synchronized(this) { ....... ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } }
ActivityManagerService沒(méi)有直接干這個(gè)活,而是把這個(gè)任務(wù)交給了mService, mService 是一個(gè) ActiveServices 對(duì)象。在早期的安卓版本中并沒(méi)有這個(gè)類,后來(lái)重構(gòu)時(shí)抽出這個(gè)類專門用來(lái)管理Service.
ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, String callingPackage, int userId) throws TransactionTooLargeException { ........ return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); }
tartServiceInnerLocked調(diào)用了 bringUpServiceLocked(),bringUpServiceLocked()內(nèi)部調(diào)用了realStartServiceLocked(),我們看realStartServiceLocked()方法。
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ....... try { ....... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { .... } finally { .... } requestServiceBindingsLocked(r, execInFg); 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)); } // 進(jìn)入onStartCommand() sendServiceArgsLocked(r, execInFg, true); .... }
這里的關(guān)鍵是
app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app 是要運(yùn)行 Service 的進(jìn)程對(duì)應(yīng)的 ProcessRecord 對(duì)象,代表一個(gè)應(yīng)用進(jìn)程; 要區(qū)分一下,一般我們都是單方向通信,客戶端將處理請(qǐng)求發(fā)送給服務(wù)端,服務(wù)端處理后返回,如果要服務(wù)端向客戶端發(fā)送一個(gè)“請(qǐng)求”呢?這里的thread 是一個(gè) ApplicationThreadProxy 對(duì)象,它是應(yīng)用進(jìn)程的 ApplicatonThread 對(duì)象在 AMS 端的代理,AMS 靠它來(lái)和應(yīng)用進(jìn)程進(jìn)行通信。所以AMS和應(yīng)用進(jìn)程可以雙向通信了。
ApplicationThreadProxy.java
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); info.writeToParcel(data, 0); compatInfo.writeToParcel(data, 0); data.writeInt(processState); try { mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); } catch (TransactionTooLargeException e) { throw e; } data.recycle(); }
執(zhí)行mRemote.transact后,就會(huì)回調(diào)ApplicationThreadNative的onTransact,這是Binder的套路。
ApplicationThreadNative.java
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case SCHEDULE_CREATE_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); int processState = data.readInt(); scheduleCreateService(token, info, compatInfo, processState); return true; } ... }
內(nèi)部調(diào)用scheduleCreateService,看上面的圖,可以知道,scheduleCreateService是屬于ApplicatonThread的。
ApplicatonThread.java
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); }
發(fā)送一個(gè)消息,這個(gè)消息都是由H類處理的,H類就是系統(tǒng)Hander,專門處理系統(tǒng)請(qǐng)求的; 比如一些Activity的生命周期等全在這里面。這個(gè) H對(duì)象是在應(yīng)用進(jìn)程的主線程中創(chuàng)建的,所以最終的結(jié)果是把創(chuàng)建 Service 的消息傳到了主線程,因此Service是運(yùn)行在主線程中的。
H.java
private class H extends Handler { ......... public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate"); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
ActivityThread.java
private void handleCreateService(CreateServiceData data) { ....... LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { // 反射加載Service java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { ....... } try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); //創(chuàng)建ContextImpl對(duì)象 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); //創(chuàng)建Application對(duì)象 Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); //回調(diào)onCreate方法 service.onCreate(); mServices.put(data.token, service); try { //調(diào)用服務(wù)創(chuàng)建完成 ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { ....... } }
到此Service的onCreate就回調(diào)了,那么onStartCommand()何時(shí)回調(diào)呢?在realStartServiceLocked中調(diào)用了sendServiceArgsLocked(r, execInFg, true),sendServiceArgsLocked與上面類似,最終也是發(fā)送了一個(gè)(SERVICE_ARGS)消息。
ApplicationThread.java
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, int flags ,Intent args) { ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = taskRemoved; s.startId = startId; s.flags = flags; s.args = args; sendMessage(H.SERVICE_ARGS, s); }
ActivityThread.java
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) { //onStartCommand回調(diào) res = s.onStartCommand(data.args, data.flags, data.startId); } 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) { // nothing to do. } ensureJitEnabled(); } catch (Exception e) { ...... } } }
Service的onCreate的回調(diào)和onStartCommand的回調(diào)套路是完全一樣的,朋友們可以自己體會(huì),onCreate的回調(diào)先執(zhí)行scheduleCreateService()方法,最終回調(diào)Service.onCreate(); onStartCommand的回調(diào)先執(zhí)行scheduleServiceArgs()方法,最終回調(diào)Service.onStartCommand()
總結(jié)一下:
IActivityManager接口中定義了AMS向應(yīng)用程序(本例中即Service)提供的多種API,Activity通過(guò)ActivityManagerProxy就可以使用這些API,向AMS發(fā)出請(qǐng)求
所以是通過(guò)ActivityManagerProxy,調(diào)用ActivityManagerProxy的startService方法; 在內(nèi)部調(diào)用transact,然后會(huì)調(diào)用ActivityManagerNative中的onTransact()方法,在該方法中,將會(huì)r完成AMS與Activity的連接并調(diào)用AMS的startService()方法,那么AMS是如何Service所在的應(yīng)用程序呢?比如scheduleCreateService
原來(lái)ApplicationThreadProxy 是應(yīng)用進(jìn)程的 ApplicatonThread 對(duì)象在 AMS 端的代理,AMS 靠它來(lái)和應(yīng)用進(jìn)程進(jìn)行通信。這就是Activity與AMS之間的雙向Binder連接;Activity用IActivityManager提供的APIActivityManagerService提出執(zhí)行某個(gè)動(dòng)作的請(qǐng)求(本例中是啟動(dòng)RemoteService),ActivityManagerService通過(guò)IApplicationThread提供的API來(lái)控制Activity所在的應(yīng)用程序
上面的分析省去了很多的內(nèi)容,如果從進(jìn)程角度看服務(wù)啟動(dòng)過(guò)程。
- Process A進(jìn)程: 是指調(diào)用startService命令所在的進(jìn)程,也就是啟動(dòng)服務(wù)的發(fā)起端進(jìn)程
- system_server進(jìn)程: 系統(tǒng)進(jìn)程,是java framework框架的核心載體,里面運(yùn)行了大量的系統(tǒng)服務(wù),比如這里提供ApplicationThreadProxy,ActivityManagerService,這個(gè)兩個(gè)服務(wù)都運(yùn)行在system_server進(jìn)程的不同線程中
- Zygote進(jìn)程: 是由init進(jìn)程孵化而來(lái)的,用于創(chuàng)建Java層進(jìn)程的母體,所有的Java層進(jìn)程都是由Zygote進(jìn)程孵化而來(lái)
- Remote Service進(jìn)程: 遠(yuǎn)程服務(wù)所在進(jìn)程,是由Zygote進(jìn)程孵化而來(lái)的用于運(yùn)行Remote服務(wù)的進(jìn)程。主線程主要負(fù)責(zé)Activity/Service等組件的生命周期以及UI相關(guān)操作都運(yùn)行在這個(gè)線程; 另外,每個(gè)App進(jìn)程中至少會(huì)有兩個(gè)binder線程 ApplicationThread和ActivityManagerProxy
啟動(dòng)流程:
- Process A進(jìn)程采用Binder IPC向system_server進(jìn)程發(fā)起startService請(qǐng)求;
- system_server進(jìn)程接收到請(qǐng)求后,向zygote進(jìn)程發(fā)送創(chuàng)建進(jìn)程的請(qǐng)求;
- zygote進(jìn)程fork出新的子進(jìn)程Remote Service進(jìn)程;
- Remote Service進(jìn)程,通過(guò)Binder IPC向sytem_server進(jìn)程發(fā)起attachApplication請(qǐng)求;
- system_server進(jìn)程在收到請(qǐng)求后,進(jìn)行一系列準(zhǔn)備工作后,再通過(guò)binder IPC向remote Service進(jìn)程發(fā)送scheduleCreateService請(qǐng)求;
- Remote Service進(jìn)程的binder線程在收到請(qǐng)求后,通過(guò)handler向主線程發(fā)送CREATE_SERVICE消息;
- 主線程在收到Message后,通過(guò)發(fā)射機(jī)制創(chuàng)建目標(biāo)Service,并回調(diào)Service.onCreate()方法。 到此,服務(wù)便正式啟動(dòng)完成。當(dāng)創(chuàng)建的是本地服務(wù)或者服務(wù)所屬進(jìn)程已創(chuàng)建時(shí),則無(wú)需經(jīng)過(guò)上述步驟2、3,直接創(chuàng)建服務(wù)即可
到此這篇關(guān)于Android Service啟動(dòng)流程刨析的文章就介紹到這了,更多相關(guān)Android Service內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Android App開(kāi)發(fā)中Fragment的創(chuàng)建與生命周期
這篇文章主要介紹了Android App開(kāi)發(fā)中Fragment的創(chuàng)建與生命周期,文中詳細(xì)地介紹了Fragment的概念以及一些常用的生命周期控制方法,需要的朋友可以參考下2016-02-02flutter的環(huán)境安裝配置問(wèn)題及解決方法
Flutter是Google推出的基于Dart語(yǔ)言開(kāi)發(fā)的跨平臺(tái)開(kāi)源UI框架,旨在統(tǒng)一紛紛擾擾的跨平臺(tái)開(kāi)發(fā)框架,在UI層面上多端共用一套Dart代碼來(lái)實(shí)現(xiàn)多平臺(tái)適配開(kāi)發(fā),這篇文章主要介紹了flutter的環(huán)境安裝配置問(wèn)題,需要的朋友可以參考下2020-06-06Android懸浮按鈕點(diǎn)擊返回頂部FloatingActionButton
這篇文章主要為大家詳細(xì)介紹了Android懸浮按鈕FloatingActionButton點(diǎn)擊回到頂部的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Android 屏幕實(shí)現(xiàn)上下翻轉(zhuǎn)
這篇文章主要介紹了Android 屏幕實(shí)現(xiàn)上下翻轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下2017-07-07Android 如何獲取手機(jī)總內(nèi)存和可用內(nèi)存等信息
這篇文章主要介紹了Android系統(tǒng)檢測(cè)程序內(nèi)存占用各種方法,并對(duì)內(nèi)存信息的詳細(xì)介紹,需要的朋友可以參考下2016-07-07Android編程經(jīng)典代碼集錦(復(fù)制,粘貼,瀏覽器調(diào)用,Toast顯示,自定義Dialog等)
這篇文章主要介紹了Android編程經(jīng)典代碼集錦,包括Android的復(fù)制,粘貼,瀏覽器調(diào)用,Toast顯示,自定義Dialog等實(shí)現(xiàn)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2016-01-01Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度
本篇文章主要介紹了Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07