原文:

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

Android应用程序绑定服务(bindService)的过程源代码分析



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

Step 1. ActivityManagerService.startService

Step 2. ActivityManagerService.startServiceLocked;函数首先通过retrieveServiceLocked来解析service这个Intent,就是解析前面我们在AndroidManifest.xml定义的Service标签的intent-filter相关内容,然后将解析结果放在res.record中,然后继续调用bringUpServiceLocked进一步处理。

Step 3. ActivityManagerService.bringUpServiceLocked;appName便是我们前面在AndroidManifest.xml文件定义service标签时指定的android:process属性值了,即“.Server”。接着调用startProcessLocked函数来创建一个新的进程,以便加载自定义的Service类。最后将这个ServiceRecord保存在成员变量mPendingServices列表中,后面会用到。
Step 4. ActivityManagerService.startProcessLocked 这里调用Process.start函数创建了一个新的进程,指定新的进程执行android.app.ActivityThread类。最后将表示这个新进程的ProcessRecord保存在mPidSelfLocked列表中,后面会用到

Step 5. Process.start;这个函数定义在frameworks/base/core/java/android/os/Process.java文件中,这个函数我们就不看了,有兴趣的读者可以自己研究一下。在这个场景中,它就是新建一个进程,然后导入android.app.ActivityThread这个类,然后执行它的main函数。

Step 6. ActivityThread.main;这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:  注意,执行到这里的时候,已经是在上一步创建的新进程里面了,即这里的进程是用来启动服务的,原来的主进程已经完成了它的命令,返回了。 前面我们提到,在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函数进一步处理。

Step 7. ActivityThread.attach;从Step 6中,这里传进来的参数system为false。成员变量mAppThread是一个ApplicationThread实例,我们在前面已经描述过这个实例的作用,它是用来辅助ActivityThread来执行一些操作的,是一个binder对象。调用ActivityManagerNative.getDefault函数得到ActivityManagerService的远程接口,即ActivityManagerProxy,接着调用它的attachApplication函数。

  Step 8. ActivityManagerProxy.attachApplication; 这个函数主要是将新进程里面的IApplicationThread实例通过Binder驱动程序传递给ActivityManagerService

Step 9. ActivityManagerService.attachApplication;这里通过调用attachApplicationLocked函数进一步处理。

Step 10. ActivityManagerService.attachApplicationLocked;回忆一下在上面的Step 4中,以新进程的pid值作为key值保存了一个ProcessRecord在mPidsSelfLocked列表中,这里先把它取出来,存放在本地变量app中,并且将app.processName保存在本地变量processName中。再回忆一下在上面的Step 3中,在成员变量mPendingServices中,保存了一个ServiceRecord,这里通过进程uid和进程名称将它找出来,然后通过realStartServiceLocked函数来进一步处理。

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

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

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

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

 Step 15. H.sendMessage;消息分发以后,就进入到H.handleMessage函数进行处理了

Step 16. H.handleMessage;处理的消息是CREATE_SERVICE,它调用ActivityThread类的handleCreateService成员函数进一步处理。

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

Step 18. ClassLoader.loadClass ;这一步继续实现在上面的ActivityThread.handleCreateService函数中,加载该类

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

Step 20. Service.onCreate;这一步继续实现在上面的ActivityThread.handleCreateService函数中, 因为这里的service实际上是一个shy.luo.ashmem.Server类实例,因此,这里就是执行shy.luo.ashmem.Server类的onCreate函数了


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

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

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

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

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


二、Android应用程序绑定服务(bindService)的过程源代码分析


Step 1. ContextWrapper.bindService; 这里的mBase是一个ContextImpl实例变量,于是就调用ContextImpl的bindService函数来进一步处理。

Step 2. ContextImpl.bindService;

class ContextImpl extends Context {......@Overridepublic boolean bindService(Intent service, ServiceConnection conn,int flags) {IServiceConnection sd;if (mPackageInfo != null) {sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);} else {......}try {int res = ActivityManagerNative.getDefault().bindService(mMainThread.getApplicationThread(), getActivityToken(),service, service.resolveTypeIfNeeded(getContentResolver()),sd, flags);......return res != 0;} catch (RemoteException e) {return false;}}......}
 这里的mMainThread是一个ActivityThread实例,通过它的getHandler函数可以获得一个Handler对象,有了这个Handler对象后,就可以把消息分发到ActivityThread所在的线程消息队列中去了,后面我们将会看到这个用法,现在我们暂时不关注,只要知道这里从ActivityThread处获得了一个Handler并且保存在下面要介绍的ServiceDispatcher中去就可以了

