Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 框架啟動流程

Android 框架啟動流程

編輯:關於Android編程

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
 
    Service(服務):服務是init進程啟動的程序、當服務退出時init進程會視情況重啟服務。
語法


service []*

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”是一個簡單的包含一系列需要預加載類的文本文件,你可以在/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);
}     最後用一張圖片總結下 圖片出處:http://blog.csdn.net/zirconsdu/article/details/8574049 \        
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved