Android源码解析四大组件系列(二)---Activity启动过程的总体把握

转载请注明文章出处LooperJing

之前写过Service的启动过程,相对来说Activity的启动过程比Service的启动过程更为复杂,其一Activity的生命周期方法比Service多,其二Activity具有启动模式和返回栈。写本文的目的在于更清晰的梳理Activity的启动过程,加强自己的内功修炼,博客粉丝日益增多,力在以最简单的方式让大家理解,跟大家一起学习。

Activity的启动过程计划用三篇博客来写;

  • 第一篇(本文),侧重Binder视角或者从进程这方面,对Activity启动先从整体有个把握,代码少,理论多。
  • 第二篇,深入源码,分析Launcher进程向SystemServer进程发起startActivity请求,SystemServer进程在向zygote进程发起请求,最后孵化出应用进程的这一过程。
  • 第三篇:深入源码,由Zygote进程孵化的应用进程是如何启动Activity的。

一、Binder的基本理解

Activity的启动有多次IPC过程,所以Binder属于预备知识,帮助我们更好理解系统的C/S的这种架构模式,我看过几篇文章还不错,推荐给大家。

二、Activity启动的双向IPC过程

一般Android各个应用进程的启动都以这样一条路线,init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

  • Init进程:Linux的根进程,Android系统是基于Linux系统的,因此可以算作是整个android操作系统的第一个进程;
  • Zygote进程是所有应用进程的父进程,所有的应用进程都是它孵化出来的;
  • SystemServer进程含有一些核心的服务,比如ActivityManagerService,PackageManagerService,WindowManagerService等;
  • 各种应用进程:启动自己编写的客户端应用时,有自己的虚拟机与运行环境。

由此可知应用的第一个Activity的启动是多个进程相互配合的结果,多个进程相互配合就少不了使用Binder进行IPC了,现在看一次IPC调用的过程是怎样的。

Activity到AMS一次IPC调用

上图大概说明了一次IPC的过程,或许你现在对里面各个类还不是很清楚,没关系,大致了解一下

ActivityManagerService(下文简称AMS),AMS是Android中最核心的服务,实现了ActivityManager,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,AMS提供了一个ArrayList mHistory来管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord,它在Android中特别重要。

ActivityManagerNative(下文简称AMN):由于AMS是系统核心服务在SystemServer进程里面,很多API不能直接开放供客户端使用,所以需要通过IPC的方式,具体是这样的,ActivityManager类内部调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信。

ActivityManagerProxy(下文简称AMP):AMP是AMS在客户端进程的一个代理,通过AMP里面的方法请求AMS。

Instrumentation:Instrumentaion是一个工具类,一个大管家。当它被启用时,系统先创建它,再通过它来创建其他组件。另外,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。Android中Junit的使用到了Intrstrumentation。关于它更详细的了解,戳我

OK,现在我们知道,Activity是如何向AMS发出startActivity这个请求了,这意味着Activity可以与AMS进行通信,但是AMS却不能与Activity通信,Binder是单向的,所以在Activity发出请求之后,AMS需要通知Activity发生状态改变,要做到这一点,自然就在AMS到Activity这个过程建立一个Binder,如下。

AMS到Activity的一次IPC过程

大致过程就是,SystemServer进程在收到请求后,再通过IPC向应用进程发送scheduleLaunchActivity请求,应用进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息,主线程在收到Message后,创建目标Activity,并回调Activity.onCreate()等方法。

对上面的理解不是太明白,在看下面这张图,简单多了,AMS到Activity这个过程建立了一个Binder,Activity到AMS这个过程也建立了一个Binder,这就能相互通信了。


双向Binder的建立

上图就是Activity与AMS之间的双向Binder连接,(备注:这个就是理解Activity启动流程的指南针,不记住这个,复杂的启动流程会让你晕头转向)。Activity用IActivityManager提供的API向AMS提出执行某个动作的请求(本例中是启动RemoteService),AMS通过IApplicationThread提供的API来控制Activity所在的应用程序,这些API包括schedulePauseActivity()、scheduleStopActivity()等。

IActivityManager接口定义的API,启动四大组件的等多种请求都在里面。


对IActivityManager了解更近一步

IApplicationThread接口定义的API,一看就比IActivityManager高逼格一点,IActivityManager好多方法是start开头,表示去AMS请求,IApplicationThread以schedule开头,表示对Activity进行调度。


对IApplicationThread了解更近一步

分析到这里,我们不知不觉间忽略了两个问题,那就是启动Activity至少需要两个前提,第一是,应用进程存在,第二AMS已经初始化完毕。在调用startActivity方法时候,如果我们的应用进程不存在,Activity能启动吗,当然是不能的,比如点击桌面图标的时候,这个时候需要先创建进程。关于Zygote孵化应用进程,这个暂时不说,先看看AMS服务注册。

三、AMS服务注册

先忽略 Activity调用ActivityManagerService启动应用,直接从SystemServer的main方法说起。

 SystemServer.java

 /**
    * The main entry point from zygote.
    */
   public static void main(String[] args) {
       new SystemServer().run();
   }

