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