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,如需转载请自行联系原作者

目录
相关文章
|
2月前
|
监控 关系型数据库 MySQL
在CentOS系统中,如何统计哪个进程打开了文件描述符?
利用上述方法,你可以有效地监控和统计CentOS系统中的进程打开的文件描述符数量,以帮助排查错误或优化系统配置。通过组合使用各种工具和命令,可以获得对系统状态和行为的深入了解,进而做出相应的调整和
141 5
|
9月前
|
弹性计算 运维 监控
基于进程热点分析与系统资源优化的智能运维实践
智能服务器管理平台提供直观的可视化界面,助力高效操作系统管理。核心功能包括运维监控、智能助手和扩展插件管理,支持系统健康监控、故障诊断等,确保集群稳定运行。首次使用需激活服务并安装管控组件。平台还提供进程热点追踪、性能观测与优化建议,帮助开发人员快速识别和解决性能瓶颈。定期分析和多维度监控可提前预警潜在问题,保障系统长期稳定运行。
387 17
|
11月前
|
监控 搜索推荐 开发工具
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
1206 2
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
|
11月前
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
265 6
|
12月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
530 13
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
456 4
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
455 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
330 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
|
开发工具 Android开发 C++
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
309 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
|
Android开发 C语言
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
543 0
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )

热门文章

最新文章