1. 程式人生 > >App啟動流程

App啟動流程

目錄介紹

  • 1.什麼是Zygote程序
    • 1.1 簡單介紹
    • 1.2 各個程序的先後順序
    • 1.3 程序作用說明
  • 2.Zygote程序的啟動流程
    • 2.1 原始碼位置
    • 2.2 ZygoteInit類的main方法
    • 2.3 registerZygoteSocket(socketName)分析
    • 2.4 preLoad()方法分析
    • 2.5 startSystemServer()啟動程序
  • 3.SystemServer程序啟動流程
    • 3.1 SystemServer程序簡介
    • 3.2 SystemServer的main方法
    • 3.3 檢視run方法
    • 3.4 run方法中createSystemContext()解析
    • 3.5 mSystemServiceManager的建立
  • 4.啟動服務
    • 4.1 啟動哪些服務
    • 4.2 啟動服務流程原始碼分析
    • 4.3 啟動部分服務

好訊息

  • 部落格筆記大彙總【16年3月到至今】,包括Java基礎及深入知識點,Android技術部落格,Python學習筆記等等,還包括平時開發中遇到的bug彙總,當然也在工作之餘收集了大量的面試題,長期更新維護並且修正,持續完善……開源的檔案是markdown格式的!同時也開源了生活部落格,從12年起,積累共計47篇[近20萬字],轉載請註明出處,謝謝!
  • 連結地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起於忽微,量變引起質變!

1.什麼是Zygote程序

1.1 簡單介紹

  • Zygote程序是所有的android程序的父程序,包括SystemServer和各種應用程序都是通過Zygote程序fork出來的。Zygote(孵化)程序相當於是android系統的根程序,後面所有的程序都是通過這個程序fork出來的
  • 雖然Zygote程序相當於Android系統的根程序,但是事實上它也是由Linux系統的init程序啟動的。

1.2 各個程序的先後順序

  • init程序 --> Zygote程序 --> SystemServer程序 -->各種應用程序

1.3 程序作用說明

  • init程序:linux的根程序,android系統是基於linux系統的,因此可以算作是整個android作業系統的第一個程序;
  • Zygote程序:android系統的根程序,主要作用:可以作用Zygote程序fork出SystemServer程序和各種應用程序;
  • SystemService程序:主要是在這個程序中啟動系統的各項服務,比如ActivityManagerService,PackageManagerService,WindowManagerService服務等等;
  • 各種應用程序:啟動自己編寫的客戶端應用時,一般都是重新啟動一個應用程序,有自己的虛擬機器與執行環境;

2.Zygote程序的啟動流程

2.1 原始碼位置

  • 位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
  • Zygote程序mian方法主要執行邏輯:
    • 初始化DDMS;
    • 註冊Zygote程序的socket通訊;
    • 初始化Zygote中的各種類,資原始檔,OpenGL,類庫,Text資源等等;
    • 初始化完成之後fork出SystemServer程序;
    • fork出SystemServer程序之後,關閉socket連線;

2.2 ZygoteInit類的main方法

  • init程序在啟動Zygote程序時一般都會呼叫ZygoteInit類的main方法,因此這裡看一下該方法的具體實現(基於android23原始碼);
    • 呼叫enableDdms(),設定DDMS可用,可以發現DDMS啟動的時機還是比較早的,在整個Zygote程序剛剛開始要啟動額時候就設定可用。
    • 之後初始化各種引數
    • 通過呼叫registerZygoteSocket方法,註冊為Zygote程序註冊Socket
    • 然後呼叫preload方法實現預載入各種資源
    • 然後通過呼叫startSystemServer開啟SystemServer服務,這個是重點
    public static void main(String argv[]) {
        try { //設定ddms可以用 RuntimeInit.enableDdms(); SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); SamplingProfilerIntegration.writeZygoteSnapshot(); gcAndFinalize(); Trace.setTracingEnabled(false); if (startSystemServer) { startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } } 

2.3 registerZygoteSocket(socketName)分析

  • 呼叫registerZygoteSocket(String socketName)為Zygote程序註冊socket
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); sServerSocket = new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } } 

2.4 preLoad()方法分析

  • 原始碼如下所示
    static void preload() {
        Log.d(TAG, "begin preload"); preloadClasses(); preloadResources(); preloadOpenGL(); preloadSharedLibraries(); preloadTextResources(); // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); Log.d(TAG, "end preload"); } 
  • 大概操作是這樣的:
    • preloadClasses()用於初始化Zygote中需要的class類;
    • preloadResources()用於初始化系統資源;
    • preloadOpenGL()用於初始化OpenGL;
    • preloadSharedLibraries()用於初始化系統libraries;
    • preloadTextResources()用於初始化文字資源;
    • prepareWebViewInZygote()用於初始化webview;

2.5 startSystemServer()啟動程序

  • 這段邏輯的執行邏輯就是通過Zygote fork出SystemServer程序
    private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; } 

