<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                #### 9.3.2 Service的綁定過程 和Service的啟動過程一樣,Service的綁定過程也是從ContextWrapper開始的,如下所示。 public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); } 這個過程和Service的啟動過程是類似的,mBase同樣是ContextImpl類型的對象。ContextImpl的bindService方法最終會調用自己的bindServiceCommon方法,如下所示。 private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) { IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo ! = null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags); } else { throw new RuntimeException("Not supported in system context"); } 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(); int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res ! = 0; } catch (RemoteException e) { return false; } } bindServiceCommon方法主要完成如下兩件事情。 首先將客戶端的ServiceConnection對象轉化為ServiceDispatcher.InnerConnection對象。之所以不能直接使用ServiceConnection對象,這是因為服務的綁定有可能是跨進程的,因此ServiceConnection對象必須借助于Binder才能讓遠程服務端回調自己的方法,而ServiceDispatcher的內部類InnerConnection剛好充當了Binder這個角色。那么ServiceDispatcher的作用是什么呢?其實ServiceDispatcher起著連接ServiceConnection和InnerConnection的作用。這個過程由LoadedApk的getServiceDispatcher方法來完成,它的實現如下: public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, 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) { sd = new ServiceDispatcher(c, context, handler, flags); if (map == null) { map = new ArrayMap<ServiceConnection, LoadedApk.Service- Dispatcher>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } } 在上面的代碼中,mServices是一個ArrayMap,它存儲了一個應用當前活動的ServiceConnection和ServiceDispatcher的映射關系,它的定義如下所示。 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk. ServiceDispatcher>> mServices = new ArrayMap<Context, ArrayMap <ServiceConnection, LoadedApk.ServiceDispatcher>>(); 系統首先會查找是否存在相同的ServiceConnection,如果不存在就重新創建一個ServiceDispatcher對象并將其存儲在mServices中,其中映射關系的key是ServiceConnection, value是ServiceDispatcher,在ServiceDispatcher的內部又保存了ServiceConnection和InnerConnection對象。當Service和客戶端建立連接后,系統會通過InnerConnection來調用ServiceConnection中的onServiceConnected方法,這個過程 有可能是跨進程的。當ServiceDispatcher創建好了以后,getServiceDispatcher會返回其保存的InnerConnection對象。 接著bindServiceCommon方法會通過AMS來完成Service的具體的綁定過程,這對應于AMS的bindService方法,如下所示。 public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service ! = null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, userId); } } 接下來,AMS會調用ActiveServices的bindServiceLocked方法,bindServiceLocked再調用bringUpServiceLocked, bringUpServiceLocked又會調用realStartServiceLocked方法,realStartServiceLocked方法的執行邏輯和9.3.1節中的邏輯類似,最終都是通過ApplicationThread來完成Service實例的創建并執行其onCreate方法,這里不再重復講解了。和啟動Service不同的是,Service的綁定過程會調用app.thread的scheduleBindService方法,這個過程的實現在ActiveServices的requestServiceBindingLocked方法中,如下所示。 private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) { if (r.app == null || r.app.thread == null) { // If service is not currently running, can't yet bind. return false; } if ((! i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_ SERVICE); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); if (! rebind) { i.requested = true; } i.hasBound = true; i.doRebind = false; } catch (RemoteException e) { if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r); return false; } } return true; } 在上述代碼中,app.thread這個對象多次出現過,對于它我們應該再熟悉不過了,它實際上就是ApplicationThread。ApplicationThread的一系列以schedule開頭的方法,其內部都是通過Handler H來中轉的,對于scheduleBindService方法來說也是如此,它的實現如下所示。 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; if (DEBUG_SERVICE) Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); sendMessage(H.BIND_SERVICE, s); } 在H內部,接收到BIND_SERVICE這類消息時,會交給ActivityThread的handleBind-Service方法來處理。在handleBindService中,首先根據Service的token取出Service對象,然后調用Service的onBind方法,Service的onBind方法會返回一個Binder對象給客戶端使用,這個過程我們在Service的開發過程中應該都比較熟悉了。原則上來說,Service的onBind方法被調用以后,Service就處于綁定狀態了,但是onBind方法是Service的方法,這個時候客戶端并不知道已經成功連接Service了,所以還必須調用客戶端的ServiceConnection中的onServiceConnected,這個過程是由ActivityManagerNative.getDefault()的publishService方法來完成的,而前面多次提到,ActivityManagerNative.getDefault()就是AMS。handleBindService的實現過程如下所示。 ``` private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (DEBUG_SERVICE) Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); if (s ! = null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (! data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, 0, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { } } catch (Exception e) { if (! mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } } ``` Service有一個特性,當多次綁定同一個Service時,Service的onBind方法只會執行一次,除非Service被終止了。當Service的onBind執行以后,系統還需要告知客戶端已經成功連接Service了。根據上面的分析,這個過程由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); } } 從上面代碼可以看出,AMS的publishService方法將具體的工作交給了ActiveServices類型的mServices對象來處理。ActiveServices的publishServiceLocked方法看起來很復雜,但其實核心代碼就只有一句話:c.conn.connected(r.name, service),其中c的類型是ConnectionRecord, c.conn的類型是ServiceDispatcher.InnerConnection, service就是Service的onBind方法返回的Binder對象。為了分析具體的邏輯,下面看一下ServiceDispatcher. InnerConnection的定義,如下所示。 private static class InnerConnection extends IServiceConnection.Stub { final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected(ComponentName name, IBinder service) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd ! = null) { sd.connected(name, service); } } } 從InnerConnection的定義可以看出,它的connected方法又調用了ServiceDispatcher的connected方法,ServiceDispatcher的connected方法的實現如下所示。 public void connected(ComponentName name, IBinder service) { if (mActivityThread ! = null) { mActivityThread.post(new RunConnection(name, service, 0)); } else { doConnected(name, service); } } 對于Service的綁定過程來說,ServiceDispatcher的mActivityThread是一個Handler,其實它就是ActivityThread中的H,從前面ServiceDispatcher的創建過程來說,mActivityThread不會為null,這樣一來,RunConnection就可以經由H的post方法從而運行在主線程中,因此,客戶端ServiceConnection中的方法是在主線程被回調的。RunConnection的定義如下所示。 private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command) { mName = name; mService = service; mCommand = command; } public void run() { if (mCommand == 0) { doConnected(mName, mService); } else if (mCommand == 1) { doDeath(mName, mService); } } final ComponentName mName; final IBinder mService; final int mCommand; } 很顯然,RunConnection的run方法也是簡單調用了ServiceDispatcher的doConnected方法,由于ServiceDispatcher內部保存了客戶端的ServiceConnection對象,因此它可以很方便地調用ServiceConnection對象的onServiceConnected方法,如下所示。 // If there is a new service, it is now connected. if (service ! = null) { mConnection.onServiceConnected(name, service); } 客戶端的onServiceConnected方法執行后,Service的綁定過程也就分析完成了,至于Service的停止過程和解除綁定的過程,系統的執行過程是類似的,讀者可以自行分析源碼,這里就不再分析了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看