Android系统在新进程中启动自定义服务过程(startService)的原理分析 (下)-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

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

简介:

       Step 10. ActivityManagerService.attachApplicationLocked

         这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:


  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.                         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.  
  4.     ......  
  5.  
  6.     private final boolean attachApplicationLocked(IApplicationThread thread,  
  7.             int pid) {  
  8.         // Find the application record that is being attached...  either via  
  9.         // the pid if we are running in multiple processes, or just pull the  
  10.         // next app record if we are emulating process with anonymous threads.  
  11.         ProcessRecord app;  
  12.         if (pid != MY_PID && pid >= 0) {  
  13.             synchronized (mPidsSelfLocked) {  
  14.                 app = mPidsSelfLocked.get(pid);  
  15.             }  
  16.         } else if (mStartingProcesses.size() > 0) {  
  17.             app = mStartingProcesses.remove(0);  
  18.             app.setPid(pid);  
  19.         } else {  
  20.             app = null;  
  21.         }  
  22.  
  23.         ......  
  24.  
  25.  
  26.         String processName = app.processName;  
  27.           
  28.         ......  
  29.  
  30.         app.thread = thread;  
  31.  
  32.         ......  
  33.           
  34.         boolean badApp = false;  
  35.  
  36.         ......  
  37.  
  38.         // Find any services that should be running in this process...  
  39.         if (!badApp && mPendingServices.size() > 0) {  
  40.             ServiceRecord sr = null;  
  41.             try {  
  42.                 for (int i=0; i<mPendingServices.size(); i++) {  
  43.                     sr = mPendingServices.get(i);  
  44.                     if (app.info.uid != sr.appInfo.uid  
  45.                         || !processName.equals(sr.processName)) {  
  46.                             continue;  
  47.                     }  
  48.  
  49.                     mPendingServices.remove(i);  
  50.                     i--;  
  51.                     realStartServiceLocked(sr, app);  
  52.                     didSomething = true;  
  53.                 }  
  54.             } catch (Exception e) {  
  55.  
  56.                 ......  
  57.  
  58.             }  
  59.         }  
  60.  
  61.         ......  
  62.  
  63.         return true;  
  64.     }  
  65.  
  66.     ......  
  67.  

        回忆一下在上面的Step 4中,以新进程的pid值作为key值保存了一个ProcessRecord在mPidsSelfLocked列表中,这里先把它取出来,存放在本地变量app中,并且将app.processName保存在本地变量processName中。

 

        再回忆一下在上面的Step 3中,在成员变量mPendingServices中,保存了一个ServiceRecord,这里通过进程uid和进程名称将它找出来,然后通过realStartServiceLocked函数来进一步处理。

        Step 11. ActivityManagerService.realStartServiceLocked
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:


  1. class ActivityManagerProxy implements IActivityManager  
  2. {  
  3.     ......  
  4.  
  5.     private final void realStartServiceLocked(ServiceRecord r,  
  6.             ProcessRecord app) throws RemoteException {  
  7.           
  8.         ......  
  9.  
  10.         r.app = app;  
  11.           
  12.         ......  
  13.  
  14.         try {  
  15.  
  16.             ......  
  17.           
  18.             app.thread.scheduleCreateService(r, r.serviceInfo);  
  19.               
  20.             ......  
  21.  
  22.         } finally {  
  23.  
  24.             ......  
  25.  
  26.         }  
  27.  
  28.         ......  
  29.  
  30.     }  
  31.  
  32.     ......  
  33.  

        这里的app.thread是一个ApplicationThread对象的远程接口,它是在上面的Step 6创建ActivityThread对象时作为ActivityThread对象的成员变量同时创建的,然后在Step 9中传过来的。然后调用这个远程接口的scheduleCreateService函数回到原来的ActivityThread对象中执行启动服务的操作。        

        Step 12. ApplicationThreadProxy.scheduleCreateService        

        这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:


  1. class ApplicationThreadProxy implements IApplicationThread {  
  2.       
  3.     ......  
  4.  
  5.     public final void scheduleCreateService(IBinder token, ServiceInfo info)  
  6.                 throws RemoteException {  
  7.         Parcel data = Parcel.obtain();  
  8.         data.writeInterfaceToken(IApplicationThread.descriptor);  
  9.         data.writeStrongBinder(token);  
  10.         info.writeToParcel(data, 0);  
  11.         mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,  
  12.             IBinder.FLAG_ONEWAY);  
  13.         data.recycle();  
  14.     }  
  15.  
  16.     ......  
  17.  

        这里通过Binder驱动程序回到新进程的ApplicationThread对象中去执行scheduleCreateService函数。

        Step 13. ApplicationThread.scheduleCreateService

        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:


  1. public final class ActivityThread {  
  2.       
  3.     ......  
  4.  
  5.     private final class ApplicationThread extends ApplicationThreadNative {  
  6.  
  7.         ......  
  8.  
  9.         public final void scheduleCreateService(IBinder token,  
  10.         ServiceInfo info) {  
  11.             CreateServiceData s = new CreateServiceData();  
  12.             s.token = token;  
  13.             s.info = info;  
  14.  
  15.             queueOrSendMessage(H.CREATE_SERVICE, s);  
  16.         }  
  17.  
  18.         ......  
  19.  
  20.     }  
  21.  
  22.     ......  
  23.  

        这里调用ActivityThread的queueOrSendMessage将一个CreateServiceData数据放到消息队列中去,并且分开这个消息。注意,这里已经是在上面Step 4创建的新进程中执行了。

 

        Step 14. ActivityThread.queueOrSendMessage

        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:


  1. public final class ActivityThread {  
  2.       
  3.     ......  
  4.  
  5.     private final void queueOrSendMessage(int what, Object obj) {  
  6.         queueOrSendMessage(what, obj, 0, 0);  
  7.     }  
  8.  
  9.     private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {  
  10.         synchronized (this) {  
  11.             ......  
  12.             Message msg = Message.obtain();  
  13.             msg.what = what;  
  14.             msg.obj = obj;  
  15.             msg.arg1 = arg1;  
  16.             msg.arg2 = arg2;  
  17.             mH.sendMessage(msg);  
  18.         }  
  19.     }  
  20.  
  21.     ......  
  22.  

        这里调用成员变量mH的sendMessage函数进行消息分发。这里的mH的类型为H,它继承于Handler类。

        Step 15. H.sendMessage

        这个函数继承于Handle类的sendMessage函数中,定义在frameworks/base/core/java/android/os/Handler.java文件中。这个函数我们就不看了,有兴趣的读者可以自己研究一下。消息分发以后,就进入到H.handleMessage函数进行处理了。

        Step 16. H.handleMessage

        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:


  1. public final class ActivityThread {  
  2.       
  3.     ......  
  4.  
  5.     private final class H extends Handler {  
  6.           
  7.         ......  
  8.  
  9.         public void handleMessage(Message msg) {  
  10.  
  11.             ......  
  12.  
  13.             switch (msg.what) {  
  14.  
  15.                 ......  
  16.  
  17.                 case CREATE_SERVICE:  
  18.                     handleCreateService((CreateServiceData)msg.obj);  
  19.                     break;  
  20.  
  21.                 ......  
  22.             }  
  23.  
  24.             ......  
  25.  
  26.         }  
  27.  
  28.         ......  
  29.  
  30.     }  
  31.  
  32.     ......  
  33.  

        这里要处理的消息是CREATE_SERVICE,它调用ActivityThread类的handleCreateService成员函数进一步处理。

 

        Step 17. ActivityThread.handleCreateService

        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:


  1. public final class ActivityThread {  
  2.       
  3.     ......  
  4.  
  5.     private final void handleCreateService(CreateServiceData data) {  
  6.         // If we are getting ready to gc after going to the background, well  
  7.         // we are back active so skip it.  
  8.         unscheduleGcIdler();  
  9.  
  10.         LoadedApk packageInfo = getPackageInfoNoCheck(  
  11.             data.info.applicationInfo);  
  12.         Service service = null;  
  13.         try {  
  14.             java.lang.ClassLoader cl = packageInfo.getClassLoader();  
  15.             service = (Service) cl.loadClass(data.info.name).newInstance();  
  16.         } catch (Exception e) {  
  17.             if (!mInstrumentation.onException(service, e)) {  
  18.                 throw new RuntimeException(  
  19.                     "Unable to instantiate service " + data.info.name  
  20.                     + ": " + e.toString(), e);  
  21.             }  
  22.         }  
  23.  
  24.         try {  
  25.             if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);  
  26.  
  27.             ContextImpl context = new ContextImpl();  
  28.             context.init(packageInfo, nullthis);  
  29.  
  30.             Application app = packageInfo.makeApplication(false, mInstrumentation);  
  31.             context.setOuterContext(service);  
  32.             service.attach(context, this, data.info.name, data.token, app,  
  33.                 ActivityManagerNative.getDefault());  
  34.             service.onCreate();  
  35.             mServices.put(data.token, service);  
  36.             try {  
  37.                 ActivityManagerNative.getDefault().serviceDoneExecuting(  
  38.                     data.token, 0, 0, 0);  
  39.             } catch (RemoteException e) {  
  40.                 // nothing to do.  
  41.             }  
  42.               
  43.         } catch (Exception e) {  
  44.             if (!mInstrumentation.onException(service, e)) {  
  45.                 throw new RuntimeException(  
  46.                     "Unable to create service " + data.info.name  
  47.                     + ": " + e.toString(), e);  
  48.             }  
  49.         }  
  50.     }  
  51.  
  52.     ......  
  53.  

        这里的data.info.name就是自定义的服务类shy.luo.ashmem.Server了。

 

        Step 18. ClassLoader.loadClass

        这一步实现在上面的ActivityThread.handleCreateService函数中:


  1. java.lang.ClassLoader cl = packageInfo.getClassLoader();  
  2. service = (Service) cl.loadClass(data.info.name).newInstance(); 

        Step 19. Obtain Service

 

        这一步也是实现在上面的ActivityThread.handleCreateService函数中。上面通过ClassLoader.loadClass来导入自定义的服务类shy.luo.ashmem.Server并且创建它的一个实例后,就通过强制类型转换得到一个Service类实例。前面我们说过,自己的服务类必须要继承于Service类,这里就体现出来了为什么要这样做了。

        Step 20. Service.onCreate

        这一步继续实现在上面的ActivityThread.handleCreateService函数中:


  1. service.onCreate(); 

        因为这里的service实际上是一个shy.luo.ashmem.Server类实例,因此,这里就是执行shy.luo.ashmem.Server类的onCreate函数了:


  1. public class Server extends Service {  
  2.       
  3.     ......  
  4.  
  5.     @Override  
  6.     public void onCreate() {  
  7.         ......  
  8.  
  9.     }  
  10.  
  11.     ......  

        至此,这个自定义的服务就启动起来了。

 

        这样,Android系统在新进程中启动服务的过程就分析完成了,虽然很复杂,但是条理很清晰。它通过三次Binder进程间通信完成了服务的启动过程,分别是:
 

        一. Step 1至Step 7,从主进程调用到ActivityManagerService进程中,完成新进程的创建;

        二. Step 8至Step 11,从新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息;

        三. Step 12至Step 20,从ActivityManagerService进程又回到新进程中,最终将服务启动起来。

        学习完Android系统在新进程中启动服务的过程后,希望读者对Android系统的Service有一个深刻的理解。在编写Android应用程序的时候,尽量把一些计算型的逻辑以Service在形式来实现,使得这些耗时的计算能在一个独立的进程中进行,这样就能保持主进程流畅地响应界面事件,提高用户体验。





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965589,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章
最新文章
相关文章