深入AndroidFramework源码内部剖析Service的启动过程

你在Activity中调用startService(Intent),轻松启动了一个Service,但是你不知道,为了完成这么一个简单的功能,Android系统在背后为我们做了多少事情,本文将为你揭晓……

须知

要理解本文所讲内容,必须对binder机制非常非常清楚,因为下面的内容就像在走盘山公路,弯弯绕绕不少,没有binder这个指南针,你很快就会晕头转向。milter之前有写过一篇binder机制的文章,你可以用来热身,请戳这里

情景

我们在一个应用的Activity中通过startService(Intent)启动的Service是另一个应用中的名为RemoteServiceService。That’s all。

总纲

要理解startService(Intent)背后发生了什么,只需要看懂下面两张图即可(现在看不懂不要紧,看完本文后还看不懂,那就…嘎嘎)。
图1:(强烈呼吁简书支持markdown书写时序图,害的我还得截图)

《深入AndroidFramework源码内部剖析Service的启动过程》 RemoteService生成序列图

图2:

《深入AndroidFramework源码内部剖析Service的启动过程》 Binder通信图

开扒

下面,要开车了,大家坐好,系好安全带,路线是图1中的五个步骤,图2是用来辅助理解图1的。

1、深入Activity中的startService()

在该方法内部,关键动作有两个:

  • 获得一个ActivityManagerProxy对象
  • 调用该对象的startService( IApplicationThread caller, Intent service, String resolvedType );

说明:要理解这两步最主要的是搞清楚ActivityManagerProxyIApplicationThread是做什么的。下面进行讲解。
这里通过和本博客另一篇讲binder机制文章中的例子做个对比,方便大家理解。

IActivityManager---------------------IPlus
ActivityManagerNative--------------plus
ActivityManagerProxy---------------PlusProxy
Activity--------------------------------进程A
ActivityManagerService-------------进程B

实际上,IActivityManager接口中定义了ActivityManagerService向应用程序(本例中即Activity)提供的多种API,Activity通过ActivityManagerProxy就可以使用这些API,向ActivityManagerService发出请求。在本例中,发出的请求是:
startService( IApplicationThread caller, Intent service, String resolvedType );
第二个参数service中包含着要启动的Service的信息,第三个参数在本例中不重要,简单起见,可以忽略。关键是第一个参数caller是干什么的?
简单来讲,caller相当于Activity所在应用程序的一个控制接口,其实际类型为ApplicationThreadNative,Activity把它提供给ActivityManagerServiceActivityManagerService通过它来控制Activity所在的应用程序。

startService()调用后,经过系统的中转,最终会调用ActivityManagerNative中的onTransact()方法,在该方法中,将会利用caller完成ActivityManagerServiceActivity的连接并调用ActivityManagerServicestartService()方法,当然,这里的连接用到的也是Binder机制,我们还是通过与本博客中讲binder机制文章中的例子做个对比来理解。
IApplicationThread———————IPlus
ApplicationThreadNative————–plus
ApplicationThreadProxy—————PlusProxy
Activity———————————–进程B
ActivityManagerService—————-进程A

现在再来看一下这张图。

《深入AndroidFramework源码内部剖析Service的启动过程》 Binder通信图

是不是感觉清楚多了?这就是
Activity
ActivityManagerService之间的
双向Binder连接
Activity
IActivityManager提供的API向
ActivityManagerService提出执行某个动作的请求(本例中是启动
RemoteService),
ActivityManagerService通过
IApplicationThread提供的API来控制
Activity所在的应用程序,这些API包括
schedulePauseActivity()、scheduleStopActivity()等。

2、转场进入ActivityManagerService

好了,Activity通过ActivityManagerProxystartService(...,Intent service,...)方法,向ActivityManagerService提出了启动RemoteService的要求,并与ActivityManagerService建立了双向binder连接并调用了ActivityManagerServicestartService()方法,在该方法中有这么关键几步:

  • 首先,根据传过来的Intent service中关于RemoteService的信息,去查找一个Service表,这个表中保存着该手机上所有的应用的<manifest>文件中声明的所有Service的信息(晕不晕?放心,不会有更绕的啦。),而且每个Service的信息都用一个ServiceRecord对象封装。经过查找,得到了RemoteService对应的ServiceRecord对象。
  • ServiceRecord对象中有一条信息用于说明该RemoteService应该运行在哪个进程中,通常情况下,就是RemoteService所在应用的进程。程序接下来会利用该信息查找另外一张表,这张表保存着当前设备上所有正在运行的进程的信息,且每个进程的信息都用一个ProcessRecord对象封装了。我们假设RemoteService所在应用还没有启动,那么显然,这次查找是落空了。

