Service的startService和bindService源码流程

学习完Activity的启动流程后,接着学习Service的启动流程和绑定流程。

1.Service的启动流程

和Activity一样,Service的启动过程我们可以看成两个部分:

  1. ContextImplAMS的调用过程(从应用程序进程到SystemServer进程)
  2. ActivityThread启动Service (从SystemServer进程回到应用程序进程)

1.1 ContextImpl到AMS的调用过程

先看下从 ContextImpl到AMS调用的时序图:
在这里插入图片描述
要启动Service,我们会调用 startService(),它在ContextWrapper中实现:

//ContextWrapper.java
    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

其中 mBase是 Context类型,因为Context是抽象类,所以我们必须要搞清其实现类,所以我们先要了解这个mBase的由来。
Android应用程序启动(根Activity)过程 Activity的实例创建之前,有这么一段代码:

// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
   ...
   ContextImpl appContext = createBaseContextForActivity(r);
   ...
   activity.attach(appContext....);
   ...
}

可以appContext 是一个 ContextImpl 类,然后在activity调用attach()后传入这个对象。在 attach()中,会把 ContextImpl 赋值给 ContextWrapper的 成员变量mBase。
也就是说,调用了 mBase.startService() 就是调用 ContextImpl.startService:

// ContextImpl.java
   @Override
   public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
   }

    @Override
    public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
        return startServiceCommon(service, true, user);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            //1
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            ...
            return cn;
        } 
        ...
     }

startService调用了 startServiceCommon()
它做的事情就是获取一个 ComponentName然后返回他。
在学习Activity启动的时候我们知道 ComponentName这个类用存储一个类的包名信息。如果一个Service启动成功了,就会返回其创建路径名。
而它是通过ActivityManager.getService().startService,这个我熟,就是通过AIDL,调用了 AMS.startService(),进程从应用程序进程切换到了 SystemServer层。

1.2 ActivityThread启动Service

接下来就是走AMS是如何启动Service的。我们先看看时序图:
在这里插入图片描述
从最开始看:

// ActivityManagerService.java
    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                //1
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

在 synchronized里面,通过Binder拿到调用者的 Pid、Uid、Id的信息
在注释1中,把这些参数传入到 ActivesServices.startServiceLocked()函数里面。看这个方法:

// ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ...
        //1
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }
        // 2
        ServiceRecord r = res.record;
        ...
        //3
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

注释1:通过 retrieveServiceLocked()查找是否有与service对应的ServiceRecord,如果没有找到就会调用 PackageManagerService去获取参数对应的Service信息,并封装到 ServiceRecord然后再封装为一个 ServiceLookupResult并返回。
注释2:把封装的 ServiceRecord给拿出来。 ServiceRecord用来描述一个Service
注释3:把 ServiceRecord传入到 startServiceInnerLocked()方法中
我们继续看一下这个方法:

// ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }
        ...
        return r.name;
    }

startServiceInnerLocked()中调用了这么一个方法 bringUpServiceLocked()

// ActiveServices.java
 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ...
        //1获取Service所要运行的进程
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
            //2
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            //3
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //4. 启动Service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } else {
            ...
        }
        // 5 
        if (app == null && !permissionsReviewRequired) {
             // 6
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            ...
        }
        ...
        return null;
    }

注释1:从ServiceRecord中获取 processName赋值给 procName
注释2:根据 procName和Service的uid来传入到 AMS的 getProcessRecordLocked()中,查询是否存在一个与Service对应的ProcessRecord类型对象。
如果不存在,则在注释5、6中调用 AMS的 startProcessLocked()来创建一个引用程序进程。
如果存在,则在注释3、4中调用 realStartServiceLocked()来启动一个Service。

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ...
        try {
            ....
            //1
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
           ...
        } 
        ...
    }

这里也有一个Real方法。app.thread.scheduleCreateService即调用调用主线程的 scheduleCreateService()的方法。
我们知道 app.thread就是 IApplicationThread,通过AIDL,这时候的代码从 SystemServer进程到了 应用程序的进程中。

// ActivityThread.java
 public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            sendMessage(H.CREATE_SERVICE, s);
        }

这里创建了一个 CreateServiceData类,把Service的信息都封装了进去,设置一个 H.CREATE_SERVICE字段,sendMessage出去。
到了 ApplicationThread这里,免不了要使用Handler来将线程切换到主线程去。我们直接来看看 H是怎么处理这个信息的吧