我们先看一下ActivityThread.getHandler的实现,然后再回到这里的bindService函数来。

        Step 3. ActivityThread.getHandler

回到Step 2中的ContextImpl.bindService函数中,获得了这个Handler对象后,就调用mPackageInfo.getServiceDispatcher函数来获得一个IServiceConnection接口,这里的mPackageInfo的类型是LoadedApk,我们来看看它的getServiceDispatcher函数的实现,然后再回到ContextImpl.bindService函数来

 Step 4. LoadedApk.getServiceDispatcher;在getServiceDispatcher函数中,传进来的参数context是一个MainActivity实例,先以它为Key值在mServices中查看一下,是不是已经存在相应的ServiceDispatcher实例,如果有了,就不用创建了,直接取出来。在我们这个情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例的过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在了ServiceDispatcher实例的内部,并且创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。 函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。

Step 5. ActivityManagerService.bindService;这个函数通过Binder驱动程序就进入到ActivityManagerService的bindService函数去了。

Step 6. ActivityManagerService.bindService;函数首先根据传进来的参数token是MainActivity在ActivityManagerService里面的一个令牌,通过这个令牌就可以将这个代表MainActivity的ActivityRecord取回来了,接着通过retrieveServiceLocked函数,得到一个ServiceRecord,这个ServiceReocrd描述的是一个Service对象,这里就是CounterService了,这是根据传进来的参数service的内容获得的。回忆一下在MainActivity.onCreate函数绑定服务的语句:

Intent bindIntent = new Intent(MainActivity.this, CounterService.class);bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
这里的参数service,就是上面的bindIntent了,它里面设置了CounterService类的信息(CounterService.class),因此,这里可以通过它来把CounterService的信息取出来,并且保存在ServiceRecord对象s中,接下来,就是把传进来的参数connection封装成一个ConnectionRecord对象。注意,这里的参数connection是一个Binder对象,它的类型是LoadedApk.ServiceDispatcher.InnerConnection,是在Step 4中创建的,后续ActivityManagerService就是要通过它来告诉MainActivity,CounterService已经启动起来了,因此,这里要把这个ConnectionRecord变量c保存下来,它保在在好几个地方,都是为了后面要用时方便地取回来的,这里就不仔细去研究了,只要知道ActivityManagerService要使用它时就可以方便地把它取出来就可以了,具体后面我们再分析。这里会调用bringUpServiceLocked函数进一步处理。

Step 7. ActivityManagerService.bringUpServiceLocked;我们没有在程序的AndroidManifest.xml配置文件中设置CounterService的process属性值,因此,它默认就为application标签的process属性值,而application标签的process属性值也没有设置,于是,它们就默认为应用程序的包名了,即这里的appName的值为"shy.luo.broadcast"。接下来根据appName和应用程序的uid值获得一个ProcessRecord记录,由于之前在启动MainActivity的时候,已经根据这个appName和uid值创建了一个ProcessReocrd对象(具体可以参考Android应用程序启动过程源代码分析一文),因此,这里取回来的app和app.thread均不为null,于是,就执行realStartServiceLocked函数来执行下一步操作了。如果这里得到的ProcessRecord变量app为null,又是什么情况呢?在这种情况下,就会执行后面的startProcessLocked函数来创建一个新的进程,然后在这个新的进程中启动这个Service了。

 Step 8. ActivityManagerService.realStartServiceLocked;这个函数执行了两个操作,一个是操作是调用app.thread.scheduleCreateService函数来在应用程序进程内部启动CounterService,这个操作会导致CounterService的onCreate函数被调用;另一个操作是调用requestServiceBindingsLocked函数来向CounterService要一个Binder对象,这个操作会导致CounterService的onBind函数被调用

