Android Service啟動綁定流程詳解
前言
本文基於Android 11,參考《Android進階解密》一書資料。瞭解Service的啟動和綁定流程,以及Service的Context創建過程。
由於基於分析流程,忽略很多細節分支。各位在看源碼的時候,要盡可能忽略細節,分析整體流程之後,還有精力的話再去看細節。例如有些屬性是在後面賦值的,如果在前面追究,難哦。
另:閱讀這種流程需要很大的耐心和毅力。建議在心情愉悅想要學習的時候搭配源碼一起食用。
一、Service 的啟動流程
1、ContextImpl.startService
啟動一個Service
,通常在Activity
調用startService
來啟動。
@Override public ComponentName startService(Intent service) { return startServiceCommon(service, false, mUser); }
2、ContextImpl.startServiceCommon
startServiceCommon
檢查intent
內容是否合法,然後做一些離開當前進程的準備操作。調用 ActivityManager.getService()
獲得AMS
的本地引用,並調用其startService
函數。
也就是說通過Binder
機制跨進程通信調用瞭AMS
的startService
函數。
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { //檢查intent 的compant和package是否合法 validateServiceIntent(service); ... ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier()); ... return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
通過 ActivityManager.getService()
的實現。
@UnsupportedAppUsage public static IActivityManager getService() { return IActivityManagerSingleton.get(); } @UnsupportedAppUsage private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
3、AMS.startService
AMS.startService
函數獲取調用Pid
和Uid
,然後調用ActiveService
的startServiceLocked
函數。
@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, String callingFeatureId, 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, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
4、ActiveService.startServiceLock
ActiveService.startServiceLock
函數,對一些合法性的檢查,例如前臺Service
的權限、限制性後臺Service
進行延遲運行(standby)
。並將要啟動的信息封裝成ServiceRecord
。然後調用瞭startServiceInnerLocked
函數。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, callingPackage, callingFeatureId, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { final boolean callerFg; if (caller != null) { //獲取調用Service的應用程序進程描述 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { ... } callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; } else { callerFg = true; } //檢索ServiceRecord,包括同應用和其他應用 ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); ... //要啟動的ServiceRecord ServiceRecord r = res.record; ... r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.fgRequired = fgRequired; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid)); ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); ... return cmp; }
5、ActiveServices.startServiceInnerLocker
調用瞭bringUpServiceLocked
函數,會將ServiceRecord
添加到ServiceMap
類型的smap
集合,進行緩存。
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { r.callStart = false; ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); ... return r.name; }
6、 ActiveService.bringUpServiceLocked
分析一:首次啟動Service
時,在執行bringUpServiceLocked
函數,ServiceRecord
是屬於新創建的,而非從AMS
的緩存mServices
中檢索而來,所以此時的ServiceRecord
的ProcessRecord
類型app
和IApplicationThread
類型thread
都是null。隻有啟動過後的ServiceRecord
才有值,才會執行sendServiceArgsLocked
函數,重復調用Service
的生命周期onStartCommand
,而不調用onCreate
函數。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { //分析一:未啟動過的ServiceRecord兩者都是null,重復啟動會執行該函數, //會重復調用service的onStartCommand函數。 if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); return null; } ... final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; HostingRecord hostingRecord = new HostingRecord("service", r.instanceName); ProcessRecord app; if (!isolated) { ////通過AMS獲取service所在進程的ProcessRecord。ProcessList=>MyProcessMap=》會緩存已創建過進程的ProcessRecord 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; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e); } } } //如果service所在的進程未啟動,通過AMS啟動該進程,可以參考應用進程的啟動流程 if (app == null && !permissionsReviewRequired) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {; bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc = app; } } //等待進程啟動完畢重啟啟動 if (!mPendingServices.contains(r)) { mPendingServices.add(r); } ... return null; }
7、ActiveService.realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //將ProcessRecord設置給ServiceRecord r.setProcess(app); //登記當ServiceRecord到ProcessRecordd的數組mServices,表示Service已經啟動(實際未啟動) final boolean newService = app.startService(r); boolean created = false; try { ... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); ... } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app, "Died when creating service"); throw e; } //會調用Service的onStartCommand函數 sendServiceArgsLocked(r, execInFg, true); ... }
通過ProcessRecord
對象的IApplicationThread
引用,通過Binder
機制調用瞭應用程序的ApplicationThread
的scheduleCreateService
函數。
8、ApplicationThread.scheduleCreateService
將ServiceInfo
等相關信息封裝到CreateServiceData
中,並發送給ActivityThread
的H
類型的mH
對象。
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); }
9、H.handleMesssage
調用瞭ActivityThread
的handleCreateService
函數。
case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break;
10、ActivityThread.handleCreateService
private void handleCreateService(CreateServiceData data) { ... //獲取當前應用的描述信息LoadedApk LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //創建Service的上下問文 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //獲取當前應用Applcation對象 Application app = packageInfo.makeApplication(false, mInstrumentation); //通過反射創建Service對象 java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); //初始化資源 context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //context 與service相互綁定 context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //調用Service的生命周期onCreate函數,意味Service創建完畢 service.onCreate(); //緩存Service 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); } } }
通過ContextImpl.createAppContext
創建Service
的上下文context
,通過packageInfo.getAppFactory().instantiateService
反射獲得當前Service
對象service
,將context
與service
相互綁定。然後調用service.onCreate
。至此,Service
創建完畢。
二、Service的綁定
1、 ContextImpl.bindService
public boolean bindService(Intent service, ServiceConnection conn, int flags) { //系統進程調用綁定服務或發送廣播都會發出警告 warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); }
2、ContextImpl.bindServiceCommon
在分析一,主要判斷入參Executor executor
或UserHandle user
哪個為null
,總有一個為null
,但最終都是調用瞭LoadedApk
的getServiceDispatcherCommon
函數來獲取ServiceDispathcer
類型sd。影響隻是回調代碼是在主線程執行,還是線程池。這裡傳入ActivityThread
的H
對象,意味著後續連接成功回調onServiceConnected
是在主線程。
分析二:通過Binder機制調用AMS
的bindIsolatedService
函數。
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser. IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (handler != null && executor != null) { throw new IllegalArgumentException("Handler and Executor both supplied"); } if (mPackageInfo != null) { if (executor != null) {//分析一:無論哪個分支,都是獲得ServiceConnect的本地引用sd,兩者最終都是 //調用LoadedApk的getServiceDispatcherCommon sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { //正常使用走這個分支 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } } else { throw new RuntimeException("Not supported in system context"); } //檢查compant and package is null ? validateServiceIntent(service); try { IBinder token = getActivityToken(); if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null && mPackageInfo.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } service.prepareToLeaveProcess(this); //分析二:調用AMS.bindIsolatedService int res = ActivityManager.getService().bindIsolatedService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, instanceName, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
IServiceConnection
連接的創建會先從緩存中獲取,避免每次都要新建。分析一:通過executor
或handler
創建ServiceDispatcher
類型的sd
,含有靜態內部類InnerConnection
的引用mIServiceConnection
。繼承自IServiceConnection.Stub
,也就是InnerConnection
是實現者,遠程調用代理在其他進程,例如SystemServer
進程中的ActiveService
。
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c, Context context, Handler handler, Executor executor, 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) { //分析一:通過executor或handler創建ServiceDispatcher if (executor != null) { sd = new ServiceDispatcher(c, context, executor, flags); } else { sd = new ServiceDispatcher(c, context, handler, flags); } if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); if (map == null) { map = new ArrayMap<>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler, executor); } return sd.getIServiceConnection(); } }
3、AMS.bindIsolatedService
AMS
經過兩次重載函數bindIsolatedService
調用,簡單檢查相關合法性。然後調用ActiveService
類型的mService
的bindServiceLocked
函數。
4、ActiveService.bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { //發起綁定service的app進程描述 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); ... ServiceLookupResult res = retrieveServiceLocked(service, instanceName, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant); ... ServiceRecord s = res.record; ... //描述Service和應用程序進程之間的關聯,內部維護Service、進程、IntentFilter以及所有綁定信息。 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //描述應用程序與service建立的一次通信(綁定) ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent, callerApp.uid, callerApp.processName, callingPackage); IBinder binder = connection.asBinder(); s.addConnection(binder, c); b.connections.add(c); if (activity != null) { activity.addConnection(c); } b.client.connections.add(c); c.startAssociationIfNeeded(); ... //啟動Service,可以參考Service的啟動 if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } ... //表示Service已啟動,且已返回binder,可以通過binder訪問接口 if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. try { //建立連接 c.conn.connected(s.name, b.intent.binder, false); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + s.shortInstanceName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } //第一個綁定該Service的進程,且要重綁 if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) {//首次綁定,執行此次 requestServiceBindingLocked(s, b.intent, callerFg, false); } ... }
AppBindRecord
描述應用程序進程和Service
的關聯,包括誰綁定瞭Service
的ProcessRecord
,綁定信息IntentBindRecord
,當前服務ServiceRecord
,當前應用進程的所有連接記錄connections
。
5、requestServiceBindingLocked
調用瞭ApplicationThread
的scheduleBindService
函數。
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.getReportedProcState()); ... }
6、ApplicationThread.scheduleBindService
將數據封裝 BindServiceData
,發送個ActivityThread
的H類型的mH
處理。
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; sendMessage(H.BIND_SERVICE, s); }
7 、 H.handleMessage
case BIND_SERVICE: handleBindService((BindServiceData)msg.obj);
8、ActivityThread.handleBindService
handleBindService
函數有兩個分支,即是否重新綁定。
如果當前進程第一個與Service
綁定,且調用過瞭onUbBinder
方法,那麼這裡的data.rebind
將為true
,直接執行Service
的onRebind
函數即可。另外一種就是沒有綁定過,那麼需要執行Service
的onBind
函數。然後還要執行AMS
的publishService
函數。
private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { ... try { if (!data.rebind) { 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); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ... } }
9、AMS.publishService
public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
10、ActiveService.publishServiceLocked
分析一:可見在第4步bindServiceLocked
函數,IntentBindRecord
對象的屬性binder
、requested
、received
都是false
。
在ServiceRecord
的所有連接記錄connections
中,通過intent
查找對應之前已經保存的ConnectionRecord
,並調用其IServiceConnection
的connected
函數。
在第2步的時候調用bindServiceCommon
函數時,會創建ServiceDispatcher
時,內部持有InnerConnection
實例,這裡的IServiceConnection
代理引用指向該InnerConnection
實例,這裡會調用其connected
函數。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) {//分析1 b.binder = service; b.requested = true; b.received = true; ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections(); for (int conni = connections.size() - 1; conni >= 0; conni--) { ArrayList<ConnectionRecord> clist = connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { ... continue; } ... try { c.conn.connected(r.name, service, false); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.shortInstanceName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }
11、InnerConnection.connected
private static class InnerConnection extends IServiceConnection.Stub { @UnsupportedAppUsage 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); } } }
12、ServiceDispatcher.connected
這裡調用瞭 mActivityThread.post(new RunConnection(name, service, 0, dead))
,執行RunConnection
的run
函數。這裡的話run函數執行代碼又回到瞭應用進程的主線程。
public void connected(ComponentName name, IBinder service, boolean dead) { if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } }
13、RunConnection.run
RunConnection
是ServiceDispatcher
的內部類,這裡執行SD
的doConnected
函數。
public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } }
14、ServiceDispatcher.doConnected
這裡調用瞭ServiceConnection
對象的onServiceConnected
函數,也就是我們發起綁定,調用context.bindService
的參數。
public void doConnected(ComponentName name, IBinder service, boolean dead) { ... mConnection.onServiceConnected(name, service); ... }
到此,Service
的綁定流程分析完畢。
三、Service的Context
在第一節Service的啟動流程最後函數調用瞭ActivityThread
的handleCreateService
函數。
private void handleCreateService(CreateServiceData data) { unscheduleGcIdler(); //應用的描述信息 LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //分析一 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); Application app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //分析二 context.setOuterContext(service); //分析三 service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); 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); } } }
分析一:通過ContextImpl
的靜態函數createAppContext
返回瞭一個ContextImpl
類型的context
。createAppContext
又調用瞭重載函數createAppContext
。直接新建瞭ContextImpl實例context,構造函數傳遞瞭ActivityThread類型的mainThread和LoadedApk類型的packageInfo。並給context設置瞭資源環境和是否Syetem屬性。
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { return createAppContext(mainThread, packageInfo, null); } static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo, String opPackageName) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null, 0, null, opPackageName); context.setResources(packageInfo.getResources()); context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context); return context; }
ContextImpl
類有一個Context
類型的mOuterContext
屬性,在構造函數時指向瞭自己。
回到handleCreateService
函數的分析二,在創建好Service
對象service
之後,將service
作為參數傳遞給瞭context.setOuterContext
函數。Service
本身繼承自ContextWrapper
,ContextWrapper
又是Context
的子類。這時候的setOuterContext
函數將service
設置給瞭context
的mOuterContext
屬性。意味著當前上下文context
持有當前新建的service
引用。
在分析三,調用瞭service.attach
函數,context
並作為第一個參數被傳入。attach
函數又調用瞭attachBaseContext
函數。
public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) { attachBaseContext(context); mThread = thread; mClassName = className; mToken = token; mApplication = application; mActivityManager = (IActivityManager)activityManager; mStartCompatibility = getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR; setContentCaptureOptions(application.getContentCaptureOptions()); }
attachBaseContext
調用瞭父類ContextWrapper
的attachBaseContext
函數
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); if (newBase != null) { newBase.setContentCaptureOptions(getContentCaptureOptions()); } }
ContextWrapper
將一路傳遞過來的上下文base
設置給你瞭mBase
屬性。
protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; }
也就是說,我們在啟動Service
時,會同時創建Service
的上下文context
,並將其存儲到Service的父類ContextWrapper
的mBases
屬性中,同時context
也會有當前Service引用,存儲在mOuterContext
變量中。
總結
Service
的啟動和綁定從AMS
轉移到ActiveService
Service
的啟動,會先判斷進程是否創建,提前啟動進程,再啟動自己。Service
重復啟動,會重復調用onStratCommand
及後續生命周期函數。Service
的綁定,會先走一趟Service
的啟動流程,再綁定。- 應用進程與
SytemServer
進程(AMS、ActiveService)
的交互式通過Binder機制進行,通過AIDL
各持有雙方接口。應用進程通過H對象,將現成重新切回主線程(所有應用誇進程通信應如此)。 Service
在應用和AMS
兩邊都會做緩存,以便快速在找到使用。應用程序存儲在ArrayMap<IBinder, Service>
類型的mServices
;ActiveService
則是ArraySet<ServiceRecord>
類型的mServices
。
以上就是Service啟動綁定流程詳解的詳細內容,更多關於Service啟動綁定流程的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Android Service完整實現流程分析
- Android Broadcast原理分析之registerReceiver詳解
- Android BindService使用案例講解
- android Service基礎(啟動服務與綁定服務)
- 解析Android AIDL的實例與原理