3.SystemServer程序啟動流程

3.1 SystemServer程序簡介

  • SystemServer程序主要的作用是在這個程序中啟動各種系統服務,比如ActivityManagerService,PackageManagerService,WindowManagerService服務,以及各種系統性的服務其實都是在SystemServer程序中啟動的,而當我們的應用需要使用各種系統服務的時候其實也是通過與SystemServer程序通訊獲取各種服務物件的控制代碼的。

3.2 SystemServer的main方法

  • 如下所示,比較簡單,只是new出一個SystemServer物件並執行其run方法,檢視SystemServer類的定義我們知道其實final型別的,所以我們一般不能重寫或者繼承。
  • image

3.3 檢視run方法

  • 程式碼如下所示
    • 首先判斷系統當前時間,若當前時間小於1970年1月1日,則一些初始化操作可能會處所,所以當系統的當前時間小於1970年1月1日的時候,設定系統當前時間為該時間點。
    • 然後是設定系統的語言環境等
    • 接著設定虛擬機器執行記憶體,載入執行庫,設定SystemServer的非同步訊息
    private void run() {
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
    
        if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory! VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further. Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user. Environment.setUserRequired(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services. System.loadLibrary("android_servers"); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } 
  • 然後下面的程式碼是:
    // Initialize the system context.
    createSystemContext();
    
    // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    
    // Start services.
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } 

3.4 run方法中createSystemContext()解析

  • 呼叫createSystemContext()方法:
    • 可以看到在SystemServer程序中也存在著Context物件,並且是通過ActivityThread.systemMain方法建立context的,這一部分的邏輯以後會通過介紹Activity的啟動流程來介紹,這裡就不在擴充套件,只知道在SystemServer程序中也需要建立Context物件。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }
    

3.5 mSystemServiceManager的建立

  • 看run方法中,通過SystemServiceManager的構造方法建立了一個新的SystemServiceManager物件,我們知道SystemServer程序主要是用來構建系統各種service服務的,而SystemServiceManager就是這些服務的管理物件。
  • 然後呼叫:
    • 將SystemServiceManager物件儲存SystemServer程序中的一個數據結構中。
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); 
  • 最後開始執行:
    // Start services.
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } 
    • 裡面主要涉及了是三個方法:
      • startBootstrapServices() 主要用於啟動系統Boot級服務
      • startCoreServices() 主要用於啟動系統核心的服務
      • startOtherServices() 主要用於啟動一些非緊要或者是非需要及時啟動的服務

4.啟動服務

4.1 啟動哪些服務

  • 在開始執行啟動服務之前總是會先嚐試通過socket方式連線Zygote程序,在成功連線之後才會開始啟動其他服務。
  • image

