bindService啟動(dòng)流程

本次源碼基于Android11分析

相關(guān)源碼:

/frameworks/base/core/java/android/content/ContextWrapper.java
/frameworks/base/core/java/android/app/ContextImpl.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
/frameworks/base/core/java/android/app/ActivityThread.java

通過bindService啟動(dòng)的Service,會(huì)執(zhí)行Service的onCreate、onBind罢猪、onUnbind只盹、onDestroy方法闯第,可以通過onBind方法返回的Binder對(duì)象和調(diào)用端進(jìn)行通信拣宏,并且Service的生命周期和調(diào)用端同步鲫骗。 如下是啟動(dòng)bindService的代碼

var stu: Student? = null
val connection = object : ServiceConnection {
  override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
      stu = Student.Stub.asInterface(p1)
  }
  override fun onServiceDisconnected(p0: ComponentName?) {
  }
}
val intent = Intent(this, Student::class.java)
bindService(intent, connection, BIND_AUTO_CREATE)


如下是bindService的啟動(dòng)流程:

1.bindService 發(fā)起端進(jìn)程

1.1 ContextWrapper.bindService

public class ContextWrapper extends Context {

  public boolean bindService(Intent service, ServiceConnection conn,
                             int flags) {
      //mBase為ContentImpl
      return mBase.bindService(service, conn, flags);
  }
}

繼續(xù)調(diào)用ContentImpl.bindService方法:

class ContextImpl extends Context {
  
  public boolean bindService(Intent service, ServiceConnection conn, int flags) {
      warnIfCallingFromSystemProcess();
      return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
              getUser());
  }

 final @NonNull LoadedApk mPackageInfo;
  private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                                    String instanceName, Handler handler, Executor executor, UserHandle user) {
      // 將ServiceConnection轉(zhuǎn)換成Binder對(duì)象變量犬耻,用于進(jìn)程間通信
      IServiceConnection sd;
      //...
      if (mPackageInfo != null) {
          // 將ServiceConnection轉(zhuǎn)換成可跨進(jìn)程
          if (executor != null) {
              sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
          } else {
              sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
          }
      } else {
          throw new RuntimeException("Not supported in system context");
      }
      validateServiceIntent(service);
      try {
          //...
          // 調(diào)用AMS.bindIsolatedService方法
          int res = ActivityManager.getService().bindIsolatedService(
                  mMainThread.getApplicationThread(), getActivityToken(), service,
                  service.resolveTypeIfNeeded(getContentResolver()),
                  sd, flags, instanceName, 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();
      }
  }
}

首先將ServiceConnection變量存儲(chǔ)到可跨進(jìn)程通信的Binder對(duì)象并賦值到sd變量,并把sd變量傳給AMS中执泰,后續(xù)AMS通過這個(gè)Binder通信枕磁。最后調(diào)用AMS.bindIsolatedService跨進(jìn)程調(diào)用方法。在分析另一個(gè)AMS進(jìn)程前术吝,先分析本進(jìn)程如何

public final class LoadedApk {

  @UnsupportedAppUsage
  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;
          //...
          // 創(chuàng)建ServiceDispatcher對(duì)象计济,并把ServiceConnection參數(shù)作為其變量之一
          sd = new ServiceDispatcher(c, context, executor, flags);
          //...
          // 返回ServiceDispatcher.InnerConnection內(nèi)部類,其繼承IServiceConnection.Stub顿苇,是個(gè)binder
          return sd.getIServiceConnection();
      }
  }
}

static final class ServiceDispatcher {
  // 返回的是此對(duì)象
  private final ServiceDispatcher.InnerConnection mIServiceConnection;
  // 存儲(chǔ)ServiceConnection的變量
  private final ServiceConnection mConnection;
  private final Context mContext;
  private final Handler mActivityThread;
  private final Executor mActivityExecutor;
  private final ServiceConnectionLeaked mLocation;

  ServiceDispatcher(ServiceConnection conn,
                    Context context, Handler activityThread, int flags) {
      //創(chuàng)建InnerConnection對(duì)象,等會(huì)會(huì)返回該對(duì)象
      mIServiceConnection = new InnerConnection(this);
      //用戶定義的ServiceConnection
      mConnection = conn;
      mContext = context;
      mActivityThread = activityThread;
      mActivityExecutor = null;
      mLocation = new ServiceConnectionLeaked(null);
      mLocation.fillInStackTrace();
      mFlags = flags;
  }

