Android 框架启动流程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tianmi1988/article/details/51164327

As we all know,Android手机系统本质上是一个基于Linux的应用程序,它以Linux系统为内核。因此系统的启动过程包括Linux内核启动和Android框架启动两个阶段。

Linux内核启动

1、装载引导程序bootloader
      Linux内核启动时首先装载执行bootloader引导程序,装载完成后进入内核程序。
2、加载Linux内核
      Linux内核加载主要包括初始化kernel核心(内存初始化,打开中断,初始化进程表等)、初始化驱动、启动内核后台(daemons)线程、安装根(root)文件系统等。
      Linux加载的最后阶段启动执行第一个用户级进程init(内核引导参数上一般都会设置“init=/init”,由kernel自动执行,PID为1,是所有进程的父进程)。由此进入Android框架的启动阶段。

android框架的启动

 Android框架的启动始于init进程,这个阶段也是本文要重点讲解的。概括起来启动过程可以分为以下几个主要的阶段:
   1、init进程启动
   2、init.rc脚本启动
   3、zygote服务启动
   4、System Server进程启动
   5、Home应用启动



下面将从Android5.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结,

以下学习过程中代码片段中均有省略不完整,请参照源码。

Init进程的启动

init是一个进程,确切地说,它是Linux系统中用户空间的第一个进程。由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。


init进程的入口函数是main,system\core\init\init.c

init进程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。

int main(int argc, char **argv)
{
intdevice_fd = -1;
intproperty_set_fd = -1;
intsignal_recv_fd = -1;
intkeychord_fd = -1;
int fd_count;
ints[2];
intfd;
structsigaction act;
chartmp[PROP_VALUE_MAX];
structpollfd ufds[4];
char*tmpdev;
char*debuggable;
//设置子进程退出的信号处理函数,该函数为sigchld_handler。
act.sa_handler = sigchld_handler;
act.sa_flags= SA_NOCLDSTOP;
act.sa_mask = 0;
act.sa_restorer = NULL;
sigaction(SIGCHLD, &act, 0);
......//创建一些文件夹,并挂载设备,这些是和Linux相关的,不拟做过多讨论。
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0,NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
//重定向标准输入/输出/错误输出到/dev/_null_。
open_devnull_stdio();
/*
设置init的日志输出设备为/dev/__kmsg__,不过该文件打开后,会立即被unlink了,
这样,其他进程就无法打开这个文件读取日志信息了。
*/
log_init();
//上面涉及很多和Linux系统相关的知识,不熟悉的读者可自行研究,它们不影响我们的分析
//解析init.rc配置文件
parse_config_file("/init.rc");
......
//下面这个函数通过读取/proc/cpuinfo得到机器的Hardware名,我的HTCG7手机为bravo。
get_hardware_name();
snprintf(tmp,sizeof(tmp), "/init.%s.rc", hardware);
//解析这个和机器相关的配置文件,我的G7手机对应文件为init.bravo.rc。
parse_config_file(tmp);
/*
解析完上述两个配置文件后,会得到一系列的Action(动作),下面两句代码将执行那些处于
early-init阶段的Action。init将动作执行的时间划分为四个阶段:early-init、init、
early-boot、boot。由于有些动作必须在其他动作完成后才能执行,所以就有了先后之分。哪些
动作属于哪个阶段由配置文件决定。后面会介绍配置文件的相关知识。
*/
action_for_each_trigger("early-init", action_add_queue_tail);
drain_action_queue();
/*
创建利用Uevent和Linux内核交互的socket。关于Uevent的知识,第9章中对
Vold进行分析时会做介绍。
*/
device_fd = device_init();
//初始化和属性相关的资源
property_init();
//初始化/dev/keychord设备,这和调试有关,本书不讨论它的用法。读者可以自行研究,
//内容比较简单。
keychord_fd = open_keychord();
......
/*
INIT_IMAGE_FILE定义为”/initlogo.rle”,下面这个函数将加载这个文件作为系统的开机
画面,注意,它不是开机动画控制程序bootanimation加载的开机动画文件。
*/
if(load_565rle_image(INIT_IMAGE_FILE) ) {
/*
如果加载initlogo.rle文件失败(可能是没有这个文件),则会打开/dev/ty0设备,并
输出”ANDROID”的字样作为开机画面。在模拟器上看到的开机画面就是它。
*/
......
}
}
if(qemu[0])
import_kernel_cmdline(1);
......
//调用property_set函数设置属性项,一个属性项包括属性名和属性值。
property_set("ro.bootloader", bootloader[0] ? bootloader :"unknown");
......//执行位于init阶段的动作
action_for_each_trigger("init", action_add_queue_tail);
drain_action_queue();
//启动属性服务
property_set_fd = start_property_service();
/*
调用socketpair函数创建两个已经connect好的socket。socketpair是Linux的系统调用,
不熟悉的读者可以利用man socketpair查询相关信息。后面就会知道它们的用处了。
*/
if(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
signal_fd = s[0];
signal_recv_fd = s[1];
......
}
......
//执行配置文件中early-boot和boot阶段的动作。
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
drain_action_queue();
......
//init关注来自四个方面的事情。
ufds[0].fd= device_fd;//device_fd用于监听来自内核的Uevent事件
ufds[0].events = POLLIN;
ufds[1].fd = property_set_fd;//property_set_fd用于监听来自属性服务器的事件
ufds[1].events= POLLIN;
//signal_recv_fd由socketpair创建,它的事件来自另外一个socket。
ufds[2].fd = signal_recv_fd;
ufds[2].events = POLLIN;
fd_count = 3;
if(keychord_fd > 0) {
//如果keychord设备初始化成功,则init也会关注来自这个设备的事件。
ufds[3].fd = keychord_fd;
ufds[3].events = POLLIN;
fd_count++;
}
......
#if BOOTCHART
......//与Boot char相关,不做讨论了。
/*
Boot chart是一个小工具,它能对系统的性能进行分析,并生成系统启动过程的图表,
以提供一些有价值的信息,而这些信息最大的用处就是帮助提升系统的启动速度。
*/
#endif
for(;;) {
//从此init将进入一个无限循环。
int nr, i, timeout = -1;
for (i = 0; i < fd_count; i++)
ufds[i].revents = 0;
//在循环中执行动作
drain_action_queue();
restart_processes(); //重启那些已经死去的进程
......
#if BOOTCHART
...... // Boot Chart相关
#endif
//调用poll等待一些事情的发生
nr= poll(ufds, fd_count, timeout);
......
//ufds[2]保存的是signal_recv_fd,用于接收来自socket的消息。
if(ufds[2].revents == POLLIN) {
//有一个子进程去世,init要处理这个事情
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0))
;
continue;
}
if(ufds[0].revents == POLLIN)
handle_device_fd(device_fd);//处理Uevent事件
if(ufds[1].revents == POLLIN)
handle_property_set_fd(property_set_fd);//处理属性服务的事件。
if(ufds[3].revents == POLLIN)
handle_keychord(keychord_fd);//处理keychord事件。
}
return0;
}

