Service启动流程

### Service启动流程

> Service作为四大组件之一,与Activity类似,只不过作为后台服务,不提供用户界面,可以在后台长时间运行。服务启动方式有两种,分别是startService和bindService。(源码基于android13)

#### startService

Activity继承ContextWrapper,这里调用的是父类ContextWrapper的startService方法

>frameworks/base/core/java/android/content/ContextWrapper.java

```java
Context mBase;
protected void attachBaseContext(Context base) {
    if (mBase != null) {
        throw new IllegalStateException("Base context already set");
    }
    mBase = base;
}

@Override
public ComponentName startService(Intent service) {
    return mBase.startService(service);
}
```

mBase即ContexImpl

> frameworks/base/core/java/android/app/ContextImpl.java

```java
@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
                                         UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        // 1 调用到ams的startService
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                getContentResolver()), requireForeground,
            getOpPackageName(), user.getIdentifier());
        .......
            return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
```

1处直接通过binder调用到ams的startService,把intent和applicationThread传过去

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

```java
final ActiveServices mServices;
public ComponentName startService(IApplicationThread caller, Intent service...)
    throws TransactionTooLargeException {
    //...
    try {
        res = mServices.startServiceLocked(caller, service...);//1
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
    return res;
}
```

AMS是通过ActiveServices来管理Service的

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

```java
ComponentName startServiceLocked(IApplicationThread caller, Intent service...){
    //...
    //1 检索是否存在要启动的服务,如果存在,就把ServiceRecord封装到ServiceLookupResult
    ServiceLookupResult res =
        retrieveServiceLocked(service, null, resolvedType, callingPackage,
                              callingPid, callingUid, userId, true, callerFg, false, false);
    //...
    ServiceRecord r = res.record;
    //...
    //2 调用startServiceInnerLocked把查找到的ServiceRecord传过去
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}
private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,...) {
     //...
    //3 这里比较关键,给service标记是通过start请求启动的,并添加到pendingStarts缓存中
    r.startRequested = true;
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                                                    service, neededGrants, callingUid));
    //...
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
                                                callingUid, wasStartRequested);
    return cmp;
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r...){
    //...
    String error = bringUpServiceLocked(r, service.getFlags(),callerFg,false,false ,false ,true);
    //...
}
```

注释1处会先检查是否存在要启动的服务,即ServiceRecord(AMS用ActivityRecord描述Activity,同样,用ServiceRecord描述Service),如果存在就把ServiceRecord封装到ServiceLookupResult返回。后面一直调用到bringUpServiceLocked方法(注释2)。注释3处比较关键,容易忽略,这里对serviceRecord标记了是通过start启动的,并且缓存了此请求。(因为startService和bindservice都会调用到realStartServiceLocked这个方法,通过startRequested就可以区分,区分后startservice的就会走service的onStartCommand的流程,bindservice的不走)。先看retrieveServiceLocked

```java
private ServiceLookupResult retrieveServiceLocked(Intent service...){
    ServiceRecord r = null;
    //...
    if (r == null) {
        //1 通过PMS去拿应用信息
        ResolveInfo rInfo = mAm.getPackageManagerInternal().resolveService(service, resolvedType, flags, userId, callingUid);
        
        //2从缓存拿ServiceRecord,如果没有就new出来并放进缓存
        r = smap.mServicesByInstanceName.get(name);
        if (r == null && createIfNeeded) {
            r = new ServiceRecord(mAm, className, name, definingPackageName,
                                  definingUid, filter, sInfo, callingFromFg, res,
                                  sdkSandboxProcessName, sdkSandboxClientAppUid,
                                  sdkSandboxClientAppPackage);
            res.setService(r);
            smap.mServicesByInstanceName.put(name, r);
        }
    }
}                                             
```

再看bringUpServiceLocked是怎么启动服务的

```java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags...) {
    //1 这里的r.app是等service创建完才不为空,如果这里不为空,说明service已经创建好了此时service.onCreate已经执行
    // 直接走sendServiceArgsLocked去执行service.onStartCommand,如果为空,说明服务还没创建,走注释2去拿服务端进程
    if (r.app != null && r.app.getThread() != null) {
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }
    //...
    ProcessRecord app;
    //2 service对应的进程是否存在
    app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);    
    if (app != null ) {
        final IApplicationThread thread = app.getThread();
        if (thread != null) {
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                //3 真正启动服务
                realStartServiceLocked(r, app, thread, pid, uidRecord,execInFg, enqueueOomAdj);
                return null;
            } catch (TransactionTooLargeException e) {
                throw e;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
            }
        }
    }
    //4 要启动的服务进程不存在,通过AMS.startProcessLocked先启动进程
    if (app == null && !permissionsReviewRequired && !packageFrozen) {
          app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated);
    }
    //5 把要启动的service存起来,待要启动的进程启动好后再起服务,startService和bindService都会存进mPendingServices
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    }
    //...
    return null;
}
```

