Android启动Service流程

来源:互联网 发布:603258电魂网络吧 编辑:程序博客网 时间:2024/05/25 23:25

其实启动Service和我们上一篇启动App的流程差不多,通过学习老罗的Android系统在新进程中启动自定义服务过程(startService)的原理分析,补充了一些不太清楚的知识点。这里做一下笔记。
老罗的例子,Service是设置了一个android:process属性,表明要在新建的进程运行Service。例子xml代码:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="shy.luo.ashmem"      android:sharedUserId="android.uid.system"      android:versionCode="1"      android:versionName="1.0">          <application android:icon="@drawable/icon" android:label="@string/app_name">              ......              <service                   android:enabled="true"                   android:name=".Server"                  android:process=".Server" ><!-- 设置了process属性 -->                      <intent-filter>                          <action android:name="shy.luo.ashmem.server"/>                          <category android:name="android.intent.category.DEFAULT"/>                      </intent-filter>              </service>          </application>  </manifest>   

在这篇博文中,讲述了ActivityManagerService是在一个ServerThread类(有种熟悉的感觉,ActivityThread,不过没有联系的,哈哈)中启动的,代码如下:

class ServerThread extends Thread {       ......      @Override      public void run() {          ......          // Critical services...          try {              ......              context = ActivityManagerService.main(factoryTest);              ......              ActivityManagerService.setSystemProcess();              ......          } catch (RuntimeException e) {              Slog.e("System", "Failure starting core service", e);          }          ......      }      ......}  

调用了ActivityManagerService的main和setSystemProcess方法,我们接着看代码:

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {      ......      static ActivityManagerService mSelf;      ......      public static void setSystemProcess() {          try {              ActivityManagerService m = mSelf;              ServiceManager.addService("activity", m);              ......          } catch (PackageManager.NameNotFoundException e) {              ......          }      }      ......      public static final Context main(int factoryTest) {          ......          ActivityManagerService m = thr.mService;          mSelf = m;          ......      }  }  

在setSystemProcess方法里,调用了ServiceManager的addService方法,这样ActivityManagerService作为Service注册到ServiceManager中,Client就可以在ServiceManager中获取到ActivityManagerService的代理对象,并与之通信。这样ActivityManagerService就算是“启动”起来了。
当我们通过startService启动Service时,和启动App一样,其实是调用ActivityManagerService代理对象ActivityManagerProxy 的startService方法:

class ActivityManagerProxy implements IActivityManager {      ......      public ComponentName startService(IApplicationThread caller, Intent service,          String resolvedType) throws RemoteException {          Parcel data = Parcel.obtain();          Parcel reply = Parcel.obtain();          data.writeInterfaceToken(IActivityManager.descriptor);          data.writeStrongBinder(caller != null ? caller.asBinder() : null);          service.writeToParcel(data, 0);          data.writeString(resolvedType);          mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);          reply.readException();          ComponentName res = ComponentName.readFromParcel(reply);          data.recycle();          reply.recycle();          return res;      }      ......  }  

参数service是一个Intent实例,它里面指定了要启动的服务的名称,也就是例子定义的服务名称“shy.luo.ashmem.server”了。

参数caller是一个IApplicationThread实例,它是一个在主进程创建的一个Binder对象。在Android应用程序中,每一个进程都用一个ActivityThread实例来表示,而在ActivityThread类中,有一个成员变量mAppThread,它是一个ApplicationThread实例,实现了IApplicationThread接口,它的作用是用来辅助ActivityThread类来执行一些操作(其实mAppThread是ActivityManagerService持有与App进程通信的Binder代理对象,ActivityManagerService利用调用IApplicationThread代理对象,实现通知ActivityThread执行对应的方法),这个我们在后面会看到它是如何用来启动服务的。

参数resolvedType是一个字符串,它表示service这个Intent的MIME类型,它是在解析Intent时用到的。在这个例子中,我们没有指定这个Intent 的MIME类型,因此,这个参数为null。

ActivityManagerProxy类的startService函数把这三个参数写入到data本地变量去,接着通过mRemote.transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒正在等待Client请求的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中。

接下来就是ActivityManagerService会做一系列检查,然后通过socket方式通知Zygote孵化新的进程,指定新的进程加载ActivityThread类,并执行main方法。代码过程请参考我上一篇博文Android应用App启动流程。这里我们还是着重看一下Service在新的进程启动过程。

先看看ActivityThread的main方法:

public final class ActivityThread {       ......      public static final void main(String[] args) {          ......          Looper.prepareMainLooper();          ......          ActivityThread thread = new ActivityThread();          thread.attach(false);          ......          Looper.loop();          ......          thread.detach();          ......      }  }  

因为这段代码可以带我们了解App的启动和初始化过程,所以很重要。在这里初始化Looper,创建Looper和MessageQueue,然后调用attach方法,把自己的ApplicationThread代理对象通过IPC传给ActivityManagerService,调用Looper.loop方法,让Looper不断的从MessageQueue取出消息,实现消息机制。我们来看看attach方法(上一个博文没有写清楚attach方法,因为不清楚):

public final class ActivityThread {      ......      private final void attach(boolean system) {          ......          if (!system) {              ......              IActivityManager mgr = ActivityManagerNative.getDefault();              try {                  mgr.attachApplication(mAppThread);              } catch (RemoteException ex) {              }          } else {              ......          }          ......      }      ......  }  

主要是调用ActivityManagerService的代理对象ActivityManagerProxy的attachApplication的方法:

class ActivityManagerProxy implements IActivityManager {      ......      public void attachApplication(IApplicationThread app) throws RemoteException {          Parcel data = Parcel.obtain();          Parcel reply = Parcel.obtain();          data.writeInterfaceToken(IActivityManager.descriptor);          data.writeStrongBinder(app.asBinder());          mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);          reply.readException();          data.recycle();          reply.recycle();      }      ......  }  