public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app) throws RemoteException {......r.app = app;......app.services.add(r);......try {......app.thread.scheduleCreateService(r, r.serviceInfo);......} finally {......}requestServiceBindingsLocked(r);......}......}
这里,我们先沿着app.thread.scheduleCreateService这个路径分析下去,然后再回过头来分析requestServiceBindingsLocked的调用过程。这里的app.thread是一个Binder对象的远程接口,类型为ApplicationThreadProxy。每一个Android应用程序进程里面都有一个ActivtyThread对象和一个ApplicationThread对象,其中是ApplicationThread对象是ActivityThread对象的一个成员变量,是ActivityThread与ActivityManagerService之间用来执行进程间通信的

Step 9. ApplicationThreadProxy.scheduleCreateService;这里通过Binder驱动程序就进入到ApplicationThread的scheduleCreateService函数去了。

Step 10. ApplicationThread.scheduleCreateService;这里它执行的操作就是调用ActivityThread的queueOrSendMessage函数把一个H.CREATE_SERVICE类型的消息放到ActivityThread的消息队列中去。

Step 11. ActivityThread.queueOrSendMessage;这个消息最终是通过mH.sendMessage发送出去的,这里的mH是一个在ActivityThread内部定义的一个类,继承于Hanlder类,用于处理消息的

Step 12. H.sendMessage;由于H类继承于Handler类,因此,这里实际执行的Handler.sendMessage函数,调用了这个函数之后,这个消息就真正地进入到ActivityThread的消息队列去了,最终这个消息由H.handleMessage函数来处理, 这个消息最终由ActivityThread的handleCreateService函数来处理。

Step 13. ActivityThread.handleCreateService;这个函数的工作就是把CounterService类加载到内存中来,然后调用它的onCreate函数。

Step 14. CounterService.onCreate;这样,CounterService就启动起来了。

 至此,应用程序绑定服务过程中的第一步MainActivity.bindService->CounterService.onCreate就完成了。

这一步完成之后,我们还要回到Step  8中去,执行下一个操作,即调用ActivityManagerService.requestServiceBindingsLocked函数,这个调用是用来执行CounterService的onBind函数的。

Step 15. ActivityManagerService.requestServiceBindingsLocked。 这里的参数r就是我们在前面的Step 6中创建的ServiceRecord了,它代表刚才已经启动了的CounterService。函数requestServiceBindingsLocked调用了requestServiceBindingLocked函数来处理绑定服务的操作,而函数requestServiceBindingLocked又调用了app.thread.scheduleBindService函数执行操作,前面我们已经介绍过app.thread,它是一个Binder对象的远程接口,类型是ApplicationThreadProxy。

Step 16. ApplicationThreadProxy.scheduleBindService;Binder驱动程序就进入到ApplicationThread的scheduleBindService函数去了。

Step 17. ApplicationThread.scheduleBindService;这里像上面的Step 11一样,调用ActivityThread.queueOrSendMessage函数来发送消息。

        Step 18. ActivityThread.queueOrSendMessage; 参考上面的Step 11,不过这里的消息类型是H.BIND_SERVICE。

        Step 19. H.sendMessage;参考上面的Step 12,不过这里最终在H.handleMessage函数中,要处理的消息类型是H.BIND_SERVICE:这里调用ActivityThread.handleBindService函数来进一步处理

Step 20. ActivityThread.handleBindService; 在前面的Step 13执行ActivityThread.handleCreateService函数中,已经将这个CounterService实例保存在mServices中,因此,这里首先通过data.token值将它取回来,保存在本地变量s中,接着执行了两个操作,一个操作是调用s.onBind,即CounterService.onBind获得一个Binder对象,另一个操作就是把这个Binder对象传递给ActivityManagerService。

我们先看CounterService.onBind操作,然后再回到ActivityThread.handleBindService函数中来。

 Step 21. CounterService.onBind;(CounterService,自定义的Service类,onBind是它的函数),onBind函数返回一个是CounterBinder类型的Binder对象。

至此,应用程序绑定服务过程中的第二步CounterService.onBind就完成了。

回到ActivityThread.handleBindService函数中,获得了这个CounterBinder对象后,就调用ActivityManagerProxy.publishService来通知MainActivity,CounterService已经连接好了。

Step 22. ActivityManagerProxy.publishService;这里通过Binder驱动程序就进入到ActivityManagerService的publishService函数中去了。

 Step 23. ActivityManagerService.publishService;这里传进来的参数token是一个ServiceRecord对象,它是在上面的Step 6中创建的,代表CounterService这个Service。在Step 6中,我们曾经把一个ConnectionRecord放在ServiceRecord.connections列表中,因此,这里可以从r.connections中将这个ConnectionRecord取出来。