run方法中,调用了startBootstrapServices。

 private void startBootstrapServices() {
      
       ......
       //启动AMS服务
       Installer installer = mSystemServiceManager.startService(Installer.class);

       //请注意这里参数是Lifecycle,因为AMS是在Lifecycle里面new出来的
       mActivityManagerService = mSystemServiceManager.startService(
               ActivityManagerService.Lifecycle.class).getService();
       mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
       mActivityManagerService.setInstaller(installer);

       mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

       mActivityManagerService.initPowerManagement();

        ......
       mActivityManagerService.setSystemProcess();
     ......
}

 public SystemService startService(String className) {
       final Class<SystemService> serviceClass;
       try {
           serviceClass = (Class<SystemService>)Class.forName(className);
       } catch (ClassNotFoundException ex) {
           Slog.i(TAG, "Starting " + className);
       }
       return startService(serviceClass);
   }

继续

public <T extends SystemService> T startService(Class<T> serviceClass) {
       try {
           final String name = serviceClass.getName();
           // 1、创建服务
           final T service;
           try {
               Constructor<T> constructor = serviceClass.getConstructor(Context.class);
             // 如果传进来的是ActivityManagerService.Lifecycle对象,那么ActivityManagerService就能被创建
               service = constructor.newInstance(mContext);
           } catch (InstantiationException ex) {
               throw new RuntimeException("Failed to create service " + name
                       + ": service could not be instantiated", ex);
           }
           // 2、注册服务
           mServices.add(service);

           // 3、启动服务
           try {
               service.onStart();
           } catch (RuntimeException ex) {
               throw new RuntimeException("Failed to start service " + name
                       + ": onStart threw an exception", ex);
           }
           return service;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
   }
ActivityManagerService.java

  public static final class Lifecycle extends SystemService {
       private final ActivityManagerService mService;

       public Lifecycle(Context context) {
           super(context);
         //ActivityManagerService被new出来了
           mService = new ActivityManagerService(context);
       }

       @Override
       public void onStart() {
         //  启动
           mService.start();
       }

       public ActivityManagerService getService() {
           return mService;
       }
   }

 private void start() {
       Process.removeAllProcessGroups();
       mProcessCpuThread.start();

       mBatteryStatsService.publish(mContext);
       mAppOpsService.publish(mContext);
       Slog.d("AppOps", "AppOpsService published");
       LocalServices.addService(ActivityManagerInternal.class, new LocalService());
   }

回到 startBootstrapServices里面调用的 mActivityManagerService.setSystemProcess();

public void setSystemProcess() {
       try {
           ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
           ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
           ServiceManager.addService("meminfo", new MemBinder(this));
           ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
           ServiceManager.addService("dbinfo", new DbBinder(this));
           ......


      // 设置application info LoadedApkinfo 有关 framework-res.apk
       ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS);
       mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
       
       //给SystemServer进程创建ProcessRecord,adj值,就是将SystemServer进程加入到AMS进程管理机制中,跟应用进程一致
       synchronized (this) {
           ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
           app.persistent = true;
           app.pid = MY_PID;
           app.maxAdj = ProcessList.SYSTEM_ADJ;
           app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
           synchronized (mPidsSelfLocked) {
               mPidsSelfLocked.put(app.pid, app);
           }
           updateLruProcessLocked(app, false, null);
           updateOomAdjLocked();
 }

ServiceManager这里面注册了很多的服务,可通过dumpsys <服务名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo。在Android中所有的核心服务,并不是直接给上层使用,都先交给ServiceManager管理,上层使用的时候可以从ServiceManager获取,ServiceManager相当于一个路由作用。现在来看一张经典的图。其中注册服务,获取服务以及使用服务,每一次都是一个完整的Binder IPC过程,可见理解Binder是多么的重要啊。关于AMS启动得深入了解,请戳我

  • 注册服务:首先AMS注册到ServiceManager。AMS所在进程(SystemServer)是客户端,ServiceManager是服务端。
  • 获取服务:Client进程使用AMS前,须先向ServiceManager中获取AMS的代理类AMP。该过程。AMP所在进程(应用进程)是客户端,ServiceManager是服务端。
  • 使用服务: app进程根据得到的代理类AMP,便可以直接与AMS所在进程交互。该过程,AMP所在进程(应用进程)是客户端,AMS所在进程(SystemServer)是服务端。

OK ,本文终于写完了,翻看源码,查阅资料,画图花了两天时间,最后回顾一下,本文解释了双向Binder是如何建立的?这个是最重要的部分,其次AMS作为管理Android系统组件的核心服务,AMS是如何注册的?(在SystemServer执行run()方法的时候被创建,并运行在独立的进程中)。OK,see you。

·

Please accept mybest wishes for your happiness and success

参考链接:

http://www.cloudchou.com/android/post-788.html

[Android源码解析之(八)-->Zygote进程启动流程]
(http://blog.csdn.net/qq_23547831/article/details/51104873)

[深入理解Android卷二 全文-第六章]深入理解ActivityManagerService

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

Android系统启动-SystemServer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,699评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,124评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,127评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,342评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,356评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,057评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,654评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,572评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,205评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,343评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,015评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,704评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,196评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,690评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,348评论 2 358

推荐阅读更多精彩内容