Android?Service啟動流程刨析
強調(diào)一下閱讀系統(tǒng)源碼,起碼要對進程間通信要了解,對binder機制非常非常清楚,binder就是指南針,要不然你會暈頭轉(zhuǎn)向;強行閱讀,就容易睡著。
Service啟動先來一張圖感受一下
這張圖能夠說明一個大致的流程,但是服務(wù)的啟動肯定不是這么簡單,但是我們先簡單的總結(jié)一下,逐漸深入。服務(wù)的啟動形式有兩種,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 { //檢驗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); } }
校驗完Intent后,就調(diào)用ActivityManagerNative.getDefault(),獲取一個IActivityManager對象,將啟動Service這件事情交給了IActivityManager。我們看一下ActivityManagerNative的類定義
public abstract class ActivityManagerNative extends Binder implements IActivityManager
這種模式是不是非常熟悉??? 繼承了Binder,實現(xiàn)了一個IActivityManager接口,這個跟我們生成了遠程服務(wù)通信生成的AIDL的java文件怎么那么像,現(xiàn)在告訴你,這就是為了遠程服務(wù)通信做準備的,只是一般這種類我們都是自動生成的,ActivityManagerNative 是谷歌的人自己寫
一個完整的AID L有兩部分,一個是個跟服務(wù)端通信的Stub,一個是跟客戶端通信的Proxy; ActivityManagerNative就是Stub,閱讀源碼發(fā)現(xiàn)在ActivityManagerNative 文件中還有個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ù)都注冊到ServiceManager來統(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; } };
就是一個單例設(shè)計模式,獲取到服務(wù)對象IBinder,把這個IBinder轉(zhuǎn)換成IActivityManager返回了。現(xiàn)在由IActivityManager啟動服務(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; }
上面說了ActivityManagerProxy作為binder通信的客戶端,ActivityManagerNative 作為binder通信的服務(wù)端; mRemote.transact()是binder通信的客戶端發(fā)起方法,經(jīng)過binder驅(qū)動,最后回到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的真正實現(xiàn)是ActivityManagerService,所以binder通信的服務(wù)端的ActivityManagerService,ActivityManagerProxy.startService()最終調(diào)用ActivityManagerService.startService()。注意這就跨進程了,ActivityManagerService是一個服務(wù)端的進程。看ActivityManagerService中的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沒有直接干這個活,而是把這個任務(wù)交給了mService, mService 是一個 ActiveServices 對象。在早期的安卓版本中并沒有這個類,后來重構(gòu)時抽出這個類專門用來管理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)); } // 進入onStartCommand() sendServiceArgsLocked(r, execInFg, true); .... }
這里的關(guān)鍵是
app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app 是要運行 Service 的進程對應(yīng)的 ProcessRecord 對象,代表一個應(yīng)用進程; 要區(qū)分一下,一般我們都是單方向通信,客戶端將處理請求發(fā)送給服務(wù)端,服務(wù)端處理后返回,如果要服務(wù)端向客戶端發(fā)送一個“請求”呢?這里的thread 是一個 ApplicationThreadProxy 對象,它是應(yīng)用進程的 ApplicatonThread 對象在 AMS 端的代理,AMS 靠它來和應(yīng)用進程進行通信。所以AMS和應(yīng)用進程可以雙向通信了。
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后,就會回調(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ā)送一個消息,這個消息都是由H類處理的,H類就是系統(tǒng)Hander,專門處理系統(tǒng)請求的; 比如一些Activity的生命周期等全在這里面。這個 H對象是在應(yīng)用進程的主線程中創(chuàng)建的,所以最終的結(jié)果是把創(chuàng)建 Service 的消息傳到了主線程,因此Service是運行在主線程中的。
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對象 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); //創(chuàng)建Application對象 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()何時回調(diào)呢?在realStartServiceLocked中調(diào)用了sendServiceArgsLocked(r, execInFg, true),sendServiceArgsLocked與上面類似,最終也是發(fā)送了一個(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)套路是完全一樣的,朋友們可以自己體會,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通過ActivityManagerProxy就可以使用這些API,向AMS發(fā)出請求
所以是通過ActivityManagerProxy,調(diào)用ActivityManagerProxy的startService方法; 在內(nèi)部調(diào)用transact,然后會調(diào)用ActivityManagerNative中的onTransact()方法,在該方法中,將會r完成AMS與Activity的連接并調(diào)用AMS的startService()方法,那么AMS是如何Service所在的應(yīng)用程序呢?比如scheduleCreateService
原來ApplicationThreadProxy 是應(yīng)用進程的 ApplicatonThread 對象在 AMS 端的代理,AMS 靠它來和應(yīng)用進程進行通信。這就是Activity與AMS之間的雙向Binder連接;Activity用IActivityManager提供的APIActivityManagerService提出執(zhí)行某個動作的請求(本例中是啟動RemoteService),ActivityManagerService通過IApplicationThread提供的API來控制Activity所在的應(yīng)用程序
上面的分析省去了很多的內(nèi)容,如果從進程角度看服務(wù)啟動過程。
- Process A進程: 是指調(diào)用startService命令所在的進程,也就是啟動服務(wù)的發(fā)起端進程
- system_server進程: 系統(tǒng)進程,是java framework框架的核心載體,里面運行了大量的系統(tǒng)服務(wù),比如這里提供ApplicationThreadProxy,ActivityManagerService,這個兩個服務(wù)都運行在system_server進程的不同線程中
- Zygote進程: 是由init進程孵化而來的,用于創(chuàng)建Java層進程的母體,所有的Java層進程都是由Zygote進程孵化而來
- Remote Service進程: 遠程服務(wù)所在進程,是由Zygote進程孵化而來的用于運行Remote服務(wù)的進程。主線程主要負責Activity/Service等組件的生命周期以及UI相關(guān)操作都運行在這個線程; 另外,每個App進程中至少會有兩個binder線程 ApplicationThread和ActivityManagerProxy
啟動流程:
- Process A進程采用Binder IPC向system_server進程發(fā)起startService請求;
- system_server進程接收到請求后,向zygote進程發(fā)送創(chuàng)建進程的請求;
- zygote進程fork出新的子進程Remote Service進程;
- Remote Service進程,通過Binder IPC向sytem_server進程發(fā)起attachApplication請求;
- system_server進程在收到請求后,進行一系列準備工作后,再通過binder IPC向remote Service進程發(fā)送scheduleCreateService請求;
- Remote Service進程的binder線程在收到請求后,通過handler向主線程發(fā)送CREATE_SERVICE消息;
- 主線程在收到Message后,通過發(fā)射機制創(chuàng)建目標Service,并回調(diào)Service.onCreate()方法。 到此,服務(wù)便正式啟動完成。當創(chuàng)建的是本地服務(wù)或者服務(wù)所屬進程已創(chuàng)建時,則無需經(jīng)過上述步驟2、3,直接創(chuàng)建服務(wù)即可
到此這篇關(guān)于Android Service啟動流程刨析的文章就介紹到這了,更多相關(guān)Android Service內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Android App開發(fā)中Fragment的創(chuàng)建與生命周期
這篇文章主要介紹了Android App開發(fā)中Fragment的創(chuàng)建與生命周期,文中詳細地介紹了Fragment的概念以及一些常用的生命周期控制方法,需要的朋友可以參考下2016-02-02Android懸浮按鈕點擊返回頂部FloatingActionButton
這篇文章主要為大家詳細介紹了Android懸浮按鈕FloatingActionButton點擊回到頂部的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android 如何獲取手機總內(nèi)存和可用內(nèi)存等信息
這篇文章主要介紹了Android系統(tǒng)檢測程序內(nèi)存占用各種方法,并對內(nèi)存信息的詳細介紹,需要的朋友可以參考下2016-07-07Android編程經(jīng)典代碼集錦(復(fù)制,粘貼,瀏覽器調(diào)用,Toast顯示,自定義Dialog等)
這篇文章主要介紹了Android編程經(jīng)典代碼集錦,包括Android的復(fù)制,粘貼,瀏覽器調(diào)用,Toast顯示,自定義Dialog等實現(xiàn)技巧,非常簡單實用,需要的朋友可以參考下2016-01-01Android中實現(xiàn)OkHttp上傳文件到服務(wù)器并帶進度
本篇文章主要介紹了Android中實現(xiàn)OkHttp上傳文件到服務(wù)器并帶進度,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07