  // 返回的是mIServiceConnection變量峭咒,是Binder類
  IServiceConnection getIServiceConnection() {
      return mIServiceConnection;
  }

  //內(nèi)部的Binder類
  private static class InnerConnection extends IServiceConnection.Stub {

      final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

      // 通過構(gòu)造函數(shù)弱引用ServiceDispatcher對(duì)象,此對(duì)象有ServiceConnection變量
      InnerConnection(LoadedApk.ServiceDispatcher sd) {
          mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
      }

      // 調(diào)用ServiceDispatcher.connected()方法
      public void connected(ComponentName name, IBinder service, boolean dead)
              throws RemoteException {
          LoadedApk.ServiceDispatcher sd = mDispatcher.get();
          if (sd != null) {
              sd.connected(name, service, dead);
          }
      }
  }

  // ServiceDispatcher.connected()的方法
  public void connected(ComponentName name, IBinder service, boolean dead) {
      if (mActivityExecutor != null) {
          // 在線程池執(zhí)行一個(gè)任務(wù)
          mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
      } else if (mActivityThread != null) {
          // 給主線程發(fā)送一個(gè)post一個(gè)任務(wù)
          mActivityThread.post(new RunConnection(name, service, 0, dead));
      } else {
          // 如果上述兩個(gè)都為空纪岁,則執(zhí)行doConnected方法
          doConnected(name, service, dead);
      }
  }

  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) {
              // mCommand為0 ,進(jìn)入doConnected方法
              doConnected(mName, mService, mDead);
          } else if (mCommand == 1) {
              doDeath(mName, mService);
          }
      }

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

  // 調(diào)用ServiceConnection.onServiceConnected()方法
  public void doConnected(ComponentName name, IBinder service, boolean dead) {
      ServiceDispatcher.ConnectionInfo old;
      ServiceDispatcher.ConnectionInfo info;

      synchronized (this) {
          if (mForgotten) {
              return;
          }
          old = mActiveConnections.get(name);
          if (old != null && old.binder == service) {
              return;
          }

          if (service != null) {
              info = new ConnectionInfo();
              info.binder = service;
              //創(chuàng)建死亡監(jiān)聽對(duì)象
              info.deathMonitor = new DeathMonitor(name, service);
              try {
                  //建立死亡通知
                  service.linkToDeath(info.deathMonitor, 0);
                  mActiveConnections.put(name, info);
              } catch (RemoteException e) {
                  mActiveConnections.remove(name);
                  return;
              }

          } else {
              mActiveConnections.remove(name);
          }

          if (old != null) {
              old.binder.unlinkToDeath(old.deathMonitor, 0);
          }
      }

      // 如果有舊服務(wù)凑队,它現(xiàn)在已斷開連接。
      if (old != null) {
          mConnection.onServiceDisconnected(name);
      }
      if (dead) {
          mConnection.onBindingDied(name);
      }
      //如果有新的可行服務(wù)幔翰,它現(xiàn)在已連接漩氨。
      if (service != null) {
          // 回調(diào)用戶定義的ServiceConnection()
          mConnection.onServiceConnected(name, service);
      } else {
          // The binding machinery worked, but the remote returned null from onBind().
          mConnection.onNullBinding(name);
      }
  }

}

創(chuàng)建LoadedApk.ServiceDispatcher類的實(shí)例化對(duì)象,對(duì)象里面包含了一個(gè)Binder對(duì)象LoadedApk.ServiceDispatcher.InnerConnection,方法最后就是返回這個(gè)Binder對(duì)象遗增。AMS也通過這個(gè)Binder對(duì)象通信調(diào)用ServiceConnection.onServiceConnected()方法叫惊。

AMS處理bindService請求

首先調(diào)用AMS的bindIsolatedService方法

public class ActivityManagerService extends IActivityManager.Stub {

  final ActiveServices mServices;

  public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
                                 String resolvedType, IServiceConnection connection, int flags, String instanceName,
                                 String callingPackage, int userId) throws TransactionTooLargeException {
      // 空判斷 ...
      // 調(diào)用ActiveServices.bindServiceLocked方法
      synchronized (this) {
          return mServices.bindServiceLocked(caller, token, service,
                  resolvedType, connection, flags, instanceName, callingPackage, userId);
      }
  }
}

