某学姐

Android Female Developer, Technology Fan, Reader.

bindService过程

2020-03-29 | Comments

基于Android 10.0的源码剖析, 站在Luoshengyang/Innost/Gityuan肩膀上.

本文分析bindService过程.

0.文件结构

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java

frameworks/base/core/java/android/app/LoadedApk.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/core/java/android/app/Service.java

1.时序图

TODO

2.ContextImpl

[ -> frameworks/base/core/java/android/app/ContextImpl.java ]

2.1 bindService

@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser());
}

2.2 bindServiceCommon

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
        String instanceName, Handler handler, Executor executor, UserHandle user) {   
    // 获取ServiceConnection对象
    IServiceConnection sd;
    if (mPackageInfo != null) {
        if (executor != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
        } else {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        }
    }
    // 获取Activity令牌
    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为不影响Service所在进程的调度和内存管理
        flags |= BIND_WAIVE_PRIORITY;
    }
    service.prepareToLeaveProcess(this);
    // 绑定isolated服务. 参考【第3节】
    int res = ActivityManager.getService().bindIsolatedService(
        mMainThread.getApplicationThread(), getActivityToken(), service,
        service.resolveTypeIfNeeded(getContentResolver()),
        sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
    return res != 0;
}

3.ActivityManagerService.bindIsolatedService

[ -> frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ]

public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, int flags, String instanceName,
        String callingPackage, int userId) throws TransactionTooLargeException {
    // isolated进程不能调用
    enforceNotIsolatedCaller("bindService");
 
    // instanceName非空的话,进行字符校验. 此处instanceName为空,走不到这里
    if (instanceName != null) {
        for (int i = 0; i < instanceName.length(); ++i) {
            char c = instanceName.charAt(i);
            if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
                        || (c >= '0' && c <= '9') || c == '_' || c == '.')) {
                throw new IllegalArgumentException("Illegal instanceName");
            }
        }
    }
 
    synchronized(this) {
        // 绑定服务. 参考【第4.1节】
        return mServices.bindServiceLocked(caller, token, service,
                resolvedType, connection, flags, instanceName, callingPackage, userId);
    }
}

4.ActiveServices

[ -> frameworks/base/services/core/java/com/android/server/am/ActiveServices.java ]