注释写的很清楚,注释1先去判断对应的service是否已经创建,如果创建了,直接走sendServiceArgsLocked流程。否则走注释2,先看对应服务的进程是否启动,即ProcessRecord,如果进程启动了就直接通过realStartServiceLocked去启动服务,如果进程没启动,就通过注释4调用AMS.startProcessLocked来启动对应进程,然后把要启动的服务先缓存到mPendingServices中,待要启动进程启动好后再拉起服务。先看进程已经启动的情况,即调到realStartServiceLocked

```java
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
                                    IApplicationThread thread...) {
    //...
    //1 调用到要启动服务的进程的scheduleCreateService去创建服务
    thread.scheduleCreateService(r, r.serviceInfo,
                                 mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                                 app.mState.getReportedProcState());
    //...
    //2 等service创建完成后,再通过binder把参数传过去执行服务的onStartCommand
    sendServiceArgsLocked(r, execInFg, true);
    //...
}
```

thread即ApplicationThread,这里注释1通过binder通信调用到要启动服务的进程的ApplicationThread.scheduleCreateService,待进程的service创建完成后,再通过2处启动服务。先看scheduleCreateService创建服务

> frameworks/base/core/java/android/app/ActivityThread.java

```java
private class ApplicationThread extends IApplicationThread.Stub {
    public final void scheduleCreateService(IBinder token,
    ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
        sendMessage(H.CREATE_SERVICE, s);
    }
}
class H extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case CREATE_SERVICE:
                handleCreateService((CreateServiceData)msg.obj);
                break;
        }
    }
}
private void handleCreateService(CreateServiceData data) {
    //1 获取应用的描述对象LoadedApk
    LoadedApk packageInfo = getPackageInfoNoCheck(
        data.info.applicationInfo, data.compatInfo);
    Service service = null;
    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    //2 通过1拿到到描述对象,通过类加载器加装处真正的Service对象
    service = packageInfo.getAppFactory()
        .instantiateService(cl, data.info.name, data.intent);
    //3 根据1处拿到的描述对象,创建ContextImpl,即Service的上下文
     ContextImpl context = ContextImpl.getImpl(service.createServiceBaseContext(this, packageInfo));
    //4 通过attach把ContextImpl和service关联起来
    service.attach(context, this, data.info.name, data.token, app,
                   ActivityManager.getService());
    //5 调用service的onCreate
    service.onCreate();
    //6 本地用ArrayMap存放已经启动好的service
    mServices.put(data.token, service);
    //...
}
```

先拿到应用的描述对象,再创建service和创建ContextImpl,通过attach把service和ContextImpl关联起来,再执行Service的onCreate方法,终于到应用的onCreate回调了。注释6会把创建好的service缓存到mServices,方便ams下次调用。此时service已经创建好了,继续看ActiveServices.sendServiceArgsLocked启动服务。

```java
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) {
    //1 startService的方式启动的,pendingStarts不为空。bindservice的pendingStarts为空
    final int N = r.pendingStarts.size();
    if (N == 0) {
        return;
    }

    //...
    //2 只有startservice的才会走这里
    r.app.getThread().scheduleServiceArgs(r, slice);
    //...
}
```

注释1会根据根据前面存进去的pendingStarts缓存来区分是否走注释2的流程,startservice启动的pendingStarts不为空,bindservice的pendingStarts为空。注释2处scheduleServiceArgs又是熟悉的套路,binder通信调用到ApplicatinThread的scheduleServiceArgs,再通过hander调用到ActivityThread的handleServiceArgs方法

```java
private void handleServiceArgs(ServiceArgsData data) {
    //...
    Service s = mServices.get(data.token);
    res = s.onStartCommand(data.args, data.flags, data.startId);
    //...
}
```

从创建service时缓存的mServices中拿到具体的service,并回调onStartCommand,到此,startService的流程就结束了。

上面还有个进程不存在的场景,即在bringUpServiceLocked方法里拿到的ProcessRecord为空,就会通过AMS.startProcessLocked来启动进程,并回调到ActivityThread的main方法。这个过程在Activity启动流程中已经详细介绍了,这里只关注跟服务相关的。

> frameworks/base/core/java/android/app/ActivityThread.java 