AMS方法首先進(jìn)行空判斷,然后調(diào)用ActiveServices類的bindServiceLocked()方法:

public final class ActiveServices {

  int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                        String resolvedType, final IServiceConnection connection, int flags,
                        String instanceName, String callingPackage, final int userId)
          throws TransactionTooLargeException {

      final int callingPid = Binder.getCallingPid();
      final int callingUid = Binder.getCallingUid();
      //查詢發(fā)起端所對(duì)應(yīng)的進(jìn)程記錄結(jié)構(gòu)
      final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
      if (callerApp == null) {
          throw new SecurityException(
                  "Unable to find app for caller " + caller
                          + " (pid=" + callingPid
                          + ") when binding service " + service);
      }

      ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
      //token不為空, 代表著發(fā)起方具有activity上下文
      if (token != null) {
          activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
          if (activity == null) {
              return 0;
          }
      }

      int clientLabel = 0;
      PendingIntent clientIntent = null;
      final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;

      ...
      //根據(jù)發(fā)送端所在進(jìn)程的SchedGroup來決定是否為前臺(tái)service
      final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;

      // 1. 根據(jù)傳遞進(jìn)來Intent來檢索相對(duì)應(yīng)的服務(wù),service變量就是Intent
      ServiceLookupResult res =
              retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
                      callingPid, callingUid, userId, true,
                      callerFg, isBindExternal, allowInstant);
      // 空檢查
      if (res == null) {
          return 0;
      }
      if (res.record == null) {
          return -1;
      }

      //2. 查詢到相應(yīng)的Service記錄
      ServiceRecord s = res.record;

      final long origId = Binder.clearCallingIdentity();
      try {

          // 調(diào)用ServiceRecord.retrieveAppBindingLocked方法
          AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
          //創(chuàng)建對(duì)象ConnectionRecord,此處connection來自發(fā)起方
          ConnectionRecord c = new ConnectionRecord(b, activity,
                  connection, flags, clientLabel, clientIntent,
                  callerApp.uid, callerApp.processName, callingPackage);

          IBinder binder = connection.asBinder();
          ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
          if (clist == null) {
              clist = new ArrayList<>();
              mServiceConnections.put(binder, clist);
          }
          clist.add(c); // clist是ServiceRecord.connections的成員變量

          if ((flags & Context.BIND_AUTO_CREATE) != 0) {
              //更新當(dāng)前service活動(dòng)時(shí)間
              s.lastActivity = SystemClock.uptimeMillis();
              //3. 啟動(dòng)service做修,這個(gè)過程跟startService過程一致
              if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                      permissionsReviewRequired) != null) {
                  return 0;
              }
          }
        //.....
      return 1;
  }

bindServiceLocked方法主要做了三件事:

  1. 調(diào)用retrieveServiceLocked方法霍狰,根據(jù)Intent解析尋找要啟動(dòng)的Service,并得到ServiceLookupResult對(duì)象實(shí)例饰及。
  2. 根據(jù)ServiceLookupResult對(duì)象實(shí)例得到ServiceRecord對(duì)象蔗坯。
  3. 調(diào)用bringUpServiceLocked方法,開始啟動(dòng)Service燎含。

