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

目录
相关文章
|
1月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
160 4
|
8天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
61 13
|
24天前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
29 8
|
24天前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
44 4
|
28天前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
34 1
|
1月前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
90 1
|
1月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
5月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
5月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
192 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
4月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。

相关实验场景

更多