此时,程序会先将RemoteServiceServiceRecord信息暂存入一个名为mPendingServices(后面还会用到哦!)的数组中,转而去创建运行RemoteService所需要的进程,方法就是调用Process类的start("android.app.ActivityThread")方法。

说明:以上过程中涉及到的两张表都归ActivityManagerService管理。
你有没有感觉到ActivityManagerService的强大威力,有木有?但是,还有比它更牛逼的,接下来就是。

3、再次转场进入Zygote

ActivityManagerService通过Processstart("android.app.ActivityThread")方法,实际上是要求创建一个进程(为了运行RemoteService),并在进程中加载ActivityThread类,然后运行该类的main方法。这一 要求将会被Zygote收到,Zygote将会满足ActivityManagerService的要求。

在继续进行之前,我们必须停下来解决两个问题,第一个就是Zygote是什么,它能干什么?第二个就是ActivityThread是个什么梗?这玩意儿怎么还有main方法?(我们现在是在Android应用中呢还是在普通的java程序中?天哪!)

首先来看Zygote,它是系统中一个进程,每当我们要启动一个应用时,都是由它派生出一个子进程,然后在该子进程中运行我们的应用,也就是说,Android手机上运行的所有应用的进程都是Zygote进程的子进程。Zygote在英文中的意思是“受精卵”,你可以体会下Google工程师为什么将该进程命名为Zygote

第二个问题。没错,从Zygote创建子进程,加载ActivityThread类,运行它的main方法,这一过程就是一个普通的java程序的启动过程。区别在于ActivityThread运行的方式不同于一般的java程序,这种运行方式是专为Android应用程序设计的。那么,ActivityThread的运行方式特殊在什么地方呢?所谓一言不合,就看源码,下面就是ActivityThread的主要代码:

public final class ActivityThread {
             final ApplicationThread mAppThread = new ApplicationThread();
            
              public static void main(String[] args) {
                    Looper.prepareMainLooper();
                   ActivityThread thread = new ActivityThread();
                   thread.attach(false);
                    Looper.loop();
              }

             public void handleMessage(Message msg) {        
                      switch (msg.what) {
                          ......//很多很多cases
                          case CREATE_SERVICE: 
                                    handleCreateService((CreateServiceData)msg.obj);
                                    break;
                          ......//还有很多很多cases
                       }
              }

}

此时,我们必须要强调,ActivityThread main方法的运行,标志着一个新的Android应用的运行,这是一个milestone。

下面我们来分析一下ActivityThread中的代码。

简言之,以上代码就干了两件事:

  • 一是通过thread.attach(false)方法,将该应用的控制接口mAppThread(类型为ApplicationThread,就是上面图中的ApplicationThreadNative)传递给ActivityManagerService,好让ActivityManagerService来控制这个应用,这是通过Binder机制实现的。由此可见,每个应用在混沌初开的时候,就乖乖把自己的控制权交给了ActivityManagerServiceActivityManagerService不可谓不牛逼!!!
  • 二是初始化并启动一个MainLooper,而它唯一的handler就是ActivityThread对象thread(在main方法中创建)。

4、终于再次转场进入ActivityManagerService

前面说了,新建的应用通过thread.attach(false)方法把自己的控制接口交给了ActivityManagerService

还记得第2步中ActivityManagerService调用Processstart方法不?此时,该方法终于返回了,返回值是一个pid,然后ActivityManagerService就用这个pid还有接收到的ApplicationThread对象 mAppThread(虽然是个代理的),组装出一个ProcessRecord对象,再把这个对象放入正在运行的进程的记录表中。

然后呢?进程已经有了,ActivityManagerService就会把之前暂存入mPendingServices数组中的ServiceRecord取出来,把它的信息通过mAppThread发一个消息给新建的应用进程,表达了让它创建一个RemoteService并运行它的要求。

5、最后一站,转场进入新建的ActivityThread

此时,ActivityThread的对象thread会收到这个消息,然后它在handleMessage方法中的case CREATE_SERVICE:下创建了RemoteService,并把它初始化。

没错,就是handleCreateService((CreateServiceData)msg.obj);这句。这个方法的内部主要代码如下:

 private void handleCreateService(CreateServiceData data) {
          LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo);     
          Service service = null;
           java.lang.ClassLoader cl = packageInfo.getClassLoader();
           service = (Service) cl.loadClass(data.info.name).newInstance();
            service.onCreate();
}

好了,经过千回百转,柳暗花明,殚精竭虑,矢志不移,衣带渐宽终不悔的努力,我们的
RemoteService


它终于运行起来啦!!!

    原文作者:milter
    原文地址: https://www.jianshu.com/p/411b504902db
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