1. retrieveServiceLocked根據(jù)Intent解析要啟動(dòng)的ServiceRecord

  private ServiceLookupResult retrieveServiceLocked(Intent service,
                                                    String instanceName, String resolvedType, String callingPackage,
                                                    int callingPid, int callingUid, int userId,
                                                    boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
                                                    boolean allowInstant) {
      ServiceRecord r = null;

      userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId,
              /* allowAll= */false, getAllowMode(service, callingPackage),
              /* name= */ "service", callingPackage);

      ServiceMap smap = getServiceMapLocked(userId);
      // 1. 根據(jù)Intent獲取全類名
      final ComponentName comp;
      if (instanceName == null) {
          comp = service.getComponent();
      } else {
          final ComponentName realComp = service.getComponent();
          if (realComp == null) {
              throw new IllegalArgumentException("Can't use custom instance name '" + instanceName
                      + "' without expicit component in Intent");
          }
          comp = new ComponentName(realComp.getPackageName(),
                  realComp.getClassName() + ":" + instanceName);
      }

      // 2. 根據(jù)全類名在緩存中查找相應(yīng)的ServiceRecord
      if (comp != null) {
          r = smap.mServicesByInstanceName.get(comp);
      }

      // ServiceRecord為空
      if (r == null) {
          try {
              // 3. 通過PKMS來查詢相應(yīng)的ResolveInfo
              ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                      resolvedType, flags, userId, callingUid);
              ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
              if (sInfo == null) {
                  return null;
              }
              //獲取組件名
              ComponentName className = new ComponentName(
                      sInfo.applicationInfo.packageName, sInfo.name);
              if (userId > 0) {
                  //服務(wù)是否屬于單例模式
                  if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                          sInfo.name, sInfo.flags)
                          && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                      userId = 0;
                      smap = getServiceMapLocked(0);
                  }
                  sInfo = new ServiceInfo(sInfo);
                  sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
              }
              r = smap.mServicesByInstanceName.get(name);
              if (r == null && createIfNeeded) {
                  final Intent.FilterComparison filter
                          = new Intent.FilterComparison(service.cloneFilter());
                  //創(chuàng)建Restarter對(duì)象
                  final ServiceRestarter res = new ServiceRestarter();
                  final BatteryStatsImpl.Uid.Pkg.Serv ss;
                  final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                  synchronized (stats) {
                      ss = stats.getServiceStatsLocked(
                              sInfo.applicationInfo.uid, name.getPackageName(),
                              name.getClassName());
                  }
                  
                  // 3.2 創(chuàng)建ServiceRecord對(duì)象
                  r = new ServiceRecord(mAm, ss, className, name, definingPackageName,
                          definingUid, filter, sInfo, callingFromFg, res);
                  r.mRecentCallingPackage = callingPackage;
                  res.setService(r);
                  smap.mServicesByInstanceName.put(name, r);
                  smap.mServicesByIntent.put(filter, r);

                  //確保該組件不再位于pending隊(duì)列
                  for (int i = mPendingServices.size() - 1; i >= 0; i--) {
                      final ServiceRecord pr = mPendingServices.get(i);
                      if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
                              && pr.instanceName.equals(name)) {
                          mPendingServices.remove(i);
                      }
                  }
              }
          } catch (RemoteException ex) {
              //運(yùn)行在同一個(gè)進(jìn)程宾濒,不會(huì)發(fā)生RemoteException
          }
      }
      if (r != null) {
          //各種權(quán)限檢查,不滿足條件則返回為null的service
          //...
          //4. 創(chuàng)建Service查詢結(jié)果對(duì)象
          return new ServiceLookupResult(r, null);
      }
      return null;
  }


retrieveServiceLocked方法主要做了四件事:

  1. 根據(jù)Intent數(shù)據(jù)獲取Service的全類名
  2. 根據(jù)全類名在緩存查找是否有ServiceRecord
  3. 如果緩存中沒有ServiceRecord屏箍,則根據(jù)PKMS查找對(duì)應(yīng)的ResolveInfo,并創(chuàng)建一個(gè)ServiceRecord對(duì)象
  4. 最后如果ServiceRecord對(duì)象不為空绘梦,則根據(jù)ServiceRecord創(chuàng)建一個(gè)ServiceLookupResult對(duì)象實(shí)例并返回。