```java
public static void main(String[] args) {
     //...
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
     //...
}
private void attach(boolean system, long startSeq) {
    //...
    final IActivityManager mgr = ActivityManager.getService();
    mgr.attachApplication(mAppThread, startSeq);
    //...
}
```

进程创建完后调用AMS.attachApplication

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

```java
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
    }
}
final ActiveServices mServices;
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
                                        int pid, int callingUid, long startSeq) {
    //...
    didSomething |= mServices.attachApplicationLocked(app, processName);
    //...
}
```

这里只关注跟服务相关的流程,调用到ActiveServices.attachApplicationLocked

```java
boolean attachApplicationLocked(ProcessRecord proc, String processName)
    throws RemoteException {
    //...
    //1 有要启动的服务
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;

        for (int i=0; i<mPendingServices.size(); i++) {
            sr = mPendingServices.get(i);
            mPendingServices.remove(i);
            i--;
            //2 真正去启动服务
            realStartServiceLocked(sr, proc, thread, pid, uidRecord, sr.createdFromFg,
                                   true);
        }
    }
    //...
}
```

mPendingServices里存着要启动的服务,注释2调用realStartServiceLocked去真正启动服务,后面流程跟进程已存在的完全一样。

#### bindService

绑定流程和启动流程有细微差别,表现在bindservice时需要传个ServiceConnection接口,绑定成功后会回调该接口。另外,bindservice>service.onCreate>service.onBind,多次调用bindservice只会调用一次onBind,而startService>>service.onCreate>service.onStartCommand,多次调用startService会执行多次onStartCommand。

> frameworks/base/core/java/android/content/ContextWrapper.java

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

一样的套路,除了传ServiceConnection接口,一般flags会传Context.BIND_AUTO_CREATE

> frameworks/base/core/java/android/app/ContextImpl.java

```java
final @NonNull LoadedApk mPackageInfo;
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                                  String instanceName, Handler handler, Executor executor, UserHandle user) {
    IServiceConnection sd;
    if (executor != null) {
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
    } else {
        //1 传过来的executor为空,走这里传的是hander
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
    }
    //...
    //2 AMS.bindServiceInstance
    int res = ActivityManager.getService().bindServiceInstance(
        mMainThread.getApplicationThread(), getActivityToken(), service,
        service.resolveTypeIfNeeded(getContentResolver()),
        sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
    return res != 0;
}
```

注意,注释1处通过LoadedApk.getServiceDispatcher来获取IServiceConnection,可以把IServiceConnection理解成对client端定义的ServiceConnection做了封装,IServiceConnection本质是个binder对象,里面包括了ServiceConnection接口,把这binder传给ams后,等绑定成功后ams会回调此binder对象,binder对象再通过内部封装的ServiceConnection回调其onServiceConnected接口。注释2处把构造好的sd通过AMS.bindServiceInstance传给ams绑定。先往注释1里看下怎么构造IServiceConnection

> frameworks/base/core/java/android/app/LoadedApk.java

```java
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices= new ArrayMap<>();
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) {
    return getServiceDispatcherCommon(c, context, handler, null, flags);
}
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,Context context, Handler handler, Executor executor, int flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        //1 先从mServices缓存里找
        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
        if (map != null) {
            sd = map.get(c);
        }
        if (sd == null) {
            //2 没找到的话new出来
            if (executor != null) {
                sd = new ServiceDispatcher(c, context, executor, flags);
            } else {
                sd = new ServiceDispatcher(c, context, handler, flags);
            }
            if (map == null) {
                map = new ArrayMap<>();
                mServices.put(context, map);
            }
            //3 把new出来的sd缓存起来
            map.put(c, sd);
        } else {
            sd.validate(context, handler, executor);
        }
        return sd.getIServiceConnection();
    }
}
```

注释1 先从mServices缓存里找,能找到就直接返回,不能找到就new出来再存缓存。ServiceDispatcher是LoadedApk的内部类

```java
public final class LoadedApk {
    static final class ServiceDispatcher {
        //1 ServiceDispatcher的构造函数中new了静态内部类InnerConnection
        ServiceDispatcher(ServiceConnection conn,Context context, Handler activityThread, int flags) {
            mIServiceConnection = new InnerConnection(this);
            mConnection = conn;
            mContext = context;
            mActivityThread = activityThread;
            mActivityExecutor = null;
            mLocation = new ServiceConnectionLeaked(null);
            mLocation.fillInStackTrace();
            mFlags = flags;
        }
        private final ServiceDispatcher.InnerConnection mIServiceConnection;
        IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }
        
        //2 InnerConnection是ServiceDispatcher的静态内部类,本质是个binder
        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) {
                    //3 binder回调connected后,内部类调用外部sd的connected方法
                    sd.connected(name, service, dead);
                }
            }
        }
    }
}
```

