Android系统源码分析——Service启动流程

发表于:2018-5-04 13:29

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:翰墨飘香    来源:51testing软件测试网采编

  在前面文章我们分析了四大组件中的两个:Broadcast和Activity,这章我们分析四大组件中的服务(Service)的启动过程。Service的启动方式有两种:一种是startService,一种是bindService;第一种通常是开启一个服务执行后台任务,不进行通信,第二章通过是启动服务进行通信。下面我们就根据这两种启动方式来讲Service的启动流程以及unbindService和stopService流程。
  Service启动流程-startService
  首先来看启动流程时序图:
  Service1.jpg
  Step0.ContextImpl.startService
      @Override
      public ComponentName startService(Intent service) {
          warnIfCallingFromSystemProcess();
          return startServiceCommon(service, mUser);
      }
  调用当前类中的startServiceCommon方法。
  Step1.ContextImpl.startServiceCommon
      private ComponentName startServiceCommon(Intent service, UserHandle user) {
          try {
              // 检验Intent,组件和包名不能为空
              validateServiceIntent(service);
              service.prepareToLeaveProcess(this);
              // 通过getDefault方法获取AMS的一个代理对象(ActivityManagerProxy),然后调用这个代理对象
              // 的startService方法来请求AMS启动Service
              ComponentName cn = ActivityManagerNative.getDefault().startService(
                      mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                              getContentResolver()), getOpPackageName(), user.getIdentifier());
              ...
              return cn;
          } catch (RemoteException e) {
              ...
          }
      }
  首先验证Intent中传递的组件名是否为空,为什么判断下面我们介绍,接着通过代理对象ActivityManagerProxy,通过Binder调用AMS(ActivityManagerService)中的对应方法startService。我们先看包名验证。
  Step2.ContextImpl.validateServiceIntent
      private void validateServiceIntent(Intent service) {
          if (service.getComponent() == null && service.getPackage() == null) {
              if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
                  IllegalArgumentException ex = new IllegalArgumentException(
                          "Service Intent must be explicit: " + service);
                  throw ex;
              } else {
                  Log.w(TAG, "Implicit intents with startService are not safe: " + service
                          + " " + Debug.getCallers(2, 3));
              }
          }
      }
  这里给出了如果系统在Android5.0及以上版本,启动服务必须为显式启动,否则抛出异常,这个情况我们在刚开始在高于5.0系统都会遇到过,限制就在这里,所以,5.0及以上系统必须用显式的方式启动服务。
  3.AMP.startService
      public ComponentName startService(IApplicationThread caller, Intent service,
                                        String resolvedType, String callingPackage, int userId) throws RemoteException {
          ...
          // 通过Binder对象mRemote向AMS发送一个类型为START_SERVICE_TRANSACTION的进程间通信请求,
          // 然后会调用AMS中的对应的startService方法
          mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
          ...
          return res;
      }
  看过前面文章的对这一段代码应该很熟悉了,这个就是通过Binder调用AMS中对应方法的。所以我们直接看AMS。
  4.AMS.startService
      public ComponentName startService(IApplicationThread caller, Intent service,
                                        String resolvedType, String callingPackage, int userId)
              throws TransactionTooLargeException {
          ...
          synchronized (this) {
              ...
              ComponentName res = mServices.startServiceLocked(caller, service,
                      resolvedType, callingPid, callingUid, callingPackage, userId);
              Binder.restoreCallingIdentity(origId);
              return res;
          }
      }
  这里的mServices是ActiveServices,因此调用的是ActiveServices中的startServiceLocked方法。
  5.ActiveServices.startServiceLocked
      ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                                       int callingPid, int callingUid, String callingPackage, final int userId)
              throws TransactionTooLargeException {
          ...
          
          // 解析service这个Intent,就是解析在AndroidManifest.xml定义的Service标签的intent-filter相关内容
          // 并将其内容保存在Service的record(ServiceRecord)中
          ServiceLookupResult res =
                  retrieveServiceLocked(service, resolvedType, callingPackage,
                          callingPid, callingUid, userId, true, callerFg, false);
          ...
          // 每一个Service组件都使用一个ServiceRecord对象来描述,就像每一个Activity都是用一个ActivityRecord
          // 对象来描述一样
          ServiceRecord r = res.record;
          ...
          // 加入启动服务列表
          r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                  service, neededGrants));
          final ServiceMap smap = getServiceMap(r.userId);
          boolean addToStarting = false;
          // 如果是非前台(后台)进程调用
          if (!callerFg && r.app == null
                  && mAm.mUserController.hasStartedUserState(r.userId)) {
              // 获取启动服务所在进程
              ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
              ...
          } else if (DEBUG_DELAYED_STARTS) {
              ...
          }
          return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
      }
  这里做的主要是启动服务前的准备工作,首先是解析Intent携带的参数,并将这些内容保存在用来描述Service的ServiceRecord对象中保存起来,并将该对象放到等待启动服务的列表中。然后调用startServiceInnerLocked启动服务。在上面调用retrieveServiceLocked函数解析的过程中先去判断AMS中是否存在参数为service对应的ServiceRecord对象,如果存在说明已经启动过该服务,如果不存在,说明是第一次启动该服务。
  8.ActiveServices.startServiceInnerLocked
     ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
                                            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
          ServiceState stracker = r.getTracker();// 获取服务状态
          ...
          r.callStart = false;// 是否调用onStart方法
          ...
          // 启动ServiceRecord对象r所描述的一个Service组件,即Server组件
          String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
          ...
          return r.name;
      }
  这里比较简单主要是调用bringUpServiceLocked唤起服务。
  Step9.ActiveServices.bringUpServiceLocked
      private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                                          boolean whileRestarting, boolean permissionsReviewRequired)
              throws TransactionTooLargeException {
              
          // 这里的r.app.thread是一个ApplicationThread对象,ApplicationThread是用来AMS和应用进程通信的工具,
          // 如果服务中的这个thread不为空说明已经和该Service存在通信了,也就是说已经启动了该服务了。
          // 如果服务已经存在,调用startService的时候会执行Service.onStartCommand,
          // 只有首次启动服务才会调用onCreate方法
          if (r.app != null && r.app.thread != null) {
              // 执行Service.onStartCommand方法过程
              sendServiceArgsLocked(r, execInFg, false);
              return null;
          }
          ...
          // Make sure that the user who owns this service is started.  If not,
          // we don't want to allow it to run.
          // 确保正在启动服务的用户已经启动,否则不允许执行
          if (!mAm.mUserController.hasStartedUserState(r.userId)) {
              ...
              bringDownServiceLocked(r);
              return msg;
          }
          ...
          // 是不是独立进程
          final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
          // 首先获取ServiceRecord对象r所描述的Service组件的android:process属性,并保存在procName中
          final String procName = r.processName;
          ProcessRecord app;
          if (!isolated) {// 要启动的服务不是独立进程
              // 如果不是独立进程,通过进程名称和uid查找是否已经存在一个对应的ProcessRecord对象app,如果存在,
              // 说明用来运行这个Service组件的应用进程已经存在了,因此下面的realStartServiceLocked函数在
              // ProcessRecord对象app所描述的应用程序进程中启动这个Service组件。
              app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
              if (app != null && app.thread != null) {// 进程存在,并且该进程已经与AMS通信过,那么直接启动服务
                  try {
                      ...
                      // 启动服务
                      realStartServiceLocked(r, app, execInFg);
                      return null;
                  } catch (TransactionTooLargeException e) {
                      ...
                  }
                  // If a dead object exception was thrown -- fall through to
                  // restart the application.
              }
          } else {// 如果要启动的进程是独立进程
              ...
          }
          // 如果要启动的Service所在进程没有启动
          if (app == null && !permissionsReviewRequired) {
              // 启动Service所需要的进程
              if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                      "service", r.name, false, isolated, false)) == null) {
                  ...
                  // 启动失败
                  bringDownServiceLocked(r);
                  return msg;
              }
              ...
          }
          ...
          if (r.delayedStop) {// 如果是延迟停止的服务
              // Oh and hey we've already been asked to stop!
              r.delayedStop = false;
              if (r.startRequested) {
                  // 停止服务
                  stopServiceLocked(r);
              }
          }
          return null;
      }
  这里是启动服务最重要的部分,根据不同的情况进行不同的处理。首先是判断服务所在进程是否存在,如果存在调用sendServiceArgsLocked方法,最终根据条件,如果服务存在调用服务的onStartCommand方法;然后判断被启动服务的用户是否已经被启动,如果没有则停止服务,也就是调用bringDownServiceLocked方法,最终调用服务的onDestroy方法;然后判断非独立进程的服务,如果进程存在并且服务未启动的开始正式启动服务,调用realStartServiceLocked方法,最终调用onCreate方法;然后判断如果进程不存在,要启动进程,并且在app启动后启动服务,这里会调用启动失败,停止启动,因为进程启动后会启动该服务,这个过程在前面我们讲过,这里不再分析这种情况。最后是如果是延迟停止的服务这里直接停止该服务。下面我们按顺序分析这几种情况。
  Step10.ActiveServices.sendServiceArgsLocked
      private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                                               boolean oomAdjusted) throws TransactionTooLargeException {
          // 等待启动服务个数
          final int N = r.pendingStarts.size();
          if (N == 0) {
              return;
          }
          while (r.pendingStarts.size() > 0) {
              ...
              try {
                  ..
                  // 标记启动服务开始
                  bumpServiceExecutingLocked(r, execInFg, "start");
                  ...
                  // 发送消息,传动到ApplicationThread中的scheduleServiceArgs方法,最终会调用onStartCommand
                  r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
              } catch (TransactionTooLargeException e) {
                  ...
              } 
          }
      }
  上面Step5提到启动的服务都要先放到等待启动服务列表中,因此这里先判断服务列表是否存在要启动的服务,如果不存在则不再继续执行,如果存在,循环启动服务,这里调用scheduleServiceArgs方法,其实在前面分析了很多遍,最终会发送消息ActivityThread中的Handler中的handleMessage中进行处理,然后调用ActivityThread中的handleServiceArgs方法。
  Step13.ActivityThread.handleServiceArgs
      private void handleServiceArgs(ServiceArgsData data) {
          // 获取Service对象
          Service s = mServices.get(data.token);
          if (s != null) {
              try {
                  ...
                  if (!data.taskRemoved) {// 任务没有被移除的话,调用Service.onStartCommand方法
                      res = s.onStartCommand(data.args, data.flags, data.startId);
                  } else {// 否则调用被移除方法
                      s.onTaskRemoved(data.args);
                      res = Service.START_TASK_REMOVED_COMPLETE;
                  }
                  ...
              } catch (Exception e) {
                  ...
              }
          }
      }
  根据Service对应的token去缓存中获取服务,如果有该服务那么调用服务的onStartCommand方法,如果不存在那么就要继续往下走创建服务。
  Step15.ActiveServices.bringDownServiceLocked
  这个方法主要是处理停止服务的方法,里面主要是断开连接,解除绑定,然后销毁服务,因为这个过程是在服务停止时会调用,所以在后面介绍,这里先不介绍了。
  Step16.ActiveServices.realStartServiceLocked
      private final void realStartServiceLocked(ServiceRecord r,
                                                ProcessRecord app, boolean execInFg) throws RemoteException {
          ...
          boolean created = false;
          ...
              // 发送信息到主线程,准备调用Service.onCreate方法
              // 请求ProcessRecord对象app描述的应用程序进程将ServiceRecord独享r所描述的Service组件启动起来。
              // ServiceRecord对象r所描述的Service组件启动完成之后,AMS就需要将它连接到一个请求绑定它的一个
              // Activity组件中,这是通过调用AMS类的另一个成员函数requestServiceBindingLocked来实现的
              app.thread.scheduleCreateService(r, r.serviceInfo,
                      mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                      app.repProcState);
          ...
          // 准备调用Service.onBind方法
          requestServiceBindingsLocked(r, execInFg);
          ...
          // 准备调用Service.onStartCommand方法
          sendServiceArgsLocked(r, execInFg, true);
          ...
      }
  启动服务调用三个方法,首先是通过app.thread.scheduleCreateService方法调用onCreate方法,然后通过requestServiceBindingsLocked方法调用Service.onBind方法,然后通过sendServiceArgsLocked方法调用Service.onStartCommand方法,其中最后一个方法我们分析过了,所以我们只分析前两个。第一很简单了,最终调用ActivityThread中的handleCreateService方法。
  Step18.ActivityThread.handleCreateService
      private void handleCreateService(CreateServiceData data) {
          ...
          // 获取一个用来描述即将要启动的Service组件所在的应用程序的LoadedApk对象,并将它保存在packageInfo
          // 变量中(每一个应用程序都使用一个LoadedApk对象来描述,通过它就能方位到它所描述的应用程序的资源)
          LoadedApk packageInfo = getPackageInfoNoCheck(
                  data.info.applicationInfo, data.compatInfo);
          Service service = null;
          ...
              // 获取类加载器
              java.lang.ClassLoader cl = packageInfo.getClassLoader();
              // 通过类加载器将CreateServiceData对象data描述的一个Service组件加载的内存中,并且创建它的一个
              // 实例,保存在Service对象service中。因为CreateServiceData对象data描述的Service组件即为应用
              // 程序的Ashmem中的Server组件,因此,Service对象service指向的Service组件实际上是一个Server组件
              service = (Service) cl.loadClass(data.info.name).newInstance();
          ...
              // 初始化一个ContextImpl对象context,用来为前面所创建的Service对象service的运行上下文环境,
              // 通过它可以访问特定的应用程序资源,以及启动其他应用程序组件
              ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
              context.setOuterContext(service);
              // 创建一个Application对象app,用来描述Service对象service所属的应用程序。
              Application app = packageInfo.makeApplication(false, mInstrumentation);
              // 使用Application对象app,ContextImpl对象context和CreateServiceData对象data来初始化
              // Service对象service
              service.attach(context, this, data.info.name, data.token, app,
                      ActivityManagerNative.getDefault());
              // 调用Service的onCreate方法
              service.onCreate();
              // 以token为关键字保存Service对象service到mServices中,服务启动完成
              mServices.put(data.token, service);
              ...
          } catch (Exception e) {
              ...
          }
      }
  首先获取LoadedApk对象,然后通过类加载器加载Service类,初始化Context,获取对应的Application,如果存在直接返回,如果该应用还没启动则直接创建该Application,然后通过Service的attach方法将对应的信息放置到Service中,这里面就包含ActivityThread,因此我们在Step9中可以通过这个来判断Service是不是被启动了,然后调用onCreate方法,创建完成后,将该服务以token为键,Service为值放入到缓存中,这样我们前面获取的时候就只从这里获取的,因此如果服务启动了换粗就会存在,否则不存在。下面我们分析onBind方法。
  Step20.ActiveServices.requestServiceBindingsLocked
      // 参数r指向一个ServiceRecord,表示一个已经启动的Service组件
      private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
              throws TransactionTooLargeException {
          for (int i = r.bindings.size() - 1; i >= 0; i--) {
              // 每一个IntentBindRecord对象都用来描述若干个需要将ServiceRecord对象r所描述的Service组件
              // 绑定到它们里面的应用程序进程
              IntentBindRecord ibr = r.bindings.valueAt(i);
              if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                  break;
              }
          }
      }
  for循环调用onBind。
  Step21.ActiveServices.requestServiceBindingLocked
      // 参数rebind表示是否需要将ServiceRecord对象r所描述的Service组件重新绑定到IntentBindRecord对象i
      // 所描述的应用程序进程中如果为false,则说明为第一绑定
      private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
                                                        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
          ...
          // 检查AMS是否已经为IntentBindRecord对象i所描述的应用程序进程请求过ServiceRecord对象r所描述的
          // Service组件返回其内部的一个Binder本地对象。如果还没有请求requested为false并且apps的数量大于0
          if ((!i.requested || rebind) && i.apps.size() > 0) {
              try {
                  ...
                  //会执行到Service的onBind方法
                  r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                          r.app.repProcState);
                  if (!rebind) {
                      // 设置为true,防止重复请求
                      i.requested = true;
                  }
              ...
              }
          }
          return true;
      }
  这里通过调用r.app.thread.scheduleBindService方法,最终调用到ActivityThread中的handleBindService方法。
  Step23.ActivityThread.handleBindService
      private void handleBindService(BindServiceData data) {
          // 通过token来获得一个描述Service组件的Service对象
          Service s = mServices.get(data.token);
          if (s != null) {
              try {
                 ...
                      if (!data.rebind) {// 首次绑定
                          // 获取一个实现了IBinder接口的Binder对象
                          IBinder binder = s.onBind(data.intent);
                          ...
                      } else {
                          s.onRebind(data.intent);
                          ...
                      }
                  ...
              } catch (Exception e) {
                  ...
              }
          }
      }
  现获取服务,然后判断是再次绑定还是首次绑定,如果是首次绑定调用Service.onBind方法,如果是再次绑定调用Service.onRebind方法。到这里服务的启动就完成了,其他一些操作就不分析了。下面我们先分析另外一个启动流程bindService,最后分析停止服务流程。
  Service启动流程-bindService
  首先来看绑定流程时序图:
  Step1.ContextImpl.bindService
      public boolean bindService(Intent service, ServiceConnection conn,
                                 int flags) {
          warnIfCallingFromSystemProcess();
          return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                  Process.myUserHandle());
      }
  这里是绑定服务的入口位置,调用bindServiceCommon方法。
  Step2.ContextImpl.bindServiceCommon
      private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
              handler, UserHandle user) {
          IServiceConnection sd;
          ...
          // mPackageInfo类型是LoadedApk
          if (mPackageInfo != null) {
              // 将ServiceConnection对象conn封装成一个实现了IServiceConnection接口的Binder本地对象sd
              sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
          } else {
              ...
          }
          ...
          try {
              IBinder token = getActivityToken();
              ...
              // 通过调用代理对象ActivityManagerProxy的bindService方法将前面获得的sd对象,以及Intent对象
              // service等信息发送给AMS,以便AMS可以将ServiceConnection组件启动起来
              int res = ActivityManagerNative.getDefault().bindService(
                      mMainThread.getApplicationThread(), getActivityToken(), service,
                      service.resolveTypeIfNeeded(getContentResolver()),
                      sd, flags, getOpPackageName(), user.getIdentifier());
              ...
              return res != 0;
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  首先调用LoadedApk中的getServiceDispatcher方法获取实现IServiceConnection接口的Binder对象ServiceDispatcher.InnerConnection。然后调用AMP中的bindService方法,然后通过Binder通信调用AMS中的bindService方法。
  Step3.LoadedApk.getServiceDispatcher
      // 每一个绑定过Service组件的Activity组件在LoadedApk类中都有一个对应的ServiceDispatcher对象,它负责将
      // 这个被绑定的Service组件与绑定它的Activity组件关联起来,这些ServiceDispatcher保存在map中
      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);
              // 检查成员变量mServices中是否存在一个以ServiceConnection对象c为关键字的ServiceDispatcher
              // 对象sd,如果不存在,则创建一个并且以context为关键字保存到mServices中
              if (map != null) {
                  sd = map.get(c);
              }
              if (sd == null) {
                  sd = new ServiceDispatcher(c, context, handler, flags);
                  if (map == null) {
                      map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                      mServices.put(context, map);
                  }
                  map.put(c, sd);
              } else {
                  sd.validate(context, handler);
              }
              // 调用前面获取到的ServiceDispatcher对象sd的成员函数getIServiceConnection来获取一个实现了
              // IServiceConnection接口的本地Binder对象
              return sd.getIServiceConnection();
          }
      }
  首先根据ServiceConnection取缓存中获取,如果没有要初始化一个ServiceDispatcher对象,然后获取ServiceDispatcher.InnerConnection对象并且返回。
  Step6.AMP.bindService
      public int bindService(IApplicationThread caller, IBinder token,
                             Intent service, String resolvedType, IServiceConnection connection,
                             int flags, String callingPackage, int userId) throws RemoteException {
          ...
          // 通过Binder对象mRemote向AMS发送一个类型为BIND_SERVICE_TRANSACTION的进程间通信请求
          mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
          ...
          return res;
      }
  这里通过Binder调用AMS中对应的方法。
  Step7.AMS.bindService
      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.bindServiceLocked方法。
  Step8.ActiveServices.bindServiceLocked
      int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                            String resolvedType, final IServiceConnection connection, int flags,
                            String callingPackage, final int userId) throws TransactionTooLargeException {
          if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                  + " type=" + resolvedType + " conn=" + connection.asBinder()
                  + " flags=0x" + Integer.toHexString(flags));
          // 根据caller来获取一个ProcessRecord对象callerApp用来描述AMS执行绑定Service组件操作的一个Activity
          // 组件所运行在的应用程序进程
          final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
          ...
          ActivityRecord activity = null;
          if (token != null) {
              // 通过token来获得一个ActivityRecord对象activity,用来描述正在请求AMS执行绑定Service组件
              // 操作的一个Activity组件
              activity = ActivityRecord.isInStackLocked(token);
              if (activity == null) {
                  Slog.w(TAG, "Binding with unknown activity: " + token);
                  return 0;
              }
          }
          ...
          final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
          // 是否是绑定了外部服务,这个服务不是应用中的服务,而是外部独立的服务(我们通常启动服务都是应用内部的服务)
          final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
          // 根据参数service来得到一个ServiceRecord对象s,用来描述即将被绑定的Service组件
          ServiceLookupResult res =
                  retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                          Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
          ...
              // 调用ServiceRecord对象s的成员函数retrieveAppBindingLocked来得到一个AppBindRecord对象b,
              // 表示ServiceRecord对象s所描述的Service组件是绑定在ProcessRecord对象callerApp所描述的一个
              // 应用程序进程中的
              AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
              // 将前面获得的APPBindRecord对象、ActivityRecord对象Activity以及参数connection封装成一个
              // ConnectionRecord对象s所描述的一个Service组件,并且这个Activity组件是运行在
              // ProcessRecord对象callerApp所描述的一个应用进程中的
              ConnectionRecord c = new ConnectionRecord(b, activity,
                      connection, flags, clientLabel, clientIntent);
              // 由于一个Service组件可能会被同一个应用程序进程中的多个Activity组件使用同一个InnerConnection
              // 对象来绑定,因此,在AMS中,用来描述该Service组件的ServiceRecord对象就有可能会对应有多个
              // ConnectionRecord对象。在这种情况下,这些ConnectionRecord对象就会被保存在一个列表中。
              // 这个列表最终会保存在对应的ServiceRecord对象的成员变量Connection所描述的HashMap中,并且以
              // 它里面的ConnectionRecord对象共同使用的一个InnerConnection代理对象的IBinder接口为关键字
              // 参数connection是一个InnerConnection代理对象,因此可以获取它的一个IBinder接口binder
              IBinder binder = connection.asBinder();
              // 检测在ServiceRecord对象s中是否存在一个以IBinder接口binder为关键字的列表clist,如果不存在
              // 创建一个,并且将clist以binder为关键字放到ServiceRecord对象成员变量connections中
              ArrayList<ConnectionRecord> clist = s.connections.get(binder);
              if (clist == null) {// 没有绑定过
                  clist = new ArrayList<ConnectionRecord>();
                  s.connections.put(binder, clist);
              }
              clist.add(c);// 添加绑定列表
              b.connections.add(c);// 添加到关联应用和服务的对象AppBindRecord中记录绑定列表中
              if (activity != null) {
                  if (activity.connections == null) {// 这里判断Activity里面是否绑定过服务
                      activity.connections = new Has

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017