2. bringUpServiceLocked啟動(dòng)Service

  // 啟動(dòng)Service的方法
  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                                      boolean whileRestarting, boolean permissionsReviewRequired)
          throws TransactionTooLargeException {
      if (r.app != null && r.app.thread != null) {
          // 如果service已經(jīng)啟動(dòng)赴魁,那么多次啟動(dòng)Service時(shí)會(huì)多次調(diào)用service.onStartCommand()方法
          sendServiceArgsLocked(r, execInFg, false);
          return null;
      }

      if (!whileRestarting && mRestartingServices.contains(r)) {
          return null; //等待延遲重啟的過程卸奉,則直接返回
      }

      // 啟動(dòng)service前,把service從重啟服務(wù)隊(duì)列中移除
      if (mRestartingServices.remove(r)) {
          clearRestartingIfNeededLocked(r);
      }

      // service正在啟動(dòng)颖御,將delayed設(shè)置為false
      if (r.delayed) {
          getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
          r.delayed = false;
      }

      //確保擁有該服務(wù)的user已經(jīng)啟動(dòng)择卦,否則停止;
      if (!mAm.mUserController.hasStartedUserState(r.userId)) {
          String msg = "Unable to launch app "
                  + r.appInfo.packageName + "/"
                  + r.appInfo.uid + " for service "
                  + r.intent.getIntent() + ": user " + r.userId + " is stopped";
          bringDownServiceLocked(r);
          return msg;
      }

      //服務(wù)正在啟動(dòng),設(shè)置package停止?fàn)顟B(tài)為false
      try {
          AppGlobals.getPackageManager().setPackageStoppedState(
                  r.packageName, false, r.userId);
      } catch (RemoteException e) {
      } catch (IllegalArgumentException e) {
          Slog.w(TAG, "Failed trying to unstop package "
                  + r.packageName + ": " + e);
      }

      final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
      final String procName = r.processName;
      ProcessRecord app;
      if (!isolated) {
          // 1. 根據(jù)進(jìn)程名和uid秉继,查詢ProcessRecord
          app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
          if (app != null && app.thread != null) {
              // 目標(biāo)進(jìn)程已存在
              try {
                  app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                  // 2. 調(diào)用realStartServiceLocked方法啟動(dòng)Service
                  realStartServiceLocked(r, app, execInFg);
                  return null;
              } catch (TransactionTooLargeException e) {
                  throw e;
              } catch (RemoteException e) {
                  Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
              }

          }
      } else {
          app = r.isolatedProc;
      }

      // 對(duì)于進(jìn)程沒有啟動(dòng)的情況
      if (app == null && !permissionsReviewRequired) {
          // 3. 通過AMS啟動(dòng)service所要運(yùn)行的進(jìn)程
          if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                  hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
              String msg = "Unable to launch app "
                      + r.appInfo.packageName + "/"
                      + r.appInfo.uid + " for service "
                      + r.intent.getIntent() + ": process is bad";
              // 進(jìn)程啟動(dòng)失敗
              bringDownServiceLocked(r);
              return msg;
          }
          if (isolated) {
              r.isolatedProc = app;
          }
      }

      if (!mPendingServices.contains(r)) {
          mPendingServices.add(r);
      }

      if (r.delayedStop) {
          r.delayedStop = false;
          if (r.startRequested) {
              //停止服務(wù)
              stopServiceLocked(r);
          }
      }

      return null;
  }


bringUpServiceLocked方法主要做了兩件事:

  1. 檢查進(jìn)程是否啟動(dòng)祈噪,如果啟動(dòng)了,則調(diào)用realStartServiceLocked方法開始真正啟動(dòng)Service尚辑。
  2. 如果進(jìn)程沒啟動(dòng)辑鲤,則先創(chuàng)建進(jìn)程,進(jìn)程創(chuàng)建完成后才調(diào)用realStartServiceLocked方法開始真正啟動(dòng)Service杠茬。

繼續(xù)查看realStartServiceLocked方法

// 真是啟動(dòng)Service方法
  private final void realStartServiceLocked(ServiceRecord r,
                                            ProcessRecord app, boolean execInFg) throws RemoteException {
      if (app.thread == null) {
          throw new RemoteException();
      }
      //...
      // 1. 發(fā)送delay消息月褥,若onCreate方法超時(shí)執(zhí)行未取消,則引發(fā)ANR
      bumpServiceExecutingLocked(r, execInFg, "create");
      try {
          //...
          // 2. 通過ApplicationThread調(diào)用Service.onCreate方法
          app.thread.scheduleCreateService(r, r.serviceInfo,
                  mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                  app.getReportedProcState());
          r.postNotification();
          created = true;
      } catch (DeadObjectException e) {
          mAm.appDiedLocked(app, "Died when creating service");
          throw e;
      } finally {
          //...
      }

      // 3. 檢查是否需要執(zhí)行onBind()方法
      requestServiceBindingsLocked(r, execInFg);
      //...
      //4. 服務(wù) 進(jìn)入onStartCommand()
      sendServiceArgsLocked(r, execInFg, true);
      //...
  }


realStartServiceLocked方法主要做了四件事:

  1. 調(diào)用bumpServiceExecutingLocked()方法發(fā)送一個(gè)延遲消息瓢喉,為Service的onCreate執(zhí)行時(shí)間裝彈宁赤。
  2. 調(diào)用app.thread.scheduleCreateService()方法,通過Service所在進(jìn)程的ApplicationThread類栓票,去創(chuàng)建Service并調(diào)用Service的onCreate()方法决左。
  3. 調(diào)用requestServiceBindingsLocked()方法,檢查是否需要執(zhí)行Service的onBind()方法走贪。
  4. 調(diào)用sendServiceArgsLocked()方法佛猛,檢查是否需要執(zhí)行Service的onStartCommand()方法