// ActivityThread.java
public void handleMessage(Message msg) {
   switch (msg.what) {
      case CREATE_SERVICE:
           Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
           //1
           handleCreateService((CreateServiceData)msg.obj);
           Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           break;
     }
}

到了主线程中,调用 handleCreateService():

private void handleCreateService(CreateServiceData data) {
        // 获取要启动Service的应用程序的 LoadedApk
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            //1
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            ...
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            //创建上下文环境
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //2
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //3
            service.onCreate();
            //4
            mServices.put(data.token, service);
           ...
        } catch (Exception e) {
          ...
        }
    }

这里的代码和创建Activity时的非常相似。
注释1:通过LoadedApk的getClassLoader()来获取一个类加载器。然后根据 CreateServiceData 来创建一个 Service实例。
注释2:通过 service.attach()来初始化一个service
注释3:调用这个 service的 onCreate()方法。这里 service就启动了。
注释4:最后,把这个service放到 ActivityThread的成员变量 mServices中,它是一个 ArrayMap

至此,一个Service的完整的创建启动流程就over了。
下面来讲解绑定一个Service。

2.Service的绑定流程

因为Service的开启方法有 startService() , 也有 bindService()
Service的绑定过程分成3个部分

  1. ContextImpl到AMS的调用过程
  2. AMS调用 bindService() 到 publishService() 过程
  3. AMS到 ServiceConnection的过程

2.1 ContextImpl到AMS的调用过程

我们先来看一下时序图:
在这里插入图片描述

在代码中调用 context.bindService(),就是调用 mBase.bindService()
从之前我们学过, mBase就是 ContextImpl。我们来看看它的 bindService()

// ContextImpl.java
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

这个方法传入了 IntentServiceConntection(Service连接的回调),和 flags,然后这个方法里面带上了 主线程的Handler,传入到 bindServiceCommom里面去:

// ContextImpl.java
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            //1
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            ...
            // 2
            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();
        }
    }

在注释1中,通过 LoadedApk.getServiceDispatcher()将传进来的 ServiceConnection封装成一个 IServiceConnection对象。
也就是说 ServiceConnection也是实现了Binder的。
注释2中:调用 ActivityManager.getSerive()IActivityManager.bindSerive(),这里代码进入到 AMS层。

2.2 AMS调用 bindService() 到 publishService() 过程

先来看看时序图:
在这里插入图片描述
我们来看看 AMS的 bindService()

// ActivityManagerService
    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);
        }
    }

省略号中的代码都是异常判断处理。
synchronized中调用了 ActiveService.bindServiceLocked()

// ActivityManagerService.java
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
            ...
             try {
                 ...
                 //1
                 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
                 
                 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                     s.lastActivity = SystemClock.uptimeMillis();
                     //2
                     if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                        return 0;
                      }
                  }
                  ...
                  //3
                  if (s.app != null && b.intent.received) {
                      try {
                          //4
                          c.conn.connected(s.name, b.intent.binder, false);
                      } ...
                    if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                      //5
                      requestServiceBindingLocked(s, b.intent, callerFg, true);
                    }
                   } else if (!b.intent.requested) {
                       //6
                       requestServiceBindingLocked(s, b.intent, callerFg, false);
                   }
            ...

    }

