bindService源碼分析

image.png

聲明:圖是借來的。
按時(shí)序圖的順序分析:

Activity

Activity是ContextWrapper的間接子類,在Activity中調(diào)用bindService其實(shí)是調(diào)用的ContextWrapper類中的bindService方法:

ContextWrapper:
Context mBase;
...
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

mBase是Context對(duì)象,在Context類中bindService是一個(gè)抽象方法,所以這里調(diào)用的是Context實(shí)現(xiàn)類即ContextImpl類的bindService方法:

ContextImpl.java:
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
        handler, UserHandle user) {
    // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (mPackageInfo != null) {
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, 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(this);
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, 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();
    }
}

在bindServiceCommon中,mPackageInfo為L(zhǎng)oadedApk的實(shí)例,在ContextImpl實(shí)例化的時(shí)候初始化,一般不為null,所以會(huì)執(zhí)行sd = mPackageInfo.getServiceDispatcher:

LoadedApk.java
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) {
            if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
            sd = map.get(c);
        }
        if (sd == null) {
            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);
        }
        return sd.getIServiceConnection();
    }
}

sd.getIServiceConnection返回的真實(shí)類型是ServiceDispatcher.InnerConnection。

LoadedApk.java:
ServiceDispatcher:
static final class ServiceDispatcher {
    private final ServiceDispatcher.InnerConnection mIServiceConnection;
...
    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, boolean dead)
                throws RemoteException {
            LoadedApk.ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) {
                sd.connected(name, service, dead);
            }
        }
    }

    IServiceConnection getIServiceConnection() {
        return mIServiceConnection;
    }
...
}

這里先記住,在ContextImpl中的bindServiceCommon方法中,sd得到的是ServiceDispatcher.InnerConnection類型的實(shí)例,這個(gè)實(shí)例中包含了傳來的ServiceConnection。接下來回到ContextImpl中的bindServiceCommon中,看看接下來做了些什么:

int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

ActivityManager.getService返回的就是AMS,所以這里調(diào)用的是AMS中的bindService,繼續(xù)跟代碼,發(fā)現(xiàn)調(diào)用的是ActiveServices中的requestServiceBIndingLocked方法:

ActivityManagerService.java:
public int bindService(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, int flags, String callingPackage,
        int userId) throws TransactionTooLargeException {
    ...

    synchronized(this) {
        return mServices.bindServiceLocked(caller, token, service,
                resolvedType, connection, flags, callingPackage, userId);
    }
}

ActiveServices.java:
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.repProcState);
           ...
    return true;
}

到這里看到了比較眼熟的東西:r.app.thread.scheduleBindService,其實(shí)就是ActivityThread的scheduleBindService:

ActivityThread.java:
public final void scheduleBindService(IBinder token, Intent intent,
            boolean rebind, int processState) {
        ...
        sendMessage(H.BIND_SERVICE, s);
    }

通過handler,然后調(diào)用:

private void handleBindService(BindServiceData data) {
     ...
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
    ...
}

經(jīng)過上面的分析,我們已經(jīng)知道,這里其實(shí)就是調(diào)用的AMS中的publishService方法:

ActivityManagerService.java:
public void publishService(IBinder token, Intent intent, IBinder service) {
    ...
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}

ActiveServices.java:
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
    ...
                            c.conn.connected(r.name, service, false);
    ...
}

到最后,會(huì)從傳來的參數(shù)中獲取到conn對(duì)象,然后調(diào)用connected方法,這里就是回調(diào)的ServiceDispatcher.InnerConnection類的connected方法,然后調(diào)用ServiceDispatcher中的connected方法,進(jìn)而回調(diào)從Activity中傳入的ServiceConnection的回調(diào)方法如onServiceConnected等。
至此,bindservice流程分析完畢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容