bumpServiceExecutingLocked延遲發(fā)送ANR消息:
  static final int SERVICE_TIMEOUT = 20 * 1000;

  static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

  // 發(fā)送一個(gè)延遲消息,消息沒被取消坠狡,則執(zhí)行ANR继找。fg參數(shù)為是否為前臺(tái)Service
  private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
      long now = SystemClock.uptimeMillis();
      if (r.executeNesting == 0) {
          //...
          if (r.app != null) {
              r.app.executingServices.add(r);
              r.app.execServicesFg |= fg;
              if (timeoutNeeded && r.app.executingServices.size() == 1) {
                  scheduleServiceTimeoutLocked(r.app);
              }
          }
      } else if (r.app != null && fg && !r.app.execServicesFg) {
          r.app.execServicesFg = true;
          if (timeoutNeeded) {
              // 發(fā)送Handler
              scheduleServiceTimeoutLocked(r.app);
          }
      }
      r.executeFg |= fg;
      r.executeNesting++;
      r.executingStart = now;
  }

  void scheduleServiceTimeoutLocked(ProcessRecord proc) {
      if (proc.executingServices.size() == 0 || proc.thread == null) {
          return;
      }
      Message msg = mAm.mHandler.obtainMessage(
              ActivityManagerService.SERVICE_TIMEOUT_MSG);
      msg.obj = proc;
      //當(dāng)超時(shí)后仍沒有remove該SERVICE_TIMEOUT_MSG消息,則執(zhí)行service Timeout流程
      // 在前臺(tái)延遲20s,否則延遲200s
      mAm.mHandler.sendMessageDelayed(msg,
              proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
  }


如果是前臺(tái)Service則延遲20s發(fā)送ANR消息逃沿,如果是后臺(tái)Service則延遲200s發(fā)送ANR消息婴渡。

requestServiceBindingsLocked檢查是否需要執(zhí)行onBind()方法:
  private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
          throws TransactionTooLargeException {
      // 通過bindService的啟動(dòng)方式,bindings一定不為空
      for (int i = r.bindings.size() - 1; i >= 0; i--) {
          IntentBindRecord ibr = r.bindings.valueAt(i);
          if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
              break;
          }
      }
  }

  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 {
              // 1. ANR裝炸彈
              bumpServiceExecutingLocked(r, execInFg, "bind");
              r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
              // 2. 通過ApplicationThread調(diào)用Service的onBind()方法
              r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                      r.app.getReportedProcState());
              if (!rebind) {
                  i.requested = true;
              }
              i.hasBound = true;
              i.doRebind = false;
          }
          //...
      }
      return true;
  }

如果ServiceRecord.bindings大小>0凯亮,則調(diào)用requestServiceBindingLocked方法边臼,先通過bumpServiceExecutingLocked方法給onBind()方法發(fā)送延遲的ANR消息,然后調(diào)用 r.app.thread.scheduleBindService()方法通過ApplicationThread類調(diào)用Service的onBind()方法触幼。

sendServiceArgsLocked檢查是否需要執(zhí)行onStartCommand方法

  private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                                           boolean oomAdjusted) throws TransactionTooLargeException {
      final int N = r.pendingStarts.size();
      if (N == 0) {
          return;
      }

      ArrayList<ServiceStartArgs> args = new ArrayList<>();

      while (r.pendingStarts.size() > 0) {
          //...
          // 裝彈,延遲發(fā)送一條消息究飞,如果執(zhí)行onStartCommand方法超過
          bumpServiceExecutingLocked(r, execInFg, "start");
          //...
          try {
              // 調(diào)用AT.scheduleServiceArgs,最終調(diào)用onStartCommand
              r.app.thread.scheduleServiceArgs(r, slice);
          }
      }

  }

如果ServiceRecord.pendingStarts大小>0則通過r.app.thread.scheduleServiceArgs調(diào)用Service的onStartCommand方法置谦。

ActivityThread創(chuàng)建并執(zhí)行Service

由于bindService啟動(dòng)的Service并不會(huì)執(zhí)行onStartCommand()方法,所以這里只分析onCreate()亿傅、onBind()方法:

