当前位置: 首页 > news >正文

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.         Proce***ecord 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值保存了一个Proce***ecord在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.             Proce***ecord 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在形式来实现,使得这些耗时的计算能在一个独立的进程中进行,这样就能保持主进程流畅地响应界面事件,提高用户体验。

相关文章:

  • Codeforces Round #419 (Div. 2) A-E
  • Ubuntu下输入sudo时如何不用输入密码?
  • 认识多渲染目标(Multiple Render Targets)技术
  • 说说參数传递(泛型托付)
  • 【转】Python常用文件操作参考
  • 在spring-boot工程中添加spring mvc拦截器
  • nodejs读写大文件
  • TreeView 控件应用
  • 终端代码重复率检测实践
  • 恋爱男女冷笑话
  • kali之***XP系统3(非法关闭计算机)
  • startActivityForResult的疑问与探索
  • 面向对象03
  • MIME 详解 [转]
  • Linux - 主机的细部权限规划:ACL 的使用
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • chrome扩展demo1-小时钟
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • django开发-定时任务的使用
  • github从入门到放弃(1)
  • Java Agent 学习笔记
  • js ES6 求数组的交集,并集,还有差集
  • Promise面试题2实现异步串行执行
  • react 代码优化(一) ——事件处理
  • 仿天猫超市收藏抛物线动画工具库
  • 来,膜拜下android roadmap,强大的执行力
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 使用 @font-face
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • scrapy中间件源码分析及常用中间件大全
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​Spring Boot 分片上传文件
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • # C++之functional库用法整理
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (4) PIVOT 和 UPIVOT 的使用
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (一)基于IDEA的JAVA基础12
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net 8 发布了,试下微软最近强推的MAUI
  • .NET HttpWebRequest、WebClient、HttpClient
  • .Net IOC框架入门之一 Unity
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET的数据绑定
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [AX]AX2012 AIF(四):文档服务应用实例