这下应该清楚知道ActivityThread怎么把ApplicationThread的代理对象传给ActivityManagerService了吧。我们顺便往下看,ActivityManagerService调用attachApplication的方法:

public final class ActivityManagerService extends ActivityManagerNative                              implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {      ......          public final void attachApplication(IApplicationThread thread) {          synchronized (this) {              int callingPid = Binder.getCallingPid();              final long origId = Binder.clearCallingIdentity();              attachApplicationLocked(thread, callingPid);              Binder.restoreCallingIdentity(origId);          }      }      ......  }  

attachApplicationLocked方法代码:

public final class ActivityManagerService extends ActivityManagerNative                          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {        ......      private final boolean attachApplicationLocked(IApplicationThread thread,              int pid) {          // Find the application record that is being attached...  either via          // the pid if we are running in multiple processes, or just pull the          // next app record if we are emulating process with anonymous threads.          ProcessRecord app;          if (pid != MY_PID && pid >= 0) {              synchronized (mPidsSelfLocked) {                  app = mPidsSelfLocked.get(pid);              }          } else if (mStartingProcesses.size() > 0) {              app = mStartingProcesses.remove(0);              app.setPid(pid);          } else {              app = null;          }          ......          String processName = app.processName;          ......          app.thread = thread;          ......          boolean badApp = false;          ......          // Find any services that should be running in this process...          if (!badApp && mPendingServices.size() > 0) {              ServiceRecord sr = null;              try {                  for (int i=0; i<mPendingServices.size(); i++) {                      sr = mPendingServices.get(i);                      if (app.info.uid != sr.appInfo.uid                          || !processName.equals(sr.processName)) {                              continue;                      }                      mPendingServices.remove(i);                      i--;                      realStartServiceLocked(sr, app);                      didSomething = true;                  }              } catch (Exception e) {                  ......              }          }          ......          return true;      }      ......  }  

最终调用realStartServiceLocked方法:

class ActivityManagerProxy implements IActivityManager {      ......      private final void realStartServiceLocked(ServiceRecord r,              ProcessRecord app) throws RemoteException {          ......          r.app = app;          ......          try {              ......              app.thread.scheduleCreateService(r, r.serviceInfo);              ......          } finally {              ......          }          ......      }      ......  }  

这里的app.thread是一个ApplicationThread的代理对象,通过调用这个代理对象scheduleCreateService方法,通知ActivityThread启动Service,回到App进程。

class ApplicationThreadProxy implements IApplicationThread {      ......      public final void scheduleCreateService(IBinder token, ServiceInfo info)                  throws RemoteException {          Parcel data = Parcel.obtain();          data.writeInterfaceToken(IApplicationThread.descriptor);          data.writeStrongBinder(token);          info.writeToParcel(data, 0);          mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,              IBinder.FLAG_ONEWAY);          data.recycle();      }      ......  }  
public final class ActivityThread {      ......      private final class ApplicationThread extends ApplicationThreadNative {          ......          public final void scheduleCreateService(IBinder token,          ServiceInfo info) {              CreateServiceData s = new CreateServiceData();              s.token = token;              s.info = info;              queueOrSendMessage(H.CREATE_SERVICE, s);          }          ......      }      ......  }  

又见到熟悉的身形了,ApplicationThread作为ActivityThread内部类,直接代用queueOrSendMessage方法,分发消息到ActivityThread的MessageQueue,通知ActivityThread执行对应方法。所以整个Handler的消息机制,在Android中起了大多的作用。整个App运行,都是通过这个消息机制得以和谐运行,表示不禁感叹。上次都没看怎么ApplicationThread怎么分发消息,代码如下:

public final class ActivityThread {      ......      private final void queueOrSendMessage(int what, Object obj) {          queueOrSendMessage(what, obj, 0, 0);      }      private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {          synchronized (this) {              ......              Message msg = Message.obtain();              msg.what = what;              msg.obj = obj;              msg.arg1 = arg1;              msg.arg2 = arg2;              mH.sendMessage(msg);          }      }      ......  }  

很普通代码,通过Handler分发消息。看一下ActivityThread的Handler怎么处理启动Service的代码:

public final class ActivityThread {       ......      private final class H extends Handler {          ......          public void handleMessage(Message msg) {              ......              switch (msg.what) {                  ......                  case CREATE_SERVICE:                      handleCreateService((CreateServiceData)msg.obj);                      break;                  ......              }              ......          }          ......      }      ......  }  

调用了handleCreateService方法:

public final class ActivityThread {      ......      private final void handleCreateService(CreateServiceData data) {          // If we are getting ready to gc after going to the background, well          // we are back active so skip it.          unscheduleGcIdler();          LoadedApk packageInfo = getPackageInfoNoCheck(              data.info.applicationInfo);          Service service = null;          try {              java.lang.ClassLoader cl = packageInfo.getClassLoader();              service = (Service) cl.loadClass(data.info.name).newInstance();          } catch (Exception e) {              if (!mInstrumentation.onException(service, e)) {                  throw new RuntimeException(                      "Unable to instantiate service " + data.info.name                      + ": " + e.toString(), e);              }          }          try {              if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);              ContextImpl context = new ContextImpl();              context.init(packageInfo, null, this);              Application app = packageInfo.makeApplication(false, mInstrumentation);              context.setOuterContext(service);              service.attach(context, this, data.info.name, data.token, app,                  ActivityManagerNative.getDefault());              service.onCreate();              mServices.put(data.token, service);              try {                  ActivityManagerNative.getDefault().serviceDoneExecuting(                      data.token, 0, 0, 0);              } catch (RemoteException e) {                  // nothing to do.              }          } catch (Exception e) {              if (!mInstrumentation.onException(service, e)) {                  throw new RuntimeException(                      "Unable to create service " + data.info.name                      + ": " + e.toString(), e);              }          }      }      ......  }  

这段代码主要是加载要启动的Service类,并执行service.onCreate()方法。至此,启动Service代码分析完毕。跟着老罗的代码解析,的确学习了不少。

参考资料

Android系统在新进程中启动自定义服务过程(startService)的原理分析