執(zhí)行onCreate()

AMS通過調(diào)用app.thread.scheduleCreateService()方法去調(diào)用Service的onCreate()方法的執(zhí)行媒峡。

private class ApplicationThread extends IApplicationThread.Stub {

      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;
          // 通過Handler發(fā)送消息執(zhí)行
          sendMessage(H.CREATE_SERVICE, s);
      }

  }

  public void handleMessage(Message msg) {
      switch (msg.what) {
          case CREATE_SERVICE:
              handleCreateService((CreateServiceData) msg.obj);
              break;
      }
  }

  // 創(chuàng)建對(duì)應(yīng)的Service并執(zhí)行onCreate()方法
  private void handleCreateService(CreateServiceData data) {
      //當(dāng)應(yīng)用處于后臺(tái)即將進(jìn)行GC,而此時(shí)被調(diào)回到活動(dòng)狀態(tài)葵擎,則跳過本次gc
      unscheduleGcIdler();
      // 1.1 獲取LoadedApk
      LoadedApk packageInfo = getPackageInfoNoCheck(
              data.info.applicationInfo, data.compatInfo);

      Service service = null;
      try {
          // 1.2 根據(jù)LoadedApk創(chuàng)建ContextImpl
          ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
          // 2. 創(chuàng)建Application對(duì)象
          Application app = packageInfo.makeApplication(false, mInstrumentation);
          // 獲取ClassLoader
          java.lang.ClassLoader cl = packageInfo.getClassLoader();
          // 3. 通過反射創(chuàng)建Service對(duì)象
          service = packageInfo.getAppFactory()
                  .instantiateService(cl, data.info.name, data.intent);
          context.getResources().addLoaders(
                  app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

          context.setOuterContext(service);
          // 4. 調(diào)用service.attach綁定資源文件
          service.attach(context, this, data.info.name, data.token, app,
                  ActivityManager.getService());
          // 5. 調(diào)用 service.onCreate()方法
          service.onCreate();
          mServices.put(data.token, service);
          try {
              // 6. onCreate()執(zhí)行完成谅阿,拆彈過程,最終調(diào)用到ActiveServices.serviceDoneExecutingLocked方法
              ActivityManager.getService().serviceDoneExecuting(
                      data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      } catch (Exception e) {
          //...
      }
  }

通過Handler通信,最終會(huì)調(diào)用ActivityThread. handleCreateService方法签餐,該方法主要6件事:

  1. 通過getPackageInfoNoCheck方法創(chuàng)建一個(gè)LoadedApk實(shí)例對(duì)象寓涨。并通過LoadedApk對(duì)象創(chuàng)建一個(gè)ContextImpl對(duì)象。
  2. 調(diào)用packageInfo.makeApplication創(chuàng)建一個(gè)Application對(duì)象
  3. 通過反射創(chuàng)建對(duì)應(yīng)的Service實(shí)例對(duì)象
  4. 調(diào)用service.attach方法綁定資源文件
  5. 調(diào)用service.onCreate()方法
  6. 調(diào)用ActivityManager.getService().serviceDoneExecuting向AMS取消延遲發(fā)送的ANR消息氯檐。

執(zhí)行onBind()

AMS通過調(diào)用r.app.thread.scheduleBindService()方法去執(zhí)行Service的onBind()方法戒良。

public final class ActivityThread extends ClientTransactionHandler {

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

  }

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


  private void handleBindService(BindServiceData data) {
      Service s = mServices.get(data.token);
      if (s != null) {
          try {

              try {
                  if (!data.rebind) {
                      // 1. 執(zhí)行Service.onBind()回調(diào)方法
                      IBinder binder = s.onBind(data.intent);
                      // 2. 將onBind返回值傳遞回給AMS,
                      // 讓其回調(diào)ServiceConnection方法冠摄,并取消ANR消息
                      ActivityManager.getService().publishService(
                              data.token, data.intent, binder);
                  } else {
                      // 取消ANR消息
                      ActivityManager.getService().serviceDoneExecuting(
                              data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                  }
              }
              //...
          }
      }

  }

通過Handler通信最終調(diào)用到ActivityThread. handleBindService方法糯崎,該方法主要做兩件事:

  1. 調(diào)用Service.onBind()方法
  2. 調(diào)用ActivityManager.getService().publishService通過AMS向發(fā)起方的ServiceConnection進(jìn)行回調(diào),并取消ANR的延遲消息河泳。
  public class ActivityManagerService extends IActivityManager.Stub
          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

      final ActiveServices mServices;

      public void publishService(IBinder token, Intent intent, IBinder service) {
          // Refuse possible leaked file descriptors
          if (intent != null && intent.hasFileDescriptors() == true) {
              throw new IllegalArgumentException("File descriptors passed in Intent");
          }

          synchronized (this) {
              if (!(token instanceof ServiceRecord)) {
                  throw new IllegalArgumentException("Invalid service token");
              }
              mServices.publishServiceLocked((ServiceRecord) token, intent, service);
          }
      }
  }

  public final class ActiveServices {

      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);
                              try {
                                  //1. 調(diào)用發(fā)起方進(jìn)程的LoadedApk.ServiceDispatcher.InnerConnection.connected方法
                                  c.conn.connected(r.name, service, false);
                              } catch (Exception e) {
                              }
                          }
                      }
                  }
                  // 2. 取消ANR消息
                  serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
              }
          } finally {
              Binder.restoreCallingIdentity(origId);
          }
      }
  }