结构稍微有点复杂,ServiceDispatcher为LoadedApk内部类,InnerConnection又是ServiceDispatcher的静态内部类,持有外部类ServiceDispatcher的弱引用,InnerConnection又是个binder。可以联想到这么设计的目的就是把这个binder传给ams,绑定成功后ams回调binder这里定义的connected方法(注释3)。sd.connected方法我们后面再分析。继续AMS.bindServiceInstance看AMS是怎么绑定服务的。

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

```java
public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
                               String resolvedType, IServiceConnection connection, int flags, String instanceName,
                               String callingPackage, int userId) throws TransactionTooLargeException {
    return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
                               instanceName, false, 0, null, callingPackage, userId);
}
private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
                                String resolvedType, IServiceConnection connection, int flags, String instanceName,
                                boolean isSdkSandboxService, int sdkSandboxClientAppUid,
                                String sdkSandboxClientAppPackage, String callingPackage, int userId)
    throws TransactionTooLargeException {
    return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
                                       flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
                                       sdkSandboxClientAppPackage, callingPackage, userId);
}
```

到ActiveService服务管理类的bindServiceLocked方法

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

```java
final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>();
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                      String resolvedType, final IServiceConnection connection...){
    //...
    //1 校验调用的进程是否存在
    final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);
    if (callerApp == null) {
        throw new SecurityException(
            "Unable to find app for caller " + caller
            + " (pid=" + callingPid
            + ") when binding service " + service);
    }
    //2 校验调用的进程的activity是否存在
    activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
    if (activity == null) {
        Slog.w(TAG, "Binding with unknown activity: " + token);
        return 0;
    }

    //3 检索是否存在要启动的服务,如果存在,就把ServiceRecord封装到ServiceLookupResult
    ServiceLookupResult res = retrieveServiceLocked(service, instanceName,isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,resolvedType, callingPackage, callingPid, callingUid, userId, true,callerFg,isBindExternal, allowInstant);
    ServiceRecord s = res.record;

    //4 检索app的绑定信息
    AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
    ConnectionRecord c = new ConnectionRecord(b, activity,
                                              connection, flags, clientLabel, clientIntent,
                                              callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);
    IBinder binder = connection.asBinder();
    s.addConnection(binder, c);
    b.connections.add(c);
    activity.addConnection(c);

    //5 缓存绑定信息到mServiceConnections,解绑的时候会从这里拿
    ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
    if (clist == null) {
        clist = new ArrayList<>();
        mServiceConnections.put(binder, clist);
    }
    clist.add(c);

    if ((flags&Context.BIND_AUTO_CREATE) != 0) {
        //6 由于bindservice时传的flag是BIND_AUTO_CREATE,执行里面的bringUpServiceLocked
        if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                                 permissionsReviewRequired, packageFrozen, true) != null) {
            return 0;
        }
    }

    //7如果要绑定的服务已经绑定过,会回调connected接口。如果服务没绑定过,会请求绑定服务流程
    //也就是说多次调用bindService,并不会多次执行onBind方法,但是ServiceConnection的onServiceConnected方法会多次回调
    if (s.app != null && b.intent.received) {
        c.conn.connected(clientSideComponentName, b.intent.binder, false);
    }else if (!b.intent.requested) {
        requestServiceBindingLocked(s, b.intent, callerFg, false);
    }
}
```

这个方法是绑定服务的核心方法。

注释1和注释2先分别校验客户端进程和activity是否存在,不存在直接退出此流程。

注释3处retrieveServiceLocked这个方法前面已经介绍了,这里会拿到service的描述对象ServiceRecord

注释4先构建了AppBindRecord,然后new ConnectionRecord创建了连接记录,并通过ServiceRecord.addConnection把客户端的IServiceConnection和ConnectionRecord关联起来。先看retrieveAppBindingLocked

```java
final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings= new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
final ArrayMap<ProcessRecord, AppBindRecord> apps = new ArrayMap<ProcessRecord, AppBindRecord>();
public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app){
    Intent.FilterComparison filter = new Intent.FilterComparison(intent);
    //1 一对多
    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;
}
```

注意到绑定的服务是一对多的关系,多个应用可以同时绑定同一个服务。所以注释1处先把service的参数封装成过滤条件,然后从bindings缓存中查找IntentBindRecord,这个对象里包含了此服务的所有绑定进程。再从IntentBindRecord里根据进程去查找AppBindRecord,找不到就new一个存进去。