4.1 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 {
    // 从mProcessList列表中获取调用进程
    final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
 
    ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
    if (token != null) {
        // 获取指定Activity的服务连接持有者ActivityServiceConnectionHolder
        activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
        // 如果holder为空, 直接返回
        if (activity == null) {
            return 0;
        }
    }
 
    int clientLabel = 0;
    PendingIntent clientIntent = null;
    final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
 
    // 如果是系统进程调用, 则需要对intent进行标记
    if (isCallerSystem) {
        // Hacky kind of thing -- allow system stuff to tell us
        // what they are, so we can report this elsewhere for
        // others to know why certain services are running.
        service.setDefusable(true);
        clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
        if (clientIntent != null) {
            clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
            if (clientLabel != 0) {
                // There are no useful extras in the intent, trash them.
                // System code calling with this stuff just needs to know
                // this will happen.
                service = service.cloneFilter();
            }
        }
    }
 
    // flags检查
    ...
 
    final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
    final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
 
    // 各种权限检查,并从ServiceMap中根据ComponentName查找ServiceRecord,并封装成ServiceLookupResult
    // 参考【第4.2节】
    ServiceLookupResult res =
        retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
                Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
                callerFg, isBindExternal, allowInstant);
    ServiceRecord s = res.record;
 
    // If permissions need a review before any of the app components can run,
    // we schedule binding to the service but do not start its process, then
    // we launch a review activity to which is passed a callback to invoke
    // when done to start the bound service's process to completing the binding.
    // 这段代码含义:如果在绑定服务之前需要权限检查,则先调起权限检查Activity,检查结果通过RemoteCallback回调
    // 如果权限检查通过,则调用bringUpServiceLocked真正绑定服务, 否则调用unbindServiceLocked解绑服务
    // 权限检查需要在前台执行
    boolean permissionsReviewRequired = false;
    if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
            s.packageName, s.userId)) {
        permissionsReviewRequired = true;
 
        // Show a permission review UI only for binding from a foreground app
        if (!callerFg) {
            return 0;
        }
 
        final ServiceRecord serviceRecord = s;
        final Intent serviceIntent = service;
 
        RemoteCallback callback = new RemoteCallback(
                new RemoteCallback.OnResultListener() {
            @Override
            public void onResult(Bundle result) {
                synchronized(mAm) {
                    final long identity = Binder.clearCallingIdentity();
                    try {
                        if (!mPendingServices.contains(serviceRecord)) {
                            return;
                        }
                        // If there is still a pending record, then the service
                        // binding request is still valid, so hook them up. We
                        // proceed only if the caller cleared the review requirement
                        // otherwise we unbind because the user didn't approve.
                        if (!mAm.getPackageManagerInternalLocked()
                                .isPermissionsReviewRequired(
                                        serviceRecord.packageName, serviceRecord.userId)) {
                            try {
                                bringUpServiceLocked(serviceRecord,
                                        serviceIntent.getFlags(), callerFg, false, false);
                            } catch (RemoteException e) {
                                /* ignore - local call */
                            }
                        } else {
                            unbindServiceLocked(connection);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(identity);
                    }
                }
            }
        });
 
        final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
        intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
 
        mAm.mHandler.post(new Runnable() {
            @Override
            public void run() {
                mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
            }
        });
    }
 
    final long origId = Binder.clearCallingIdentity();
 
    try {
        // 如果当前正在restart过程中调用bind服务, 则从mRestartingServices列表中移除该服务及重置restart相关属性
        unscheduleServiceRestartLocked(s, callerApp.info.uid, false);
 
        // 如果flags为BIND_AUTO_CREATE
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            // 如果connections列表中没有flags为BIND_AUTO_CREATE的ConnectionRecord
            if (!s.hasAutoCreateConnections()) {
                // 设置ServiceState状态为bound
                ServiceState stracker = s.getTracker();
                if (stracker != null) {
                    stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(), s.lastActivity);
                }
            }
        }
 
        // Ensures that the given package name has an explicit set of allowed associations.
        if ((flags & Context.BIND_RESTRICT_ASSOCIATIONS) != 0) {
            mAm.requireAllowedAssociationsLocked(s.appInfo.packageName);
        }
 
        // 根据入参从映射表中查找或创建Association对象,并更新各相关属性
	    // 参考【第4.3节】
        mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
                s.instanceName, s.processName);
        // Once the apps have become associated, if one of them is caller is ephemeral
        // the target app should now be able to see the calling app
        mAm.grantEphemeralAccessLocked(callerApp.userId, service,
                UserHandle.getAppId(s.appInfo.uid), UserHandle.getAppId(callerApp.uid));
 
        // 从bindings映射表中查找或新建AppBindRecord. 参考【第4.4节】
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        // 创建ConnectionRecord
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent,
                callerApp.uid, callerApp.processName, callingPackage);
 
        // 建立binder和ConnectionRecord列表的映射关系
        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();
        if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
            b.client.hasAboveClient = true;
        }
        if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
            s.whitelistManager = true;
        }
        if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
            s.setHasBindingWhitelistingBgActivityStarts(true);
        }
        // 从当前进程的services服务列表的ConnectionRecord列表中, 查找和其建立连接的Client, 看是否Client有Activity
        // 并更新该进程状态信息和lru进程列表. 参考【第4.5节】
        if (s.app != null) {
            updateServiceClientActivitiesLocked(s.app, c, true);
        }
        ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
        if (clist == null) {
            clist = new ArrayList<>();
            mServiceConnections.put(binder, clist);
        }
        clist.add(c);
 
        // 如果flags为BIND_AUTO_CREATE, 真正执行绑定服务并返回. 参考【第4.6节】
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) {
                return 0;
            }
        }
 
        // 若为其他flags, 且Service所在的进程非空, 则更新lru进程列表和oomAdj. 这个可能会提高所在进程优先级
        if (s.app != null) {
            if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                s.app.treatLikeActivity = true;
            }
            if (s.whitelistManager) {
                s.app.whitelistManager = true;
            }
            // This could have made the service more important.
            mAm.updateLruProcessLocked(s.app,
                   (callerApp.hasActivitiesOrRecentTasks() && s.app.hasClientActivities())
                       || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
                        && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0), b.client);
            mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
        }
 
        if (s.app != null && b.intent.received) {
            // Service is already running, so we can immediately publish the connection.
            // 如果服务正在运行, 则先建立连接
            c.conn.connected(s.name, b.intent.binder, false);
 
            // If this is the first app connected back to this binding,
            // and the service had previously asked to be told when rebound, then do so.
            // rebind服务
            if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                requestServiceBindingLocked(s, b.intent, callerFg, true);
            }
        } else if (!b.intent.requested) {
            // bind服务
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }
 
        // 从mStartingBackground后台服务列表中移除当前Service, 取消后台启动
        getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
 
    return 1;
}

