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

回忆一下在上面的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. private final void realStartServiceLocked(ServiceRecord r,
  5. ProcessRecord app) throws RemoteException {
  6. ......
  7. r.app = app;
  8. ......
  9. try {
  10. ......
  11. app.thread.scheduleCreateService(r, r.serviceInfo);
  12. ......
  13. } finally {
  14. ......
  15. }
  16. ......
  17. }
  18. ......
  19. }

这里的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. public final void scheduleCreateService(IBinder token, ServiceInfo info)
  4. throws RemoteException {
  5. Parcel data = Parcel.obtain();
  6. data.writeInterfaceToken(IApplicationThread.descriptor);
  7. data.writeStrongBinder(token);
  8. info.writeToParcel(data, 0);
  9. mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
  10. IBinder.FLAG_ONEWAY);
  11. data.recycle();
  12. }
  13. ......
  14. }

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

Step 13. ApplicationThread.scheduleCreateService

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

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

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

Step 14. ActivityThread.queueOrSendMessage

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

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

这里调用成员变量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. private final class H extends Handler {
  4. ......
  5. public void handleMessage(Message msg) {
  6. ......
  7. switch (msg.what) {
  8. ......
  9. case CREATE_SERVICE:
  10. handleCreateService((CreateServiceData)msg.obj);
  11. break;
  12. ......
  13. }
  14. ......
  15. }
  16. ......
  17. }
  18. ......
  19. }

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

Step 17. ActivityThread.handleCreateService

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

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

这里的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. @Override
  4. public void onCreate() {
  5. ......
  6. }
  7. ......
  8. }

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

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

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

  1. Android系统(117)---Activity启动过程

    Activity启动过程 ###一些基本的概念 ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期 ActivityThread,App的 ...

  2. 根据用户查进程_【磨叽教程】Android进阶教程之在Android系统下各进程之间的优先级关系...

    导读:本文大约2000字,预计阅读时间3分钟.本文纯属技术文,无推广. 正文     首先应用进程的生命周期并不由应用本身直接控制,而是由系统综合多种因素来确定的.Android系统有自己的一套标准, ...

  3. Android 9.0 在init.rc中启动一个服务

    现在有一个blink .bin文件,需要拷贝到/system/bin/目录下面去,然后再init.rc文件中启动该服务 一.init.rc文件中启动服务 1.在init.rc文件中启动服务 代码路径: ...

  4. Android系统刷机后第一次启动很慢的原因

    转自:Android系统刷机后第一次启动很慢的原因 - 走看看 在做Android内核开发的过程中,我们会发现,每次编译完系统源码,烧录到设备/手机中后,第一次启动都会很慢很慢,要好几分钟甚至十几分钟 ...

  5. android 自定义view xml ,Android实现在xml文件中引用自定义View的方法分析

    本文实例讲述了Android实现在xml文件中引用自定义View的方法.分享给大家供大家参考,具体如下: 在xml中引用自定义view 方法一: android:layout_width=" ...

  6. mat opencv 修改roi_OpenCV Android:在新Mat中定义并保存ROI(OpenCV Android: Define and save ROI in new Mat)...

    OpenCV Android:在新Mat中定义并保存ROI(OpenCV Android: Define and save ROI in new Mat) 我正在尝试将我的图像的一部分切割(裁剪)到另 ...

  7. android 系统(154)----OTA制作及升级过程

    OTA制作及升级过程 1.概述 1.1   文档概要 前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理解和防止以后遗忘,所以写这篇文档进行一个总结和梳理,以便日后查阅回顾.文 ...

  8. 在linux中启动mysql,在linux中启动mysql服务的命令

    用reboot命令重启linux服务器之后会导致mysql服务终止,也就是mysql服务没有启动.必须要重启mysql服务,否则启动jboss时会 报有关数据库mysql方面的错误. 命令如下: 第一 ...

  9. linux命令mysql启动,在linux中启动mysql服务的命令

    用reboot命令重启linux服务器之后会导致mysql服务终止,也就是mysql服务没有启动.必须要重启mysql服务,否则启动jboss时会 报有关数据库mysql方面的错误. 命令如下: 第一 ...

最新文章

  1. epoll ET模式服务器和客户端源码例子
  2. 【阿圆实验】Consul HA 高可用方案
  3. HTML的标签描述3
  4. bootstrap table教程--使用入门基本用法
  5. 不说技术~我需要调整自己,最近整整两天状态不是很好
  6. 再看Kafka Lag
  7. 万字长文 | 漫谈libco协程设计及实现
  8. 提取过程_大米多肽提取过程中如何应用膜分离技术呢?
  9. P4831-Scarlet loves WenHuaKe【组合数学】
  10. 【STL】算法 — partial_sort
  11. 惠普c7000服务器装系统,HP BladeSystem c7000 安装配置手册
  12. LC3无重复最长字串
  13. 键盘迷情--Treo650 VS P50 【ZZ】
  14. linux中备份mysql数据库命令_linux备份mysql数据库命令
  15. MATLAB | 画彩色图像的直方图,改对比度,计算均值、方差和信息熵
  16. excel如何全部取消隐藏_全部隐藏!
  17. python+pillow不规则图片合成合并
  18. IntelliJ IDEA 单词表--01
  19. Madgwick AHRS算法笔记
  20. 实用解析dmp文件内容

热门文章

  1. 声音匹配_如何调节人声音色方法如下
  2. c语言swatch的用法返回,Linux swatch系统监控程序命令详解
  3. 红帽启动apache服务器_CentOS6.5环境下搭建Apache httpd服务器
  4. 【Verilog HDL 训练】第 07 天(串并转换)
  5. 减少亚稳态导致错误,提高系统的MTBF
  6. 《压缩感知理论及其研究进展》读书笔记
  7. VUE2.X组件之间通信的2种方式(针对子组件值变化去改变相应父组件的值)
  8. 人工智能行业应用之:为建筑工程提供全新解决方案
  9. 一大波数据来袭 网络桃色陷阱暗藏致命危机
  10. 参观 Google 总部是一种什么体验?