这个方法里面出现了几个 Record,我们来看一下他们分别描述什么:

  • ServiceRecord
    用来描述一个 Service
  • ProcessRecord
    描述一个进程
  • ConnectionRecord
    描述应用程序进程和 Service建立的一次通信
  • AppBindRecord
    应用程序进程通过Intent绑定Service时,会通过AppBindRecord来维护Service与应用程序进程之间的关联。
    其内部会创建并存储了 谁绑定的Service(ProcessRecord)、被绑定的Service(AppBindRecord)、绑定Service的 Intent(IntentBindRecord)和所有绑定通信记录的信息(ArraySet<ConnectionRecord>
  • IntentBindRecord
    用于描述绑定Service的Intent
    注:不同的应用进程也可能会创建相同的Intent来绑定同一个Serivce。比如说一些公共的、常用的Service。

注释1:调用了 ServiceRecord.retrieveAppBindingLocked(),获取一个service的 AppBindRecord对象。我们在前面关于AppBindRecord的介绍可以看到,它内部会创建 IntentBindRecord并赋值。

注释2:如果传进来的flags == BIND_AUTO_CREATE就会调用了 bringUpServiceLocked(),其内部会调用 realStartServiceLocked(),这个方法我们学习Service的启动流程的时候学到过,其为与服务端的最后一个方法,它会通过Binder最终到 ActivityThread去,然后调用 Service.onCreate()。这也就是说在Service的绑定流程中也会去启动Serivce。

注释3: s.app != nul表示Service已经运行。其中s是ServiceRecord, app是ProcessRecord。 b.intent.received表示当前应用进程已经接收到绑定Service时返回的Binder,这样应用程序就可以通过Binder来获取要绑定的Service的访问接口。

注释4:调用c.conn的 connected,其中 c.conn就是我们一开始封装好的 IServiceConenction,它的具体实现类为 ServiceDispatcher.InnerConnection,其中ServiceDispatcher是 LoadedApk的内部类,InnerConnection的 connected方法会调用H的post()向主线程发送消息。

注释5:如果当前应用程序进程是第一个与Service进行绑定的,并且Service已经调用过 onUnBind(),则就会调用 requestServiceBindingLocked(...,true),最后的参数 rebind是true

注释6:如果应用程序进程的Client端没有发送过绑定Service的请求,则也会调用 requestServiceBindingLocked(...,flase)。最后的rebind是flase

我们来看下注释5的 requestServiceBindingLocked()

// ActivesServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        ...
        //1
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                //2
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
                ...
            }
        }
        return true;
    }

注释1中的 i.requested表示 是否发送过绑定Service的请求,从bindServiceLocked可以得知已经发送过绑定了,因此 !i.requested == false。从 bindServiceLocked中我们得知 rebind为true。所以这里是可以继续走下去的。
i.apps.size() 中,i指的是 IntenBindRecord,AMS会为每个绑定的Service的Intent分配一个IntentBindRecord对象。我们来看一下IntentBindRecord的代码:

// ActiveServices.java
final class IntentBindRecord {
    //被绑定的Service
    final ServiceRecord service;
    //绑定Service的Intent
    final Intent.FilterComparison intent; // 
    //所有用当前Intent绑定Service应用程序进程
    final ArrayMap<ProcessRecord, AppBindRecord> apps
            = new ArrayMap<ProcessRecord, AppBindRecord>();
    ...
}

不同的应用程序进程可能使用同一个Intent来绑定Service,所以我们看到 apps用来存储这些进程。
之前说过 i.apps.size() > 0就是说明已经有Intent绑定了Serivice了。下面来验证 i.apps.size()>0为true。我们回到 bindServiceLocked()的注释1代码处,即 retrieveAppBindingLocked()

// ServiceRecord.java
    public AppBindRecord retrieveAppBindingLocked(Intent intent,
            ProcessRecord app) {
        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
        IntentBindRecord i = bindings.get(filter);
        if (i == null) {
            //1
            i = new IntentBindRecord(this, filter);
            bindings.put(filter, i);
        }
        //2
        AppBindRecord a = i.apps.get(app);
        if (a != null) {
            return a;
        }
        //3
        a = new AppBindRecord(this, i, app);
        i.apps.put(app, a);
        return a;
    }

注释1:创建了 IntentBindRecord
注释2:根据ProcessRecord获取了 AppBindRecord,如果其不为null就会返回。
如果为null就在注释3中,创建一个新的 AppBindRecord,并将其put到 apps中,key为 ProcessRecord。

这里代码也就表明, i.apps.size() > 0是为true的。 这样也就会调用上述 requestServiceBindingLocked(...,true)中,注释2 的代码。
r.app.thread 是 IApplicationThread,所以 它执行的 scheduleBindService()肯定就是通过调用 H类来切换线程到ActivityThread中。
因为这里很熟悉,我们直接看ActivityThread最终会执行什么代码:

// ActivityThread.java
public void handleMessage(Message msg) {
    switch (msg.what) {
       case BIND_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
            handleBindService((BindServiceData)msg.obj);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
            ...
    }
}

    private void handleBindService(BindServiceData data) {
        //1
        Service s = mServices.get(data.token);
        ...
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    //2
                    if (!data.rebind) {
                        //3
                        IBinder binder = s.onBind(data.intent);
                        //4
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        //5
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } ...
            } ...
        }
    }