4.2 retrieveServiceLocked

参考文章: startService过程

4.3 AMS.startAssociationLocked

[ -> frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ]

// 映射关系Mapping is target uid -> target component -> source uid -> source process name -> association data.
Association startAssociationLocked(int sourceUid, String sourceProcess,
		int sourceState, int targetUid, long targetVersionCode,
		ComponentName targetComponent, String targetProcess) {
    if (!mTrackingAssociations) {
        return null;
    }
    ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> components
            = mAssociations.get(targetUid);
    if (components == null) {
        components = new ArrayMap<>();
        mAssociations.put(targetUid, components);
    }
    SparseArray<ArrayMap<String, Association>> sourceUids = components.get(targetComponent);
    if (sourceUids == null) {
        sourceUids = new SparseArray<>();
        components.put(targetComponent, sourceUids);
    }
    ArrayMap<String, Association> sourceProcesses = sourceUids.get(sourceUid);
    if (sourceProcesses == null) {
        sourceProcesses = new ArrayMap<>();
        sourceUids.put(sourceUid, sourceProcesses);
    }
    Association ass = sourceProcesses.get(sourceProcess);
    if (ass == null) {
        ass = new Association(sourceUid, sourceProcess, targetUid, targetComponent, targetProcess);
        sourceProcesses.put(sourceProcess, ass);
    }
    ass.mCount++;
    ass.mNesting++;
    if (ass.mNesting == 1) {
        ass.mStartTime = ass.mLastStateUptime = SystemClock.uptimeMillis();
        ass.mLastState = sourceState;
    }
    return ass;
}

4.4 ServiceRecord.retrieveAppBindingLocked

[ -> frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java ]

// 根据intent和app, 从bindings列表中匹配AppBindRecord, 没匹配到的话则新建一个
public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) {
    Intent.FilterComparison filter = new Intent.FilterComparison(intent);
    IntentBindRecord i = bindings.get(filter);
    if (i == null) {
        i = new IntentBindRecord(this, filter);
        bindings.put(filter, i);
    }
    AppBindRecord a = i.apps.get(app);
    if (a != null) {
        return a;
    }
    a = new AppBindRecord(this, i, app);
    i.apps.put(app, a);
    return a;
}

4.5 updateServiceClientActivitiesLocked