这个函数摘抄过来已经精简了不少。总的来说,在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听……

总的来说init的工作流程精简为以下几点:

创建一些文件夹并挂载设备

解析两个配置文件init.rc和init.hardware.rc,其中,将分析对init.rc文件的解析。
 执行各个阶段的动作,创建Zygote的工作就是在其中的某个阶段完成的。
调用property_init初始化属性相关的资源,并且通过property_start_service启动属性服务。

init进入一个无限循环,并且等待一些事情的发生。重点关注init如何处理来自socket和来自属性服务器相关的事情。


1、解析 Init.rc

对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。
Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法


    on <trigger>
        <command>
        <command>
        <command>
Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法


service <name> <pathname> [<argument>]*
    <option>
    <option>
    ...
Options(选项)
选项是对服务的描述。它们影响init进程如何以及何时启动服务。
咱们来看看默认的init.rc文件。这里我只列出了主要的事件以及服务。

Action/Service 描述
on early-init 设置init进程以及它创建的子进程的优先级,设置init进程的安全环境
on init 设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点
on fs 挂载mtd分区
on post-fs 改变系统目录的访问权限
on post-fs-data 改变/data目录以及它的子目录的访问权限
on boot 基本网络的初始化,内存管理等等
service servicemanager 启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等…
service zygote 启动zygote作为应用进程
在这个阶段你可以在设备的屏幕上看到“Android”logo了。


需要重点说明的是init.rc脚本文件配置了一些重要的服务,init进程通过创建子进程启动这些服务,这里创建的service都属于native服务,运行在Linux空间,通过socket向上层提供特定的服务,并以守护进程的方式运行在后台。脚本中服务的定义示例如下:
service servicemanager /system/bin/servicemanager  
    class core  
    user system  
    group system  
    critical  
    onrestart restart zygote  