handleBindService()中,我们得知:
注释1:获取要绑定的Service

注释2:BindServiceData这个类的成员变量 rebind的值为false,就会调用注释3的 Service.onBind()方法,到这里Service就绑定成功了。

注释5:否则执行 Service.onRebind(),如果当前应用程序进程第一个与Service绑定,并且Service已经调用过 onUnBind(),则会调用Service的 onReBind()

handleBindService有两个分支,一个是绑定过的Service的情况,一个是未绑定过Service的情况。这里分析没有绑定过的情况。
也就是注释3、注释4的代码。

注释3我们已经了解了,就是调用Service.onBind(),在接下来的注释4中,调用了 ActivityManagerService.publishService(),这相当于又回到AMS中。

2.3 AMS到 ServiceConnection的过程

我们先来看一下从AMS到ServiceConnection的过程的时序图:
在这里插入图片描述
在AMS的publishService里面调用了 ActiveServices.publishServicedLocked(),我们来看看这个方法

// ActiveServices.java
    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
           ...
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                       ...
                            try {
                                //1
                                c.conn.connected(r.name, service, false);
                            } ...
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } ...
    }

这个方法传入一个ServiceRecord,然后会去遍历每个绑定这个Service的Intent,每个就是一个 ConnectionRecord,也就是c
调用 c.conn就是获取到每次遍历的 IServiceConnection,它的作用是解决当前应用程序进程和Service跨进程通信的问题。
具体实现为类ServiceDispatcher.InnerConnection,我们来看看 InnerConnection的connected()

// LoadedApk.java
tatic final class ServiceDispatcher {
        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) {
                    //1
                    sd.connected(name, service, dead);
                }
            }
        }
}

connected()其实就是执行 ServiceDispatcherconnected()

// LoadedApk.java
 public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityThread != null) {
                //1
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

注释1:调用应用程序主线程Handler(H对象)的 post(),将 RunConnection对象的内容运行在主线程。
我们来看看 RunConnection是啥:

// LoadedApk.java
 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) {
                    doConnected(mName, mService, mDead);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
            final boolean mDead;
        }

它实现了Runnable接口,传入了 command = 0 的参数并赋值给了 mCommand。
在run方法里面,因为 mCommand == 0,所以会跑 doConnected(),我们来看看这个方法:

//LoadedApk.java
        public void doConnected(ComponentName name, IBinder service, boolean dead) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;
            ...
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (dead) {
                mConnection.onBindingDied(name);
            }
            if (service != null) {
                //1
                mConnection.onServiceConnected(name, service);
            }
        }

在最后的注释1中,调用了 ServiceConnection.onServiceConnected(),而mConnetion就是我们从一开始传进来的回调函数。
当走到回调函数时,说明Service已经完成绑定了。
这个时候,整个绑定流程就结束了。

3.总结

我们使用Service有两种方式,分别是 startService()bindService()
这两个方法是 ContextWrapper调用,而具体实现在 ContextImpl中。在ContextImpl通过 实现了Binder机制的ActivityManager来把参数带入到 AMS所在的服务端(即SystemServer进程)。
Service的绑定或创建都是在 AMS完成的。最后通过Binder机制通知应用程序进程的ActivityThread来处理Service创建后的回调。

从源码我们可以看出,这两种开启Service的方法的异同:

  1. startService()的关键方法是调用 bringUpServiceLocked()-> realStartServiceLocked()启动一个Service
    bindService()如果在传入进来的flags == BIND_AUTO_CREATE,它也会调用这两个方法。这个flags也是我们平时都用到的。
    也就是说,bindService() 它也会去做startService()做的启动Serivce的工作。
  2. 可能之前有人在刷面试题关于两者区别的时候会看到一个:startService和调用者无关联,而bindService和调用者有关联(比如Service跟着Activity一起死)。看了源码后,这里就不难理解,因为bindService会创建一个 IntentBindRecord它里面维护了一个List,用来描述 是谁绑定了Service。所以维护了这个列表,调用者就和Service建立了一个关系。

其实还有别的区别,只是我上述的源码还不够全面,比如说没有往下深入到生命周期,但是了解了这些源码的走向和流程,接下来的东西应该都不难理解了。

发布了263 篇原创文章 · 获赞 110 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/rikkatheworld/article/details/104533169
今日推荐