4.2 啟動服務流程原始碼分析

  • 首先看一下startBootstrapServices方法:
    private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);
    
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
    
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    
        mActivityManagerService.initPowerManagement();
    
        // Manages LEDs and display backlight so we need it to bring up the display.
        mSystemServiceManager.startService(LightsService.class);
    
        // Display manager is needed to provide display metrics before package manager
        // starts up. mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); // We need the default display before we can initialize the package manager. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Only run "core" apps if we're encrypting the device. String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; } else if (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps"); mOnlyCore = true; } // Start the package manager. Slog.i(TAG, "Package Manager"); mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); Slog.i(TAG, "User Service"); ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance()); // Initialize attribute cache used to cache resources from packages. AttributeCache.init(mSystemContext); // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); // The sensor service needs access to package manager service, app ops // service, and permissions service, therefore we start it after them. startSensorService(); } 
  • 先執行:
    Installer installer = mSystemServiceManager.startService(Installer.class);
    
  • mSystemServiceManager是系統服務管理物件,在main方法中已經建立完成,這裡我們看一下其startService方法的具體實現:
    • 可以看到通過反射器構造方法創建出服務類,然後新增到SystemServiceManager的服務列表資料中,最後呼叫了service.onStart()方法,因為傳遞的是Installer.class
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);
    
        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) { throw new RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName()); } final T service; try { Constructor<T> constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext); } catch (InstantiationException ex) { throw new RuntimeException("Failed to create service " + name + ": service could not be instantiated", ex); } catch (IllegalAccessException ex) { throw new RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (NoSuchMethodException ex) { throw new RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (InvocationTargetException ex) { throw new RuntimeException("Failed to create service " + name + ": service constructor threw an exception", ex); } // Register it. mServices.add(service); // Start it. try { service.onStart(); } catch (RuntimeException ex) { throw new RuntimeException("Failed to start service " + name + ": onStart threw an exception", ex); } return service; } 
  • 看一下Installer的onStart方法:
    • 很簡單就是執行了mInstaller的waitForConnection方法,這裡簡單介紹一下Installer類,該類是系統安裝apk時的一個服務類,繼承SystemService(系統服務的一個抽象介面),需要在啟動完成Installer服務之後才能啟動其他的系統服務。
    @Override
    public void onStart() { Slog.i(TAG, "Waiting for installd to be ready."); mInstaller.waitForConnection(); } 
  • 然後檢視waitForConnection()方法:
    • 通過追蹤程式碼可以發現,其在不斷的通過ping命令連線Zygote程序(SystemServer和Zygote程序通過socket方式通訊,其他程序通過Binder方式通訊)
    public void waitForConnection() { for (;;) { if (execute("ping") >= 0) { return; } Slog.w(TAG, "installd not ready"); SystemClock.sleep(1000); } } 
  • 繼續看startBootstrapServices方法:
    • 這段程式碼主要是用於啟動ActivityManagerService服務,併為其設定SysServiceManager和Installer。ActivityManagerService是系統中一個非常重要的服務,Activity,service,Broadcast,contentProvider都需要通過其餘系統互動。
    // Activity manager runs the show.
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    
  • 首先看一下Lifecycle類的定義:
    • 可以看到其實ActivityManagerService的一個靜態內部類,在其構造方法中會建立一個ActivityManagerService,通過剛剛對Installer服務的分析我們知道,SystemServiceManager的startService方法會呼叫服務的onStart()方法,而在Lifecycle類的定義中我們看到其onStart()方法直接呼叫了mService.start()方法,mService是Lifecycle類中對ActivityManagerService的引用
    public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; public Lifecycle(Context context) { super(context); mService = new ActivityManagerService(context); } @Override public void onStart() { mService.start(); } public ActivityManagerService getService() { return mService; } } 

4.3 啟動部分服務

  • 啟動PowerManagerService服務:
    • 啟動方式跟上面的ActivityManagerService服務相似都會呼叫其構造方法和onStart方法,PowerManagerService主要用於計算系統中和Power相關的計算,然後決策系統應該如何反應。同時協調Power如何與系統其它模組的互動,比如沒有使用者活動時,螢幕變暗等等。
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    
    • 然後是啟動LightsService服務
      • 主要是手機中關於閃光燈,LED等相關的服務;也是會呼叫LightsService的構造方法和onStart方法;
      mSystemServiceManager.startService(LightsService.class);
      
    • 然後是啟動DisplayManagerService服務
      • 主要是手機顯示方面的服務
      mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
      
  • 然後是啟動PackageManagerService,該服務也是android系統中一個比較重要的服務
    • 包括多apk檔案的安裝,解析,刪除,解除安裝等等操作。
    • 可以看到PackageManagerService服務的啟動方式與其他服務的啟動方式有一些區別,直接呼叫了PackageManagerService的靜態main方法
    Slog.i(TAG, "Package Manager");
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    
    • 看一下其main方法的具體實現:
      • 可以看到也是直接使用new的方式建立了一個PackageManagerService物件,並在其構造方法中初始化相關變數,最後呼叫了ServiceManager.addService方法,主要是通過Binder機制與JNI層互動
    public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); ServiceManager.addService("package", m); return m; } 
  • 然後檢視startCoreServices方法:
    • 可以看到這裡啟動了BatteryService(電池相關服務),UsageStatsService,WebViewUpdateService服務等。
    private void startCoreServices() {
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
    
        // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Update after UsageStatsService is available, needed before performBootDexOpt. mPackageManagerService.getUsageStatsIfNoPackageUsageInfo(); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); } 

總結:

  • SystemServer程序是android中一個很重要的程序由Zygote程序啟動;
  • SystemServer程序主要用於啟動系統中的服務;
  • SystemServer程序啟動服務的啟動函式為main函式;
  • SystemServer在執行過程中首先會初始化一些系統變數,載入類庫,建立Context物件,建立SystemServiceManager物件等之後才開始啟動系統服務;
  • SystemServer程序將系統服務分為三類:boot服務,core服務和other服務,並逐步啟動
  • SertemServer程序在嘗試啟動服務之前會首先嚐試與Zygote建立socket通訊,只有通訊成功之後才會開始嘗試啟動服務;
  • 建立的系統服務過程中主要通過SystemServiceManager物件來管理,通過呼叫服務物件的構造方法和onStart方法初始化服務的相關變數;
  • 服務物件都有自己的非同步訊息物件,並執行在單獨的執行緒中;

參考部落格

關於其他內容介紹

01.關於部落格彙總連結

02.關於我的部落格