Android?Service啟動(dòng)綁定流程詳解
前言
本文基于Android 11,參考《Android進(jìn)階解密》一書資料。了解Service的啟動(dòng)和綁定流程,以及Service的Context創(chuàng)建過程。
由于基于分析流程,忽略很多細(xì)節(jié)分支。各位在看源碼的時(shí)候,要盡可能忽略細(xì)節(jié),分析整體流程之后,還有精力的話再去看細(xì)節(jié)。例如有些屬性是在后面賦值的,如果在前面追究,難哦。
另:閱讀這種流程需要很大的耐心和毅力。建議在心情愉悅想要學(xué)習(xí)的時(shí)候搭配源碼一起食用。
一、Service 的啟動(dòng)流程
1、ContextImpl.startService
啟動(dòng)一個(gè)Service
,通常在Activity
調(diào)用startService
來啟動(dòng)。
@Override public ComponentName startService(Intent service) { return startServiceCommon(service, false, mUser); }
2、ContextImpl.startServiceCommon
startServiceCommon
檢查intent
內(nèi)容是否合法,然后做一些離開當(dāng)前進(jìn)程的準(zhǔn)備操作。調(diào)用 ActivityManager.getService()
獲得AMS
的本地引用,并調(diào)用其startService
函數(shù)。
也就是說通過Binder
機(jī)制跨進(jìn)程通信調(diào)用了AMS
的startService
函數(shù)。
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()
的實(shí)現(xiàn)。
@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
函數(shù)獲取調(diào)用Pid
和Uid
,然后調(diào)用ActiveService
的startServiceLocked
函數(shù)。
@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
函數(shù),對一些合法性的檢查,例如前臺(tái)Service
的權(quán)限、限制性后臺(tái)Service
進(jìn)行延遲運(yùn)行(standby)
。并將要啟動(dòng)的信息封裝成ServiceRecord
。然后調(diào)用了startServiceInnerLocked
函數(shù)。
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) { //獲取調(diào)用Service的應(yīng)用程序進(jìn)程描述 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { ... } callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; } else { callerFg = true; } //檢索ServiceRecord,包括同應(yīng)用和其他應(yīng)用 ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); ... //要啟動(dòng)的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
調(diào)用了bringUpServiceLocked
函數(shù),會(huì)將ServiceRecord
添加到ServiceMap
類型的smap
集合,進(jìn)行緩存。
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
分析一:首次啟動(dòng)Service
時(shí),在執(zhí)行bringUpServiceLocked
函數(shù),ServiceRecord
是屬于新創(chuàng)建的,而非從AMS
的緩存mServices
中檢索而來,所以此時(shí)的ServiceRecord
的ProcessRecord
類型app
和IApplicationThread
類型thread
都是null。只有啟動(dòng)過后的ServiceRecord
才有值,才會(huì)執(zhí)行sendServiceArgsLocked
函數(shù),重復(fù)調(diào)用Service
的生命周期onStartCommand
,而不調(diào)用onCreate
函數(shù)。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { //分析一:未啟動(dòng)過的ServiceRecord兩者都是null,重復(fù)啟動(dòng)會(huì)執(zhí)行該函數(shù), //會(huì)重復(fù)調(diào)用service的onStartCommand函數(shù)。 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所在進(jìn)程的ProcessRecord。ProcessList=>MyProcessMap=》會(huì)緩存已創(chuàng)建過進(jìn)程的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); //啟動(dòng)服務(wù) 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所在的進(jìn)程未啟動(dòng),通過AMS啟動(dòng)該進(jìn)程,可以參考應(yīng)用進(jìn)程的啟動(dòng)流程 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; } } //等待進(jìn)程啟動(dòng)完畢重啟啟動(dòng) 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設(shè)置給ServiceRecord r.setProcess(app); //登記當(dāng)ServiceRecord到ProcessRecordd的數(shù)組mServices,表示Service已經(jīng)啟動(dòng)(實(shí)際未啟動(dòng)) 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; } //會(huì)調(diào)用Service的onStartCommand函數(shù) sendServiceArgsLocked(r, execInFg, true); ... }
通過ProcessRecord
對象的IApplicationThread
引用,通過Binder
機(jī)制調(diào)用了應(yīng)用程序的ApplicationThread
的scheduleCreateService
函數(shù)。
8、ApplicationThread.scheduleCreateService
將ServiceInfo
等相關(guān)信息封裝到CreateServiceData
中,并發(fā)送給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
調(diào)用了ActivityThread
的handleCreateService
函數(shù)。
case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break;
10、ActivityThread.handleCreateService
private void handleCreateService(CreateServiceData data) { ... //獲取當(dāng)前應(yīng)用的描述信息LoadedApk LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //創(chuàng)建Service的上下問文 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //獲取當(dāng)前應(yīng)用Applcation對象 Application app = packageInfo.makeApplication(false, mInstrumentation); //通過反射創(chuàng)建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()); //調(diào)用Service的生命周期onCreate函數(shù),意味Service創(chuàng)建完畢 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
創(chuàng)建Service
的上下文context
,通過packageInfo.getAppFactory().instantiateService
反射獲得當(dāng)前Service
對象service
,將context
與service
相互綁定。然后調(diào)用service.onCreate
。至此,Service
創(chuàng)建完畢。
二、Service的綁定
1、 ContextImpl.bindService
public boolean bindService(Intent service, ServiceConnection conn, int flags) { //系統(tǒng)進(jìn)程調(diào)用綁定服務(wù)或發(fā)送廣播都會(huì)發(fā)出警告 warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); }
2、ContextImpl.bindServiceCommon
在分析一,主要判斷入?yún)?code>Executor executor或UserHandle user
哪個(gè)為null
,總有一個(gè)為null
,但最終都是調(diào)用了LoadedApk
的getServiceDispatcherCommon
函數(shù)來獲取ServiceDispathcer
類型sd。影響只是回調(diào)代碼是在主線程執(zhí)行,還是線程池。這里傳入ActivityThread
的H
對象,意味著后續(xù)連接成功回調(diào)onServiceConnected
是在主線程。
分析二:通過Binder機(jī)制調(diào)用AMS
的bindIsolatedService
函數(shù)。
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) {//分析一:無論哪個(gè)分支,都是獲得ServiceConnect的本地引用sd,兩者最終都是 //調(diào)用LoadedApk的getServiceDispatcherCommon sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { //正常使用走這個(gè)分支 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); //分析二:調(diào)用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
連接的創(chuàng)建會(huì)先從緩存中獲取,避免每次都要新建。分析一:通過executor
或handler
創(chuàng)建ServiceDispatcher
類型的sd
,含有靜態(tài)內(nèi)部類InnerConnection
的引用mIServiceConnection
。繼承自IServiceConnection.Stub
,也就是InnerConnection
是實(shí)現(xiàn)者,遠(yuǎn)程調(diào)用代理在其他進(jìn)程,例如SystemServer
進(jìn)程中的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創(chuàng)建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
經(jīng)過兩次重載函數(shù)bindIsolatedService
調(diào)用,簡單檢查相關(guān)合法性。然后調(diào)用ActiveService
類型的mService
的bindServiceLocked
函數(shù)。
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 { //發(fā)起綁定service的app進(jìn)程描述 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和應(yīng)用程序進(jìn)程之間的關(guān)聯(lián),內(nèi)部維護(hù)Service、進(jìn)程、IntentFilter以及所有綁定信息。 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //描述應(yīng)用程序與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(); ... //啟動(dòng)Service,可以參考Service的啟動(dòng) if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } ... //表示Service已啟動(dòng),且已返回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); } //第一個(gè)綁定該Service的進(jìn)程,且要重綁 if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) {//首次綁定,執(zhí)行此次 requestServiceBindingLocked(s, b.intent, callerFg, false); } ... }
AppBindRecord
描述應(yīng)用程序進(jìn)程和Service
的關(guān)聯(lián),包括誰綁定了Service
的ProcessRecord
,綁定信息IntentBindRecord
,當(dāng)前服務(wù)ServiceRecord
,當(dāng)前應(yīng)用進(jìn)程的所有連接記錄connections
。
5、requestServiceBindingLocked
調(diào)用了ApplicationThread
的scheduleBindService
函數(shù)。
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
將數(shù)據(jù)封裝 BindServiceData
,發(fā)送個(gè)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
函數(shù)有兩個(gè)分支,即是否重新綁定。
如果當(dāng)前進(jìn)程第一個(gè)與Service
綁定,且調(diào)用過了onUbBinder
方法,那么這里的data.rebind
將為true
,直接執(zhí)行Service
的onRebind
函數(shù)即可。另外一種就是沒有綁定過,那么需要執(zhí)行Service
的onBind
函數(shù)。然后還要執(zhí)行AMS
的publishService
函數(shù)。
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
函數(shù),IntentBindRecord
對象的屬性binder
、requested
、received
都是false
。
在ServiceRecord
的所有連接記錄connections
中,通過intent
查找對應(yīng)之前已經(jīng)保存的ConnectionRecord
,并調(diào)用其IServiceConnection
的connected
函數(shù)。
在第2步的時(shí)候調(diào)用bindServiceCommon
函數(shù)時(shí),會(huì)創(chuàng)建ServiceDispatcher
時(shí),內(nèi)部持有InnerConnection
實(shí)例,這里的IServiceConnection
代理引用指向該InnerConnection
實(shí)例,這里會(huì)調(diào)用其connected
函數(shù)。
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
這里調(diào)用了 mActivityThread.post(new RunConnection(name, service, 0, dead))
,執(zhí)行RunConnection
的run
函數(shù)。這里的話run函數(shù)執(zhí)行代碼又回到了應(yīng)用進(jìn)程的主線程。
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
的內(nèi)部類,這里執(zhí)行SD
的doConnected
函數(shù)。
public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } }
14、ServiceDispatcher.doConnected
這里調(diào)用了ServiceConnection
對象的onServiceConnected
函數(shù),也就是我們發(fā)起綁定,調(diào)用context.bindService
的參數(shù)。
public void doConnected(ComponentName name, IBinder service, boolean dead) { ... mConnection.onServiceConnected(name, service); ... }
到此,Service
的綁定流程分析完畢。
三、Service的Context
在第一節(jié)Service的啟動(dòng)流程最后函數(shù)調(diào)用了ActivityThread
的handleCreateService
函數(shù)。
private void handleCreateService(CreateServiceData data) { unscheduleGcIdler(); //應(yīng)用的描述信息 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
的靜態(tài)函數(shù)createAppContext
返回了一個(gè)ContextImpl
類型的context
。createAppContext
又調(diào)用了重載函數(shù)createAppContext
。直接新建了ContextImpl實(shí)例context,構(gòu)造函數(shù)傳遞了ActivityThread類型的mainThread和LoadedApk類型的packageInfo。并給context設(shè)置了資源環(huán)境和是否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
類有一個(gè)Context
類型的mOuterContext
屬性,在構(gòu)造函數(shù)時(shí)指向了自己。
回到handleCreateService
函數(shù)的分析二,在創(chuàng)建好Service
對象service
之后,將service
作為參數(shù)傳遞給了context.setOuterContext
函數(shù)。Service
本身繼承自ContextWrapper
,ContextWrapper
又是Context
的子類。這時(shí)候的setOuterContext
函數(shù)將service
設(shè)置給了context
的mOuterContext
屬性。意味著當(dāng)前上下文context
持有當(dāng)前新建的service
引用。
在分析三,調(diào)用了service.attach
函數(shù),context
并作為第一個(gè)參數(shù)被傳入。attach
函數(shù)又調(diào)用了attachBaseContext
函數(shù)。
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
調(diào)用了父類ContextWrapper
的attachBaseContext
函數(shù)
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); if (newBase != null) { newBase.setContentCaptureOptions(getContentCaptureOptions()); } }
ContextWrapper
將一路傳遞過來的上下文base
設(shè)置給你了mBase
屬性。
protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; }
也就是說,我們在啟動(dòng)Service
時(shí),會(huì)同時(shí)創(chuàng)建Service
的上下文context
,并將其存儲(chǔ)到Service的父類ContextWrapper
的mBases
屬性中,同時(shí)context
也會(huì)有當(dāng)前Service引用,存儲(chǔ)在mOuterContext
變量中。
總結(jié)
Service
的啟動(dòng)和綁定從AMS
轉(zhuǎn)移到ActiveService
Service
的啟動(dòng),會(huì)先判斷進(jìn)程是否創(chuàng)建,提前啟動(dòng)進(jìn)程,再啟動(dòng)自己。Service
重復(fù)啟動(dòng),會(huì)重復(fù)調(diào)用onStratCommand
及后續(xù)生命周期函數(shù)。Service
的綁定,會(huì)先走一趟Service
的啟動(dòng)流程,再綁定。- 應(yīng)用進(jìn)程與
SytemServer
進(jìn)程(AMS、ActiveService)
的交互式通過Binder機(jī)制進(jìn)行,通過AIDL
各持有雙方接口。應(yīng)用進(jìn)程通過H對象,將現(xiàn)成重新切回主線程(所有應(yīng)用夸進(jìn)程通信應(yīng)如此)。 Service
在應(yīng)用和AMS
兩邊都會(huì)做緩存,以便快速在找到使用。應(yīng)用程序存儲(chǔ)在ArrayMap<IBinder, Service>
類型的mServices
;ActiveService
則是ArraySet<ServiceRecord>
類型的mServices
。
以上就是Service啟動(dòng)綁定流程詳解的詳細(xì)內(nèi)容,更多關(guān)于Service啟動(dòng)綁定流程的資料請關(guān)注腳本之家其它相關(guān)文章!
- Android布局控件View?ViewRootImpl?WindowManagerService關(guān)系
- android?微信搶紅包工具AccessibilityService實(shí)現(xiàn)詳解
- Android?O對后臺(tái)Service限制詳解
- Android?NotificationListenerService通知監(jiān)聽服務(wù)使用
- Android?NotificationListenerService?通知服務(wù)原理解析
- Android開發(fā)InputManagerService創(chuàng)建與啟動(dòng)流程
- Android 10 啟動(dòng)之servicemanager源碼解析
- Android 開機(jī)自啟動(dòng)Service實(shí)現(xiàn)詳解
相關(guān)文章
Android調(diào)用系統(tǒng)圖片裁剪限定尺寸及7.0照相問題的解決方法
這篇文章主要介紹了Android調(diào)用系統(tǒng)圖片裁剪限定尺寸,及7.0照相問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07點(diǎn)九圖片的顯示內(nèi)容區(qū)域應(yīng)作何理解
.9 ,是andriod平臺(tái)的應(yīng)用軟件開發(fā)里的一種特殊的圖片形式,文件擴(kuò)展名為:.9.png;點(diǎn)九圖片的拉伸區(qū)域不難理解,顯示內(nèi)容區(qū)域是怎樣的,接下來本文為您一一解答,感興趣的朋友可以了解下2013-01-01簡單實(shí)現(xiàn)Android學(xué)生管理系統(tǒng)(附源碼)
這篇文章主要介紹了如何簡單實(shí)現(xiàn)Android學(xué)生管理系統(tǒng),特別適合計(jì)算機(jī)專業(yè)的即將畢業(yè)的同學(xué)學(xué)習(xí)借鑒制作學(xué)生管理系統(tǒng),感興趣的小伙伴們可以參考一下2015-12-12詳解Android中常見的內(nèi)存優(yōu)化及內(nèi)存泄露場景
本文主要給大家介紹了Android中常見的內(nèi)存優(yōu)化及Android開發(fā)中容易造成內(nèi)存泄露的場景,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-08-08Android開發(fā)實(shí)現(xiàn)的ViewPager引導(dǎo)頁功能(動(dòng)態(tài)加載指示器)詳解
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)的ViewPager引導(dǎo)頁功能(動(dòng)態(tài)加載指示器),結(jié)合實(shí)例形式詳細(xì)分析了Android使用ViewPager引導(dǎo)頁的具體步驟,相關(guān)布局、功能使用技巧,需要的朋友可以參考下2017-11-11Android 檢查更新、下載、安裝功能的實(shí)現(xiàn)
這篇文章主要介紹了Android 檢查更新、下載、安裝功能的實(shí)現(xiàn)的相關(guān)資料,這里附有實(shí)例代碼,具有一定的參考價(jià)值,需要的朋友可以參考下2017-01-01ListView實(shí)現(xiàn)下拉動(dòng)態(tài)渲染數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了ListView實(shí)現(xiàn)下拉動(dòng)態(tài)渲染數(shù)據(jù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06