继续上面注释5处会缓存绑定信息到mServiceConnections,解绑的时候会从这里拿

注释6处由于bindservice时传的flag是BIND_AUTO_CREATE,执行里面的bringUpServiceLocked,这方法上面详细介绍了,会先去获取服务端的进程,如果存在,就走sendServiceArgsLocked,startService启动的话会回调onStartCommand,bindService的不会走这个流程。如果进程不存在,就通过AMS去拉相应的服务进程,待进程启动后通过attachApplication再走服务的启动或者绑定流程。

注释7处如果服务没有绑定过,b.intent.requested为false,会调requestServiceBindingLocked走绑定流程,如果服务绑定过,只会回调connected接口。

```java
private final boolean requestServiceBindingLocked(ServiceRecord r,IntentBindRecord i,boolean execInFg, boolean rebind) {
    //1 服务端还没启动,直接返回
    if (r.app == null || r.app.getThread() == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
    //...
    r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
                                          r.app.mState.getReportedProcState());
    if (!rebind) {
        i.requested = true;
    }
    i.hasBound = true;
    i.doRebind = false;
    return true;
}
```

注释1处判断服务端是否已经启动,未启动的话直接返回,如果已经启动,就会执行onBind流程。

对于注释6,疑惑的是,startService和bindService都会执行bringUpServiceLocked,服务端未启动时,都会拉起服务进程,问题是AMS是怎么判断是走的startService还是bindService,因为服务进程启动后,还要分别执行onStartComman或者onBind

服务进程不存在时这段流程调用关系:ActiveServices.bringUpServiceLocked >AMS.startProcessLocked > ActivityThread.main>ActivityThread.attach>AMS.attachApplication>AMS.attachApplicationLocked>ActiveServices.attachApplicationLocked>ActiveServices.realStartServiceLocked,

```java
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
                                    IApplicationThread thread...) {
    //...
    //1 调用到要启动服务的进程的scheduleCreateService去创建服务
    thread.scheduleCreateService(r, r.serviceInfo,
                                 mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                                 app.mState.getReportedProcState());
    //...
    //2 执行binding流程
    requestServiceBindingsLocked(r, execInFg);
    //...
    //3 执行onStartCommand流程
    sendServiceArgsLocked(r, execInFg, true);
    //...
}
//4 遍历了所有的bindings缓存,分别执行requestServiceBindingLocked来回调起onBind
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;
        }
    }
}
```

注释1,start和bind都会先执行service.onCreate

注释2和4,会去遍历之前缓存的bindings,分别执行requestServiceBindingLocked去执行scheduleBindService绑定流程,startService的bindings为空

注释3上面详细讲过了,根据pendingStarts去区分,startService的里面有值并走startCommand流程,bindService的不走。

继续看下scheduleBindService

```java
public final void scheduleBindService(IBinder token, Intent intent,
                                      boolean rebind, int processState) {
    sendMessage(H.BIND_SERVICE, s);
}
//handler:
//  case BIND_SERVICE:
//     handleBindService((BindServiceData)msg.obj);
private void handleBindService(BindServiceData data) {
    //...
    ActivityManager.getService().publishService( data.token, data.intent, binder);
    //...
}

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

ActiveServices.publishServiceLocked

```java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
       //1 根据intent构建过滤条件,查找之前存的IntentBindRecord
    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);
                final ComponentName clientSideComponentName = c.aliasComponent != null ? c.aliasComponent : r.name;
                //遍历所有的clist,回调IServiceConnection的connected
                c.conn.connected(clientSideComponentName, service, false);
            }
        }
    }
}
```

publishServiceLocked发布服务时会先根据intent构建过滤条件,查找到所有的ConnectionRecord列表,并分别回调IServiceConnection的connected接口。

```java
private static class InnerConnection extends IServiceConnection.Stub {
    public void connected(ComponentName name, IBinder service, boolean dead)throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service, dead);
        }
    }
}
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);
    }
}
private final class RunConnection implements Runnable {
    public void run() {
        if (mCommand == 0) {
            doConnected(mName, mService, mDead);
        } else if (mCommand == 1) {
            doDeath(mName, mService);
        }
    }
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
    //...
    if (service != null) {
        //1 回调onServiceConnected
        mConnection.onServiceConnected(name, service);
    } else {
        mConnection.onNullBinding(name);
    }
}
```

AMS回调客户端的IServiceConnection.connected接口,此接口调用外部类ServiceDispatcher.connected,这里直接往主线程post个任务,此run方法相当于在客户端的主线程运行,执行doConnected,此方法里会回调客户端定义的ServiceConnection.onServiceConnected。至此,bindService也介绍完了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值