天天看點

bindService 分析---之二

1.2 requestServiceBindingLocked

直接看ActiveServices的requestServiceBindingLocked方法,

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        •••
        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);
               •••
            } catch (TransactionTooLargeException e) { 
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                throw e;
            } catch (RemoteException e) {
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                return false;
            }
        }
        return true;
    }
           

和上面啟動服務時調用流程一樣,首先從AMS程序跨程序到要綁定的服務所在程序,然後發送消息到主線程,調用對應的函數,

在這裡調用handleBindService方法

private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token); 
        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, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                }
            } catch (Exception e) {
               •••
            }
        }
    }
           

該函數首先調用服務的onBind方法得到Binder,下一步自然是通過AMS将該對象傳回給發起綁定的程序。直接看AMS的publishService方法,

public void publishService(IBinder token, Intent intent, IBinder service) {
       •••
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
           

publishServiceLocked方法如下,

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) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                           •••
                            try {
                                c.conn.connected(r.name, service);
                            } catch (Exception e) { 
                            }
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
           

直接調用c.conn.connected 方法,就像上一小節所論述的那樣,又一次跨程序調用到發起綁定的程序中。

1.3 bringUpServiceLocked

bringUpServiceLocked方法啟動服務的過程已經分析過了,這裡需要說明的是在realStartServiceLocked方法啟動線程過後,

會調用requestServiceBindingsLocked,最後仍然會調用requestServiceBindingLocked方法來綁定服務。

1.4小結

在onServiceConnected方法中, service參數,就是綁定的那個service的binder代理。現在已經打通了bindService()動作涉及

的三方關系:發起方、AMS、目标Service。具體的示意圖如下:

bindService 分析---之二

其實, bindService總體流程和startService類似,隻是多了一個綁定過程。也就是多了一個被綁定服務到AMS,然後到用戶端的回調過程。

并且,跨程序的互動過程和startService過程完全相同。