08    onrestart restart media  
  
service ril-daemon /system/bin/rild  
    class main  
    socket rild stream 660 root radio  
    socket rild-debug stream 660 radio system  
    user root  
    group radio cache inet misc audio sdcard_rw log  
  
service surfaceflinger /system/bin/surfaceflinger  
    class main  
    user system  
    group graphics  
    onrestart restart zygote  
  
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
    class main  
    socket zygote stream 666  
    onrestart write /sys/android_power/request_state wake  
    onrestart write /sys/power/state on  
    onrestart restart media  
    onrestart restart netd  
  
service media /system/bin/mediaserver  
    class main  
    user media  
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc  
    ioprio rt 4


     通过init.rc脚本系统启动了以下几个重要的服务:
      1)servicemanager:启动binder IPC,管理所有的Android系统服务
      2)mountd:设备安装Daemon,负责设备安装及状态通知
      3)debuggerd:启动debug system,处理调试进程的请求
      4)rild:启动radio interface layer daemon服务,处理电话相关的事件和请求
      5)mediaserver:启动AudioFlinger,MediaPlayerService and CameraService,负责多媒体播放相关的功能,包括音视频解码、显示输出
      6)zygote:进程孵化器,启动Android Java VMRuntime和启动systemserver,负责Android应用进程的孵化工作


在解析rc脚本文件时,将相应的类型放入各自的List中:

  \system\core\init\Init_parser.c  :init_parse_config_file( )存入到action_queue、   action_list、 service_list中,解析过程可以看一下parse_config函数,类似状态机形式

  这其中包含了服务:adbd、servicemanager、vold、ril-daemon、debuggerd、surfaceflinger、zygote、media……

2、Nativie服务启动(包括ServiceManager

文件解析完成之后将service放入到service_list中。

   \system\core\init\builtins.c

       Service的启动是在do_class_start函数中完成:
int do_class_start(int nargs, char **args)
{
    service_for_each_class(args[1], service_start_if_not_disabled);
    return 0;
}

遍历所有名称为classname,状态不为SVC_DISABLED的Service启动
void service_for_each_class(const char *classname,
                            void (*func)(struct service *svc))
{
       ……
}


static void service_start_if_not_disabled(struct service *svc)
{
    if (!(svc->flags & SVC_DISABLED)) {
        service_start(svc, NULL);
    }
}

do_class_start对应的命令:

  KEYWORD(class_start, COMMAND, 1, do_class_start)


init.rc文件中搜索class_start:class_start main 、class_start core、……

  main、core即为do_class_start参数classname

init.rc文件中Service class名称都是main:

       service drm /system/bin/drmserver

    class main

  service surfaceflinger /system/bin/surfaceflinger

       class main

于是就能够通过main名称遍历到所有的Service,将其启动。

do_class_start调用:

       init.rc中

    on boot  //action
      class_start core    //执行command 对应 do_class_start
          class_start main

Init进程main函数中:
system/core/init/init.c中:
int main(){
    //挂载文件
       //解析配置文件:init.rc……
       //初始化化action queue
     ……
       for(;;){
              execute_one_command();
              restart_processes();
              for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
       }
}

  循环调用service_start,将状态SVC_RESTARTING启动, 将启动后的service状态设置为SVC_RUNNING。
  pid=fork();
  execve();

  在消息循环中:Init进程执行了Android的Command,启动了Android的NativeService,监听Service的变化需求,Signal处理。

Init进程是作为属性服务(Property service),维护这些NativeService。
需要重点说明的是init.rc脚本文件配置了一些重要的服务,init进程通过创建子进程启动这些服务,这里创建的service都属于native服务,运行在Linux空间,通过socket向上层提供特定的服务,并以守护进程的方式运行在后台


  重点看下servicemanager ,在.rc脚本文件中servicemanager 的描述:

service servicemanager /system/bin/servicemanager
  class core
  user system
  group system
  critical
  onrestart restart zygote
  onrestart restart media
  onrestart restart surfaceflinger
  onrestart restart drm
 

       ServiceManager用来管理系统中所有的binder service,不管是本地的c++实现的还是java语言实现的都需要
这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的Service使用前都必须先在servicemanager中进行注册。

  do_find_service( )
  do_add_service( )
  svcmgr_handler( )
  代码位置:frameworks\base\cmds\servicemanager\Service_manager.c

3、zygote服务启动

在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。


      zygote进程孵化了所有的Android应用进程,是Android Framework的基础,该进程的启动也标志着Framework框架初始化启动的开始。zygote服务进程的主要功能:


       1)注册底层功能的JNI函数到虚拟机
       2)预加载java类和资源
       3)fork并启动System Server核心进程
       4)作为守护进程监听处理“孵化新进程”的请求