每一个ConnectionRecord里面都有一个成员变量conn,它的类型是IServiceConnection,是一个Binder对象的远程接口,这个Binder对象又是什么呢?这就是我们在Step 4中创建的LoadedApk.ServiceDispatcher.InnerConnection对象了。因此,这里执行c.conn.connected函数后就会进入到LoadedApk.ServiceDispatcher.InnerConnection.connected函数中去了。

Step 24. InnerConnection.connected;  这里它将操作转发给ServiceDispatcher.connected函数。

Step 25. ServiceDispatcher.connected;我们在前面Step 4中说到,这里的mActivityThread是一个Handler实例,它是通过ActivityThread.getHandler函数得到的,因此,调用它的post函数后,就会把一个消息放到ActivityThread的消息队列中去了。

 Step 26. H.post;由于H类继承于Handler类,因此,这里实际执行的Handler.post函数,这个函数定义在frameworks/base/core/java/android/os/Handler.java文件,这里我们就不看了,有兴趣的读者可以自己研究一下,调用了这个函数之后,这个消息就真正地进入到ActivityThread的消息队列去了,与sendMessage把消息放在消息队列不一样的地方是,post方式发送的消息不是由这个Handler的handleMessage函数来处理的,而是由post的参数Runnable的run函数来处理的。这里传给post的参数是一个RunConnection类型的参数,它继承了Runnable类,因此,最终会调用RunConnection.run函数来处理这个消息。

Step 27. RunConnection.run;执行ServiceDispatcher.doConnected函数来进一步操作了。

Step 28. ServiceDispatcher.doConnected;这里主要就是执行成员变量mConnection的onServiceConnected函数,这里的mConnection变量的类型的ServiceConnection,它是在前面的Step 4中设置好的,这个ServiceConnection实例是MainActivity类内部创建的,在调用bindService函数时保存在LoadedApk.ServiceDispatcher类中,用它来换取一个IServiceConnection对象,传给ActivityManagerService。

Step 29. ServiceConnection.onServiceConnected; 这里传进来的参数service是一个Binder对象,就是前面在Step 21中从CounterService那里得到的ConterBinder对象,因此,这里可以把它强制转换为CounterBinder引用。然后调用它的getService函数

 Step 30. CounterBinder.getService;这里就把CounterService(自定义的Service)接口返回给MainActivity了。

至此,应用程序绑定服务过程中的第四步CounterService.CounterBinder.getService就完成了。

   1. Step 1 -  Step 14,MainActivity调用bindService函数通知ActivityManagerService,它要启动CounterService这个服务,ActivityManagerService于是在MainActivity所在的进程内部把CounterService启动起来,并且调用它的onCreate函数;

        2. Step 15 - Step 21,ActivityManagerService把CounterService启动起来后,继续调用CounterService的onBind函数,要求CounterService返回一个Binder对象给它;

        3. Step 22 - Step 29,ActivityManagerService从CounterService处得到这个Binder对象后,就把它传给MainActivity,即把这个Binder对象作为参数传递给MainActivity内部定义的ServiceConnection对象的onServiceConnected函数;

        4. Step 30,MainActivity内部定义的ServiceConnection对象的onServiceConnected函数在得到这个Binder对象后,就通过它的getService成同函数获得CounterService接口。




更多相关文章

  1. android 不同进程间的调用 AIDL 实现通讯服务
  2. Android中使用putExtra()传递对象实例
  3. Android平台的跨进程通信——AIDL(上)
  4. Android 查看手机中所有进程
  5. Android Native进程内存泄露检测
  6. Android中使用AlarmManager需注意设置进程属性
  7. Android 抽象回调函数以及接口回调更新UI

随机推荐

  1. AndroidStudio上面最好用的插件
  2. Android(安卓)报错 “程序包R不存在...!”
  3. 【Android】【opencv】实现摄像头拍照和
  4. android 两个视频同时播放音频冲突的解决
  5. android 手势识别代码
  6. Android(安卓)studio 中与本地 html 页面
  7. 使用 SQLiteDatabase 操作 SQLite 数据库
  8. Android数据储存——文件储存
  9. Android菜鸟笔记-调用相机拍照后返回照片
  10. 转:ANDROID音频系统散记之四:4.0音频系统HA