private boolean updateServiceClientActivitiesLocked(ProcessRecord proc,
        ConnectionRecord modCr, boolean updateLru) {
    if (modCr != null && modCr.binding.client != null) {
        if (!modCr.binding.client.hasActivities()) {
            // This connection is from a client without activities, so adding and removing is not interesting.
            // 如果和Service建立连接的Client进程没有Activity, 则直接返回
            return false;
        }
    }
 
    // 从当前进程的services服务列表的ConnectionRecord列表中, 查找和其建立连接的Client, 看是否Client有Activity(即anyClientActivities).
    boolean anyClientActivities = false;
    for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) {
        ServiceRecord sr = proc.services.valueAt(i);
        ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = sr.getConnections();
        for (int conni = connections.size() - 1; conni >= 0 && !anyClientActivities; conni--) {
            ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
            for (int cri=clist.size()-1; cri>=0; cri--) {
                ConnectionRecord cr = clist.get(cri);
                if (cr.binding.client == null || cr.binding.client == proc) {
                    // Binding to ourself is not interesting.
                    continue;
                }
                if (cr.binding.client.hasActivities()) {
                    anyClientActivities = true;
                    break;
                }
            }
        }
    }

    // 更新当前进程状态和lru进程列表
    if (anyClientActivities != proc.hasClientActivities()) {
        proc.setHasClientActivities(anyClientActivities);
        if (updateLru) {
            mAm.updateLruProcessLocked(proc, anyClientActivities, null);
        }
        return true;
    }
    return false;
}

updateServiceClientActivitiesLocked方法含义:
从当前进程的services服务列表的ConnectionRecord列表中, 查找和其建立连接的Client, 看是否Client有Activity, 并更新该进程状态信息和lru进程列表.

4.6 bringUpServiceLocked

参考文章: startService过程

bringUpServiceLocked方法在上一篇文章 startService过程 讲过. 会调到realStartServiceLocked方法.
(1) 对于startService调用链为: realStartServiceLocked -> ApplicationThread.scheduleCreateService -> sendServiceArgsLocked
(2) 对于bindService调用链为: realStartServiceLocked -> ApplicationThread.scheduleCreateService -> requestServiceBindingsLocked

接下来我们看一下realStartServiceLocked方法的具体代码.

4.7 realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {
    ...
    // 服务创建
    app.thread.scheduleCreateService(r, r.serviceInfo,
           mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
           app.getReportedProcState());
    r.postNotification();
    created = true;
  
    if (r.whitelistManager) {
        app.whitelistManager = true;
    }
  
    // 请求绑定服务
    requestServiceBindingsLocked(r, execInFg);
  
    // 从当前进程的services服务列表的ConnectionRecord列表中, 查找和其建立连接的Client, 看是否Client有Activity
    // 并更新该进程状态信息和lru进程列表
    updateServiceClientActivitiesLocked(app, null, true);
  
    // 将所有与Service绑定的Client端的uid添加到mBoundClientUids列表中
    // 并将该列表信息更新到WindowProcessController中
    if (newService && created) {
        app.addBoundClientUidsOfNewService(r);
    }
    ...
}

4.8 ApplicationThread.scheduleCreateService

参考文章: startService过程

4.9 requestServiceBindingsLocked

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
        throws TransactionTooLargeException {
    for (int i=r.bindings.size()-1; i>=0; i--) {
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
            break;
        }
    }
}

遍历bindings列表每一项, 执行bind操作.

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    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 {
            // 更新ServiceRecord bind阶段各属性
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // 调用ApplicationThread.scheduleBindService
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState());
            if (!rebind) {
                i.requested = true;
            }
            i.hasBound = true;
            i.doRebind = false;
        } catch (TransactionTooLargeException e) {
            // Keep the executeNesting count accurate.
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            throw e;
        } catch (RemoteException e) {
            // Keep the executeNesting count accurate.
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            return false;
        }
    }
    return true;
}

5.ActivityThread

[ -> frameworks/base/core/java/android/app/ActivityThread.java ]

5.1 ApplicationThread.scheduleBindService

private class ApplicationThread extends IApplicationThread.Stub {
    ...
    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);
    }
}

5.2 H.BIND_SERVICE

class H extends Handler {
    ...
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BIND_SERVICE:
                handleBindService((BindServiceData)msg.obj);
                break;
            ...
        }
    }
}

5.3 handleBindService

private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        data.intent.setExtrasClassLoader(s.getClassLoader());
        data.intent.prepareToEnterProcess();
 
        if (!data.rebind) {
            // 调用Service.onBind
            IBinder binder = s.onBind(data.intent);
	        // 发布服务
            ActivityManager.getService().publishService(data.token, data.intent, binder);
        } else {
            // 调用Service.onRebind
            s.onRebind(data.intent);
            // 做一些列表移除工作
            ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        }
    }
}