加载ZygoteInit类,源代码:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在<Android Source>/frameworks/base找到“preloaded-classes”文件。
preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。
在这个阶段,你可以看到启动动画。


      如上面所述,zygote是通过init脚本启动的:


service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
    class main  
    socket zygote stream 666  
    onrestart write /sys/android_power/request_state wake  
    onrestart write /sys/power/state on  
    onrestart restart media  
    onrestart restart netd
    上面脚本的含义为作为孵化进程(-Xzygote参数),通过system/bin/app_process启动zygote服务,同时启动SystemServer(--start-system-server参数)进程。该服务对应的可执行文件app_process的源码位于frameworks/base/cmds/app_process。


    zygote服务在函数app_main.cpp:main()中启动。该函数的关键代码有两处:
    1)创建AndroidRuntime对象:


    AppRuntime runtime; // android运行空间
    2)启动zygote和systemserver:


    runtime.start("com.android.internal.os.ZygoteInit", 
               startSystemServer ? "start-system-server" : "");
      方法start()代码位于frameworks/base/core/jni/AndroidRuntime.cpp中,主要逻辑如下:
    ---调用startVM创建虚拟机:内部使用以下代码创建vm对象:


     if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        LOGE("JNI_CreateJavaVM failed\n");
        goto bail;
     }
        ---注册底层功能的JNI函数到JNIEnv: startReg()
   ---调用env->GetStaticMethodID和env->CallStaticVoidMethod()函数运行Java类ZygoteInit的main()
      由此可见虚拟机启动后执行的第一个Java类是ZygoteInit.java,并进入ZygoteInit.java:main()函数中。在main函数中实现了以下逻辑:
      1)启动服务端Socket端口:
        调用registerZygoteSocket()实现,主要用于接受处理创建新进程的请求。
   2)预加载指定的java类和资源:
        调用preloadClasses()预加载指定的java类,调用preloadResources()预加载指定的Resources。特别说明的是孵化器进程会把这些预先加载的类和资源共享给所有APK应用进程,这样有效的解决了Framework类和资源共享的问题。
   3)启动System Server进程:
        调用startSystemServer()创建(fork)SystemServer进程。该函数的关键代码有三处:
        ---设定启动进程的相关信息:比如进程名称、启动后装载的第一个java类
        ---调用forkSystemServer()从当前的zygote进程孵化出新的进程
        ---调用函数hanldeSystemServerProcess()关闭从Zygote进程继承过来的Socket,调用RuntimeInit.zygoteInit()启动SystemServer.java:main()函数
   4)循环监听孵化新Dalvik进程的请求:
        调用runSelectLoopMode()进入无限循环:监听客户端socket连接,根据请求孵化新的应用进程。Process类中保存了客户端socket,并由ActivityManagerService管理该客户端。每当需要启动新的Dalvik应用进程时,ActivityManagerService都会通过该socket客户端与Zygote进程的socket服务端进行通信,请求Zygote孵化出新的进程。
  至此,启动zygote服务工作完成,需要说明的是zygote进程即为app_process可执行程序所在进程。

