<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文基於Android 11,參考《Android進階解密》一書資料。瞭解Service的啟動和繫結流程,以及Service的Context建立過程。
由於基於分析流程,忽略很多細節分支。各位在看原始碼的時候,要儘可能忽略細節,分析整體流程之後,還有精力的話再去看細節。例如有些屬性是在後面賦值的,如果在前面追究,難哦。
另:閱讀這種流程需要很大的耐心和毅力。建議在心情愉悅想要學習的時候搭配原始碼一起食用。
啟動一個Service
,通常在Activity
呼叫startService
來啟動。
@Override public ComponentName startService(Intent service) { return startServiceCommon(service, false, mUser); }
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; } };
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; } }
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; }
呼叫了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; }
分析一:首次啟動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; }
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
函數。
將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); }
呼叫了ActivityThread
的handleCreateService
函數。
case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break;
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
建立完畢。
public boolean bindService(Intent service, ServiceConnection conn, int flags) { //系統程序呼叫繫結服務或傳送廣播都會發出警告 warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); }
在分析一,主要判斷入參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(); } }
AMS
經過兩次過載函數bindIsolatedService
呼叫,簡單檢查相關合法性。然後呼叫ActiveService
型別的mService
的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
。
呼叫了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()); ... }
將資料封裝 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); }
case BIND_SERVICE: handleBindService((BindServiceData)msg.obj);
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(); } ... } }
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); } }
分析一:可見在第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); } }
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); } } }
這裡呼叫了 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); } }
RunConnection
是ServiceDispatcher
的內部類,這裡執行SD
的doConnected
函數。
public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } }
這裡呼叫了ServiceConnection
物件的onServiceConnected
函數,也就是我們發起繫結,呼叫context.bindService
的引數。
public void doConnected(ComponentName name, IBinder service, boolean dead) { ... mConnection.onServiceConnected(name, service); ... }
到此,Service
的繫結流程分析完畢。
在第一節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啟動繫結流程的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45