6.发布服务

6.1 AMS.publishService

[ -> frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ]

public void publishService(IBinder token, Intent intent, IBinder service) {
    synchronized(this) {
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}

6.2 ActiveServices.publishServiceLocked

[ -> frameworks/base/services/core/java/com/android/server/am/ActiveServices.java ]

// 这段代码的含义是: 根据intent封装filter对象并以此作为匹配条件
// 从bindings列表中的所有ConnectionRecord中查找filter匹配的ConnectionRecord, 然后建立连接
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;
                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;
                        }
						
						// 建立连接. 参考【第7.1节】
                        c.conn.connected(r.name, service, false);
                    }
                }
            }
			
			// 发布服务后的收尾工作
            serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

7.ServiceDispatcher

[ -> frameworks/base/core/java/android/app/LoadedApk.java ]

7.1 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, boolean dead)
            throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            // 建立连接. 参考【第7.2节】
            sd.connected(name, service, dead);
        }
    }
}

7.2 connected

// 如果有线程池在Runnable中执行, 否则直接在当前线程执行, 最终都调到doConnected
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);
    }
}

7.3 RunConnection

private final class RunConnection implements Runnable {
    RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
        mName = name;
        mService = service;
        mCommand = command;
        mDead = dead;
    }
 
    public void run() {
        if (mCommand == 0) {
            // 建立连接. 参考【第7.4节】
            doConnected(mName, mService, mDead);
        } else if (mCommand == 1) {
            doDeath(mName, mService);
        }
    }
 
    final ComponentName mName;
    final IBinder mService;
    final int mCommand;
    final boolean mDead;
}

7.4 doConnected

// name为要bind的服务对应的ComponentName, service为onBind返回的Binder对象, dead为false表示绑定操作
public void doConnected(ComponentName name, IBinder service, boolean dead) {
    ServiceDispatcher.ConnectionInfo old;
    ServiceDispatcher.ConnectionInfo info;
 
    synchronized (this) {
        if (mForgotten) {
            // We unbound before receiving the connection; ignore any connection received.
            return;
        }
        // 如果当前连接中已经含义目标Service的ComponentName, 且binder和onBind方法返回的binder相同
        // 则说明已经完成建立连接了, 直接返回
        old = mActiveConnections.get(name);
        if (old != null && old.binder == service) {
            // Huh, already have this one.  Oh well!
            return;
        }
 
        if (service != null) {
            // 新建ConnectionInfo对象并设置binder, 将ConnectionInfo对象添加到mActiveConnections列表
            // A new service is being connected... set it all up.
            info = new ConnectionInfo();
            info.binder = service;
            info.deathMonitor = new DeathMonitor(name, service);

            service.linkToDeath(info.deathMonitor, 0);
            mActiveConnections.put(name, info);
        } else {
            // The named service is being disconnected... clean up.
            mActiveConnections.remove(name);
        }
 
        if (old != null) {
            old.binder.unlinkToDeath(old.deathMonitor, 0);
        }
    }
 
    // If there was an old service, it is now disconnected.
    if (old != null) {
        mConnection.onServiceDisconnected(name);
    }
    if (dead) {
        mConnection.onBindingDied(name);
    }
    // If there is a new viable service, it is now connected.
    if (service != null) {
        // 回调ServiceConnection.onServiceConnected
        mConnection.onServiceConnected(name, service);
    } else {
        // The binding machinery worked, but the remote returned null from onBind().
        mConnection.onNullBinding(name);
    }
}

8.ServiceConnection.onServiceConnected

[ -> frameworks/base/core/java/android/content/ServiceConnection.java ]

一般是开发者调用bindService时, 手动传入ServiceConnection的实现类.

9.总结

bindService和startService过程差不多, 差别主要是在创建Service实例后一个是执行bind操作, 一个是执行start操作.

本文原文发自 某学姐, 转载请保留出处, 谢谢.

Comments