4、System Server进程启动       

     SystemServer进程在Android的运行环境中扮演了“神经中枢”的作用,Android应用能够直接交互的大部分系统服务都在该进程中运行,如WindowManagerServer、ActivityManagerSystemService、PackageManagerServer等,这些系统服务都是以独立线程的方式存在于SystemServer进程中。System Server进程的主要功能:

     1)加载android servers底层函数库
     2)启动android系统中的native服务
     3)创建、注册并启动Android的系统服务,在独立线程中运行
     4)创建Looper消息循环,处理System Server进程中的事件消息


     在zygote进程中调用函数startSystemServer()创建和启动Server进程,进程首先执行的函数是SystemServer.java:main()。该函数函数实现的主要逻辑为:
     1)加载android_servers函数库
     2)启动native服务:
      调用本地函数init1()实现,该函数的源码位于文件frameworks/base/services/jni/com_android_server_systemService.cpp中,涉及的函数system_init()实现在文件frameworks/base/cmds/system_server/library/system_init.cpp中。
     3)启动Android系统的各种系统服务:
     调用函数init2()实现,该函数首先创建了一个ServerThread对象,该对象是一个线程,然后直接运行该线程,如以下代码所示:


   public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }
     从ServerThread的run()方法内部开始真正启动各种服务线程。
         ---创建Android系统服务对象,并注册到ServiceManager
         ---在SystemServer进程中建立Looper消息循环:通过Looper.prepare和Looper.loop来实现
   ---系统就绪通知:调用systemReady()通知各个服务


      System Server进程启动过程中最核心的一步是“启动Android系统的各种系统服务”,这些系统服务构成了整个Android框架的基础(如图所示),通过Binder IPC为上层应用提供各种功能。Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。介绍下几个重要系统服务的功能。


       1)ActivityManagerService
            Activity管理服务,主要功能包括:
            ---统一管理和调度各应用程序的Activity,维护系统中运行的所有应用Task和Activity
            ---内存管理:应用程序关闭时对应进程还在运行,当系统内存不足时根据策略kill掉优先级较低进程
            ---进程管理:维护和管理系统中运行的所有进程,并提供了查询进程信息的API
            ---Provider、Service和Broadcast管理和调度

      2)WindowManagerService
            窗口管理服务,主要功能包括为应用程序分配窗口,并管理这些窗口。包括分配窗口的大小、调节各窗口的叠放次序、隐藏或者显示窗口,程序退出时删除窗口。

      3)PackageManagerService
            程序包管理服务,主要功能为:
             ---根据intent查找匹配的Activity、Provider以及Service
             ---进行权限检查,即当应用程序调用某个需要一定权限的函数时,系统能够判断调用者是否具备该权限
             ---提供安装、删除应用程序的API

      4)NotificationManagerService
            通知管理服务,负责管理和通知后台事件的发生等,这个和statusbar服务结合在一起,一般会在statusbar上添加响应图标。用户可以通过这知道系统后台发生了什么事情。

      5)AudioService
            音频管理服务,AudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理。

      6)TelephonyRegistry
             电话服务管理,用于监听和上报电话状态,包括来电、通话、信号变化等。

       到这里,Android Framework的启动已经完成,框架中提供的各种服务也已经就绪,可以正常运行并响应处理应用的各种操作请求。
一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。


核心服务:

启动电源管理器;
创建Activity管理器;
启动电话注册;
启动包管理器;
设置Activity管理服务为系统进程;
启动上下文管理器;
启动系统Context Providers;
启动电池服务;
启动定时管理器;
启动传感服务;
启动窗口管理器;
启动蓝牙服务;
启动挂载服务。

其他服务:
启动状态栏服务;
启动硬件服务;
启动网络状态服务;
启动网络连接服务;
启动通知管理器;
启动设备存储监视服务;
启动定位管理器;
启动搜索服务;
启动剪切板服务;
启动登记服务;
启动壁纸服务;
启动音频服务;
启动耳机监听;
启动AdbSettingsObserver(处理adb命令)。

   启动完成后需要启动home应用进入手机主界面,这是下面第5节讲解的。


5、Home应用启动

     在ServerThread:run()函数的最后调用了ActivityManagerService.self().systemReady方法,该方法实现了如下代码用于启动第一个Activity:

    mMainStack.resumeTopActivityLocked(null);
public void systemReady(final Runnable goingCallback) {
    ……
    //ready callback
       if (goingCallback != null)
              goingCallback.run();

       synchronized (this) {
              // Start up initial activity.
              // ActivityStack mMainStack;
              mMainStack.resumeTopActivityLocked(null);
       }
……

}

final boolean resumeTopActivityLocked(ActivityRecord prev) {
  // Find the first activity that is not finishing.
  ActivityRecord next = topRunningActivityLocked(null);
  if (next == null) {
    // There are no more activities!  Let's just start up the
    // Launcher...
    if (mMainStack) {
      //ActivityManagerService mService;
      return mService.startHomeActivityLocked();
    }
  }
  ……
}


     由于系统刚启动时没有任何Activity对象,代码会调用ActivityManagerService:startHomeActivityLocked函数启动Home应用:
        Intent intent = new Intent(
            mTopAction,
            mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }

最后用一张图片总结下




参考资料:

猜你喜欢

转载自blog.csdn.net/tianmi1988/article/details/51164327