最終調(diào)用到ActiveServices.publishServiceLocked()方法沃呢,向發(fā)起方的進(jìn)行回調(diào),并取消的ANR的延遲消息拆挥。

總結(jié):

bingService會(huì)執(zhí)行的方法有 onCreate薄霜、onBind、onUnBind竿刁、onDestory,其中onBind()方法會(huì)返回一個(gè)Binder對(duì)象黄锤。

  • 發(fā)起方在調(diào)用bingService時(shí)要傳入一個(gè)ServiceConnection實(shí)例對(duì)象,并把這個(gè)對(duì)象封裝在一個(gè)Binder對(duì)象中食拜,便于AMS回調(diào)鸵熟。
  • AMS則通過Intent找到對(duì)應(yīng)的Service記錄,如果Service的進(jìn)程沒啟動(dòng)則先創(chuàng)建進(jìn)程负甸,進(jìn)程啟動(dòng)后依此通過進(jìn)程的ActivityThread創(chuàng)建并調(diào)用Service的onCreate流强、onBind方法,并在調(diào)用方法前發(fā)送一個(gè)延遲的ANR消息
  • Service進(jìn)程的ActivityThread在onCreate()時(shí)先通過反射創(chuàng)建Service呻待,并調(diào)用Service的attach打月、onCreate方法。在onBind()時(shí)先調(diào)用Service的onBinder方法蚕捉,并向AMS發(fā)送i個(gè)給發(fā)起方的ServiceConnection的回調(diào)奏篙。在執(zhí)行完方法后發(fā)送一個(gè)取消執(zhí)行ANR的延遲消息。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迫淹,一起剝皮案震驚了整個(gè)濱河市秘通,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敛熬,老刑警劉巖肺稀,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異应民,居然都是意外死亡话原,警方通過查閱死者的電腦和手機(jī)夕吻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來繁仁,“玉大人涉馅,你說我怎么就攤上這事「谋福” “怎么了控漠?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長悬钳。 經(jīng)常有香客問我盐捷,道長,這世上最難降的妖魔是什么默勾? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任碉渡,我火速辦了婚禮,結(jié)果婚禮上母剥,老公的妹妹穿的比我還像新娘滞诺。我一直安慰自己,他們只是感情好环疼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布习霹。 她就那樣靜靜地躺著,像睡著了一般炫隶。 火紅的嫁衣襯著肌膚如雪淋叶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天伪阶,我揣著相機(jī)與錄音煞檩,去河邊找鬼。 笑死栅贴,一個(gè)胖子當(dāng)著我的面吹牛斟湃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播檐薯,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼凝赛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坛缕?” 一聲冷哼從身側(cè)響起墓猎,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祷膳,沒想到半個(gè)月后陶衅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屡立,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡直晨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年搀军,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勇皇。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罩句,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出敛摘,到底是詐尸還是另有隱情门烂,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布兄淫,位于F島的核電站屯远,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捕虽。R本人自食惡果不足惜慨丐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泄私。 院中可真熱鬧房揭,春花似錦、人聲如沸晌端。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咧纠。三九已至蓬痒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惧盹,已是汗流浹背乳幸。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钧椰,地道東北人粹断。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像嫡霞,于是被迫代替她去往敵國和親瓶埋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容