Android 系統開發_啟動階段篇 — 深入鑽研 SystemServer

DeepCoder發表於2019-01-19

前言

SystemServer程式是zygote程式啟動後,主動“分裂”的第一個程式。它負責啟動大量的Android系統核心服務,其重要性不言而喻。一旦該程式崩潰,整個Android系統將重新啟動。

開篇

核心原始碼

關鍵類 路徑
com_android_internal_os_Zygote.cpp frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
AndroidRuntime.cpp frameworks/base/core/jni/AndroidRuntime.cpp
ZygoteInit.java frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Zygote.java frameworks/base/core/java/com/android/internal/os/Zygote.java
ActivityThread.java frameworks/base/core/java/android/app/ActivityThread.java
ContextImpl.java.java frameworks/base/core/java/android/app/ContextImpl.java
LoadedApk.java.java frameworks/base/core/java/android/app/LoadedApk.java
SystemServer.java frameworks/base/services/java/com/android/server/SystemServer.java
RuntimeInit.java frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

概述

       SystemServer是什麼?它是Android Java的兩大支柱之一。另外一個支柱是專門負責孵化Java程式的Zygote(Zygote程式是整個android系統的根程式)。這兩個支柱倒了任何一個,都會導致Android Java的崩潰(所有由Zygote孵化的Java程式都會被銷燬,而SystemServer就是由Zygote孵化而來)。
       若Android Java真的崩潰了,那麼Linux系統中的程式init會重新啟動“兩大支柱”以重建Android Java。
       SystemServer和系統服務有著重要的關係,Android系統中幾乎所有的核心服務都是在這個程式中,如:ActivityManagerService、PowerManagerService和WindowManagerService等。當我們的應用需要使用各種系統服務的時候,其實也是通過與SystemServer程式通訊獲取各種服務物件的控制程式碼,進而執行相應的操作。

Read The Fucking Code

       SystemServer是由Zygote孵化而來的一個程式,通過ps命令,我們發現其程式名為:system_server。

啟動SystemServer程式

在分析zygote程式時,我們知道當zygote程式進入到java世界後,在ZygoteInit.java中,將呼叫startSystemServer函式啟動SystemServer程式,其關鍵程式碼是:

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);                 // fork出system server

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

我們看下forkSystemServer():

// 我們這邊挑出重要程式碼講解,詳細程式碼分析請參考Zygote篇
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
        parsedArgs.uid, parsedArgs.gid,
        parsedArgs.gids,
        parsedArgs.debugFlags,
        null,
        parsedArgs.permittedCapabilities,
        parsedArgs.effectiveCapabilities);

老樣子,原始碼繼續跟下去:

    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, debugFlags);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

容易看出,該函式通過呼叫native方法,完成實際的建立操作。該Native方法定義於frameworks/base/core/jni/com_android_internal_os_Zygote.cpp中。 我們來看看對應的native函式。

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
        
  // 進行實際的“分裂”工作
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL, NULL);
  if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      
      // 這裡SystemServer程式已經建立出來,pid > 0 說明在父程式中
      // 將子程式SystemServer的pid存在zygote程式的全域性變數中
      gSystemServerPid = pid;
      
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven`t published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          // 小概率,SystemServer程式剛建立,就crash;此時需要重啟zygote
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }

      // Assign system_server to the correct memory cgroup.
      if (!WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
        ALOGE("couldn`t write %d to /dev/memcg/system/tasks", pid);
      }
  }
  return pid;
}

上述程式碼中,實際的“分裂”工作,由函式ForAndSpecializeCommon完成。

// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jintArray fdsToIgnore,
                                     jstring instructionSet, jstring dataDir) {
  SetSigChldHandler();               // 註冊訊號監聽器
  ... ...

  pid_t pid = fork();

  if (pid == 0) {
    ... ...                          // 根據傳入引數進行對應的處理,例如設定程式名,設定各種id(使用者id,組id)等

    UnsetSigChldHandler();           // 反註冊掉訊號監聽器
    ... ...
    
  } else if (pid > 0) { 
    ... ...
    
  }
  return pid;
}

從上面的程式碼可以看出,ForkAndSpecializeCommon最終是通過fork的方式,分裂出子程式。
這裡需要關注一下的是,在zygote程式fork之前,呼叫SetSigChldHandler函式註冊了一個子程式訊號監聽器。由於子程式共享父程式中的堆及棧資訊,因此在子程式中也會有相應的訊號處理器。
為了避免該訊號監聽器對子程式的影響,可以看到在子程式中進行了UnsetSigChldHandler的操作。

分別看一下SetSigChldHandler和UnsetSigChldHandler所作工作!

SetSigChldHandler

我們看看SetSigChldHandler進行了哪些操作。

// Configures the SIGCHLD handler for the zygote process. This is configured
// very late, because earlier in the runtime we may fork() and exec()
// other processes, and we want to waitpid() for those rather than
// have them be harvested immediately.
//
// This ends up being called repeatedly before each fork(), but there`s
// no real harm in that.
static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;

  // 該訊號監聽器關注子程式結束,對應的處理函式為SigChldHandler
  int err = sigaction(SIGCHLD, &sa, NULL);
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

從上面的程式碼可以看出,SetSigChldHandler函式將註冊一個訊號處理器,來監聽子程式的死亡。當子程式死亡後,利用SigChldHandler進行操作。需要注意的是,zygote的訊號監聽器,關注的是zygote所有的子程式,而不只是SystemServer程式(每次建立一個新的程式時,zygote都會註冊對應的監聽器)。

那就繼續分析一下SigChldHandler吧:

static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;
  ... ...
  
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    // 通過status判斷子程式結束的原因,並列印相應的log
    ... ...
  
    // If the just-crashed process is the system_server, bring down zygote
    // so that it is restarted by init and system server will be restarted
    // from there.
    if (pid == gSystemServerPid) {     // 上文已經介紹過,gSystemServerPid中記錄了SystemServer的pid
      ... ...
      
      kill(getpid(), SIGKILL);         // 如果結束的子程式為SystemServer,Zygote也將結束自己
    }
  }
  ... ...
  
}

發現沒?所有zygote的子程式中,zygote只關心了SystemServer的死活。當其它子程式crash時,zygote只列印了log資訊。

UnsetSigChldHandler

最後看看UnsetSigChldHandler函式:

// Sets the SIGCHLD handler back to default behavior in zygote children.
static void UnsetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_DFL;

  int err = sigaction(SIGCHLD, &sa, NULL);
  if (err < 0) {
    ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno));
  }
}

SystemServer工作流程

在分析zygote程式時,我們知道當ZygoteInit.java的startSystemServer函式,通過fork建立出SystemServer程式後,SystemServer程式呼叫handleSystemServerProcess函式,開始執行自己的工作。

handleSystemServerProcess

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();               // 關閉從zygote程式那裡繼承下來server socket
            return handleSystemServerProcess(parsedArgs);
        }

接下來,我們來看看handleSystemServerProcess函式的主要內容。

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        // 載入SystemServer對應的檔案
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
            ... ...

        if (parsedArgs.invokeWith != null) {
            ... ...
        } else {
            // 利用systemServerClass對應的路徑構建對應的ClassLoader
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            // 將剩餘引數及classLoader遞交給ZygoteInit的zygoteInit函式
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

從上面的程式碼可以看出,接下來的流程進入到ZygoteInit的zygoteInit函式。zygoteInit函式將根據classLoader和引數,完成不同程式所需要的初始化工作(SystemServer程式與zygote的其它子程式均將使用zygoteInit函式)。

zygoteInit

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

commonInit

commonInit主要進行一些常規初始化。由於自己是做通訊的,所以比較關注的是建立UA(user agent): frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

    protected static final void commonInit() {

        ... ...

        /*
         * Sets the default HTTP User-Agent used by HttpURLConnection.
         */
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        ... ...
    }

User-Agent是Http協議中的一部分,屬於頭域的組成部分,是一種向訪問網站提供你所使用的瀏覽器型別、作業系統、瀏覽器核心等資訊的標識。通過這個標識,使用者所訪問的網站可以顯示不同的排版,從而為使用者提供更好的體驗或者進行資訊統計。

nativeZygoteInit

函式nativeZyoteInit實現在frameworks/base/core/jni/AndroidRuntime.cpp中,主要用於為Binder通訊打下基礎。

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

這裡需要關注的是,SystemServer程式中的gCurRuntime指的是什麼呢?

實際上在zygote程式啟動時,在app_main.cpp的main函式中,建立出了AppRuntime:

int main(int argc, char* const argv[])
{
    ........
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ........

AppRuntime定義如下:

class AppRuntime : public AndroidRuntime
{
public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL)
    {
    }
    ... ...
}

看看AppRuntime的父類AndroidRuntime:

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
{
    SkGraphics::Init();

    // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20);

    assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this;
}

從程式碼可以看出,AndroidRuntime初始化時定義了gCurRuntime。gCurRuntime指向物件自身,也就是說gCurRuntime指向的是AppRuntime物件。

由於SystemServer程式由zygote程式fork出來,於是system server程式中也存在gCurRuntime物件,型別為AppRuntime。至此我們知道,Native函式中gCurRuntime->onZygoteInit將呼叫AppRuntime中的onZygoteInit。

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.
");
        proc->startThreadPool();
    }

onZygoteInit的用途是啟動一個執行緒,用於binder通訊。

applicationInit

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        // 設定一些程式退出的處理策略,可用堆疊上限等
        ... ...
            
        // Remaining arguments are passed to the start class`s static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

繼續分析findStaticMain函式:

    private static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        // className為進行初始化工作的程式類名
        // 在SystemServer初始化時,為com.android.server.SystemServer
        Class<?> cl;

        try {
            // 下面就是通過反射得到對應類的main方法
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        ... ...

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception`s run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);    // 捕獲MethodAndArgsCaller異常
    }

main函式

接下來就進入了SystemServer.java的main函式,其程式碼如下:

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();        // 建立並執行,簡單粗暴!
    }

這裡比較簡單,只是new出一個SystemServer物件並執行其run方法:

    private void run() {
        try {
            traceBeginAndSlog("InitBeforeStartServices");
            // If a device`s clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it shortly.
            // 如何系統時鐘早於1970年,則設定系統始終從1970年開始
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                // private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }
            
            ... ...
            
            // If the system has "persist.sys.language" and friends set, replace them with
            // "persist.sys.locale". Note that the default locale at this point is calculated
            // using the "-Duser.locale" command line flag. That flag is usually populated by
            // AndroidRuntime using the same set of system properties, but only the system_server
            // and system apps are allowed to set them.
            //
            // NOTE: Most changes made here will need an equivalent change to
            // core/jni/AndroidRuntime.cpp
            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", "");
            }
            
            // Mmmmmm... more memory!
            // 清除vm記憶體增長上限,由於啟動過程需要較多的虛擬機器記憶體空間
            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.
            // 設定堆疊利用率,GC後會重新計算堆疊空間大小
            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);                                             
            
            ... ...
            
            // Initialize native services.
            // 載入動態庫libandroid_services.so
            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.
            // 在SystemServer程式中也需要建立Context物件,初始化系統上下文
            createSystemContext();                                                         
            
            // Create the system service manager.
            // 通過SystemServiceManager的構造方法建立了一個新的SystemServiceManager物件
            mSystemServiceManager = new SystemServiceManager(mSystemContext);  
            
            // SystemServer程式主要是用來構建系統各種service服務,而SystemServiceManager就是這些服務的管理物件            
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);           
            
            // 將SystemServiceManager物件儲存到SystemServer程式中的一個資料結構中            
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);   
            
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {                              // 分種類啟動不同的system service
            // 主要用於啟動系統Boot級服務
            startBootstrapServices(); 
            
            // 主要用於啟動系統核心的服務            
            startCoreServices();    
            
            // 主要用於啟動一些非緊要或者非需要及時啟動的服務            
            startOtherServices();     
            
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        
        ... ...
        
        // Loop forever.
        // //啟動looper,以處理到來的訊息,一直迴圈執行
        Looper.loop();                                                                       
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

       以上就是SystemServer的run函式整個流程,我們做個簡化,如下:

    private void run() {
        try {
            // Initialize the system context.
            createSystemContext();                                            // ??? 01.初始化系統上下文 ???
            
            // Create the system service manager.                                          
            mSystemServiceManager = new SystemServiceManager(mSystemContext); // ??? 02.建立系統服務管理 ???
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);                  
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);   
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.                                                    // ??? 03.啟動系統各種服務 ???
        try {
            startBootstrapServices();                                         // 啟動引導服務
            startCoreServices();                                              // 啟動核心服務
            startOtherServices();                                             // 啟動其他服務
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        
        ... ...
        
        // Loop forever.
        Looper.loop();                                                        // 一直迴圈執行  
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

       OK,接下來我們針對SystemServer所做的三部分工作,進行逐個分析!


初始化上下文

    private void run() {
        try {
            // Initialize the system context.
            createSystemContext();                                            // ??? 01.初始化系統上下文 ???

       跟蹤createSystemContext函式:

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

       跟蹤systemMain函式:

    public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);                                   // 對於低記憶體的裝置,禁用硬體加速
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }
    
    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();                   // 使用單例模式獲得一個ResourcesManager例項
    }

       繼續跟蹤attach函式:

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ... ...
        } else {
            // Don`t set application object here -- if the system crashes,
            // we can`t display an alert, we just want to die die die.
            // 設定SystemServer程式在DDMS中顯示的名字為"system_process" 
            android.ddm.DdmHandleAppName.setAppName("system_process",                      
                    UserHandle.myUserId());         // 如不設定,則顯示"?",無法除錯該程式
            try {
                mInstrumentation = new Instrumentation();
                // 首先通過getSystemContext()建立系統上下文,然後建立應用上下文
                ContextImpl context = ContextImpl.createAppContext(                        
                        this, getSystemContext().mPackageInfo);
                // 建立Application
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                // 呼叫Application的onCreate()                
                mInitialApplication.onCreate();                                            
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        // 新增回撥
        ViewRootImpl.addConfigCallback(configChangedCallback);                             
    }

可以看出,attach主要做了三件事:
       (1)建立系統上下文:getSystemContext() –> createSystemContext() –> new ContextImpl()
       (2)建立應用上下文 ContextImpl.createAppContext() –> new ContextImpl()
       (3)新增回撥configChangedCallback到ViewRootImpl


建立系統上下文

getSystemContext():

    public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }

跟蹤createSystemContext函式:

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        // 這邊new出來的LoadedApk將作為建立應用上下文的引數packageInfo
        LoadedApk packageInfo = new LoadedApk(mainThread);             
        // ContextImpl()建立系統上下文         
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,                 
                null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    }

建立應用上下文

ContextImpl.createAppContext():

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        // ContextImpl()建立應用上下文
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,                 
                null);
        context.setResources(packageInfo.getResources());
        return context;
    }

我們可以看出:new ContextImpl時,系統上下文和應用上下文的引數是一樣的,createAppContext()中的引數packageInfo,就是createSystemContext()中new的LoadedApk。
建立完成之後,系統上下文賦值給了ActivityThread的成員變數mSystemContext,而應用上下文只是作為函式中的區域性變數臨時使用。
我們回顧一下建立上下文的程式碼:

            try {
                mInstrumentation = new Instrumentation();
                // 首先通過getSystemContext()建立系統上下文,然後建立應用上下文
                ContextImpl context = ContextImpl.createAppContext(                        
                        this, getSystemContext().mPackageInfo);
                // 建立Application
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);    
                // 呼叫Application的onCreate()
                mInitialApplication.onCreate();                                            

接下來就繼續看下建立Application的流程:

建立Application

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;

        String appClass = mApplicationInfo.className;
        // 引數forceDefaultAppClass為true 
        if (forceDefaultAppClass || (appClass == null)) {                                  
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            // 此LoadedApk物件是createSystemContext時new的,mPackageName="android"
            if (!mPackageName.equals("android")) {                                         
                initializeJavaContextClassLoader();
            }
            // 又建立了一個區域性應用上下文
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);  
            // 建立Application 
            app = mActivityThread.mInstrumentation.newApplication(                         
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ... ...
        }

        // 將前面建立的app新增到應用列表
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        
        ... ...

        return app;
    }

這一步主要建立了一個ActivityThread物件,然後執行了該物件的attach()方法,attach()方法中建立了系統上下文mSystemContext(型別為ContextImpl),並建立Application物件。
系統上下文中,new了一個LoadedApk的成員變數,並將ActivityThread物件傳給LoadedApk成員,後面的Application物件就是LoadedApk使用ActivityThread建立的,LoadedApk建立了Application物件後,將Application新增到ActivityThread的應用列表中。

建立系統服務管理

我們回顧下相關程式碼:

            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

這一步比較簡單,只是new了一個SystemServiceManager,並將其新增到本地服務列表中。mSystemContext為第一步中建立的系統上下文。本地服務列表是以類為key儲存的一個列表,即列表中某種型別的物件最多隻能有一個。

public class SystemServiceManager {
    ... ...

    // Services that should receive lifecycle events.
    // 系統服務列表,系統服務必須繼承SystemService
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

    // 當前處於開機過程的哪個階段,SystemService.PHASE_XXXXX
    private int mCurrentPhase = -1;

    SystemServiceManager(Context context) {
        mContext = context;
    }

    /**
     * Starts a service by class name.
     *
     * @return The service instance.
     */
    @SuppressWarnings("unchecked")
    // 通過類名啟動系統服務,可能會找不到類而拋異常
    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        try {
            serviceClass = (Class<SystemService>)Class.forName(className);
        } catch (ClassNotFoundException ex) {
            Slog.i(TAG, "Starting " + className);
            throw new RuntimeException("Failed to create service " + className
                    + ": service class not found, usually indicates that the caller should "
                    + "have called PackageManager.hasSystemFeature() to check whether the "
                    + "feature is available on this device before trying to start the "
                    + "services that implement it", ex);
        }
        return startService(serviceClass);
    }

    /**
     * Creates and starts a system service. The class must be a subclass of
     * {@link com.android.server.SystemService}.
     *
     * @param serviceClass A Java class that implements the SystemService interface.
     * @return The service instance, never null.
     * @throws RuntimeException if the service fails to start.
     */
    @SuppressWarnings("unchecked")
    // 建立並啟動系統服務,系統服務類必須繼承SystemService
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + 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);
            }

            startService(service);
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

    /**
     * Starts the specified boot phase for all system services that have been started up to
     * this point.
     *
     * @param phase The boot phase to start.
     */
    // 通知系統服務到了開機的哪個階段,會遍歷呼叫所有系統服務的onBootPhase()函式
    public void startBootPhase(final int phase) {
        if (phase <= mCurrentPhase) {
            throw new IllegalArgumentException("Next phase must be larger than previous");
        }
        mCurrentPhase = phase;

        Slog.i(TAG, "Starting phase " + mCurrentPhase);
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
            final int serviceLen = mServices.size();
            for (int i = 0; i < serviceLen; i++) {
                final SystemService service = mServices.get(i);
                long time = SystemClock.elapsedRealtime();
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
                try {
                    service.onBootPhase(mCurrentPhase);
                } catch (Exception ex) {
                    throw new RuntimeException("Failed to boot service "
                            + service.getClass().getName()
                            + ": onBootPhase threw an exception during phase "
                            + mCurrentPhase, ex);
                }
                warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

啟動系統各種服務

    try {
        startBootstrapServices();                 // 啟動引導服務
        startCoreServices();                      // 啟動核心服務
        startOtherServices();                     // 啟動其他服務

啟動引導服務

首先來看下startBootstrapServices():

    private void startBootstrapServices() {
        ... ...

        // 啟動Installer服務,阻塞等待與installd建立socket通道
        Installer installer = mSystemServiceManager.startService(Installer.class);

        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);

        // 啟動ActivityManagerService(AMS),關於AMS我們後面會詳細講解
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // 啟動PowerManagerService
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // PowerManagerService就緒,AMS初始化電源管理
        mActivityManagerService.initPowerManagement();

        // Bring up recovery system in case a rescue party needs a reboot
        if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
            traceBeginAndSlog("StartRecoverySystemService");
            mSystemServiceManager.startService(RecoverySystemService.class);
            traceEnd();
        }

        RescueParty.noteBoot(mSystemContext);

        // 啟動LightsService
        mSystemServiceManager.startService(LightsService.class);

        // 啟動DisplayManagerService(before package manager)
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        // 初始化package manager之前,需要預設顯示。阻塞,10s超時,see DisplayManagerService.onBootPhase()
        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.
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_package_manager_init_start",
                    (int) SystemClock.elapsedRealtime());
        }

        // 啟動PackageManagerService
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

        ... ...

        // 將UserManagerService新增到服務列表,該服務是在PackageManagerService中初始化的        
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);


        // Initialize attribute cache used to cache resources from packages.
        // 初始化用來快取包資源的屬性快取
        AttributeCache.init(mSystemContext);

        // Set up the Application instance for the system process and get started.
        // 設定AMS
        mActivityManagerService.setSystemProcess();

        ... ...

        // The sensor service needs access to package manager service, app ops
        // service, and permissions service, therefore we start it after them.
        // Start sensor service in a separate thread. Completion should be checked
        // before using it.
        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
            TimingsTraceLog traceLog = new TimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(START_SENSOR_SERVICE);
            // 啟動感測器服務(native 服務,依賴PackageManagerService、AppOpsService、permissions service)
            startSensorService();
            traceLog.traceEnd();
        }, START_SENSOR_SERVICE);
    }

這步首先等待installd啟動完成,然後啟動一些相互依賴的關鍵服務。所建立的服務:ActivityManagerService,PowerManagerService,LightsService,DisplayManagerService,PackageManagerService,UserManagerService,sensor服務。

啟動核心服務

接下來繼續看下核心服務:

    /**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        mSystemServiceManager.startService(DropBoxManagerService.class);

        // 啟動BatteryService,用於統計電池電量,需要LightService
        mSystemServiceManager.startService(BatteryService.class);

        // 啟動UsageStatsService,用於統計應用使用情況
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));

        // 啟動WebViewUpdateService
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
    }

啟動服務DropBoxManagerService、BatteryService,UsageStatsService,WebViewUpdateService。

啟動其他服務

程式碼很長(1200多行…),但是邏輯簡單,主要是啟動各種服務。

    /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored
     * and organized.
     */
    private void startOtherServices() {
        ... ...

        try {

            ... ...
            traceBeginAndSlog("StartSchedulingPolicyService");   // 排程策略
            ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
            traceEnd();

            traceBeginAndSlog("StartTelecomLoaderService");
            mSystemServiceManager.startService(TelecomLoaderService.class);
            traceEnd();

            traceBeginAndSlog("StartTelephonyRegistry");         // 提供電話註冊、管理服務,可以獲取電話的連結狀態、訊號強度等
            telephonyRegistry = new TelephonyRegistry(context);
            ServiceManager.addService("telephony.registry", telephonyRegistry);
            traceEnd();

            traceBeginAndSlog("StartEntropyMixer");              // 隨機數相關,原名EntropyService
            mEntropyMixer = new EntropyMixer(context);
            traceEnd();
            
            mContentResolver = context.getContentResolver();

            // The AccountManager must come before the ContentService
            traceBeginAndSlog("StartAccountManagerService");     // 提供所有賬號、密碼、認證管理等等的服務
            mSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS);
            traceEnd();

            traceBeginAndSlog("StartContentService");            // ContentProvider服務,提供跨程式資料交換
            mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
            traceEnd();

            traceBeginAndSlog("InstallSystemProviders");
            mActivityManagerService.installSystemProviders();
            traceEnd();

            traceBeginAndSlog("StartVibratorService");           // 振動器服務
            vibrator = new VibratorService(context);
            ServiceManager.addService("vibrator", vibrator);
            traceEnd();

            ... ...
            
            traceBeginAndSlog("InitWatchdog");                   // 初始化 Watchdog
            final Watchdog watchdog = Watchdog.getInstance();
            watchdog.init(context, mActivityManagerService);
            traceEnd();

            traceBeginAndSlog("StartInputManagerService");       // 事件傳遞分發服務
            inputManager = new InputManagerService(context);
            traceEnd();

            traceBeginAndSlog("StartWindowManagerService");      // 視窗管理服務
            // WMS needs sensor service ready
            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
            mSensorServiceStart = null;
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
            traceEnd();
            ... ...
        }
        
        ... ...
    
        LockSettingsService               // 螢幕鎖定服務,管理每個使用者的相關鎖屏資訊
        DeviceIdleController              // Doze模式的主要驅動,參考“深入Android `M` Doze”
        DevicePolicyManagerService        // 提供一些系統級別的設定及屬性
        StatusBarManagerService           // 狀態列管理服務
        ClipboardService                  // 系統剪下板服務
        NetworkManagementService          // 網路管理服務
        TextServicesManagerService        // 文字服務,例如文字檢查等
        NetworkScoreService               // 網路評分服務
        NetworkStatsService               // 網路狀態服務
        NetworkPolicyManagerService       // 網路策略服務
        WifiP2pService                    // Wifi Direct服務
        WifiService                       // Wifi服務
        WifiScanningService               // Wifi掃描服務
        RttService                        // Wifi相關
        EthernetService                   // 乙太網服務
        ConnectivityService               // 網路連線管理服務
        NsdService                        // 網路發現服務
        ... ...

        NotificationManagerService        // 通知欄管理服務
        DeviceStorageMonitorService       // 磁碟空間狀態檢測服務
        LocationManagerService            // 位置服務,GPS、定位等
        CountryDetectorService            // 檢測使用者國家
        SearchManagerService              // 搜尋管理服務
        DropBoxManagerService             // 用於系統執行時日誌的儲存於管理
        WallpaperManagerService           // 桌布管理服務
        AudioService                      // AudioFlinger的上層管理封裝,主要是音量、音效、聲道及鈴聲等的管理
        DockObserver                      // 如果系統有個座子,當手機裝上或拔出這個座子的話,就得靠他來管理了
        WiredAccessoryManager             // 監視手機和底座上的耳機
        UsbService                        // USB服務
        SerialService                     // 串列埠服務
        TwilightService                   // 指出使用者當前所在位置是否為晚上,被UiModeManager等用來調整夜間模式。
        BackupManagerService              // 備份服務
        AppWidgetService                  // 提供Widget的管理和相關服務
        VoiceInteractionManagerService    // 語音互動管理服務
        DiskStatsService                  // 磁碟統計服務,供dumpsys使用
        SamplingProfilerService           // 用於耗時統計等
        NetworkTimeUpdateService          // 監視網路時間,當網路時間變化時更新本地時間。
        CommonTimeManagementService       // 管理本地常見的時間服務的配置,在網路配置變化時重新配置本地服務。
        CertBlacklister                   // 提供一種機制更新SSL certificate blacklist
        DreamManagerService               // 螢幕保護
        AssetAtlasService                 // 負責將預載入的bitmap組裝成紋理貼圖,生成的紋理貼圖可以被用來跨程式使用,以減少記憶體。
        PrintManagerService               // 列印服務
        HdmiControlService                // HDMI控制服務
        FingerprintService                // 指紋服務
        ... ...
    }

以上程式碼僅按順序列出啟動的服務,有些服務根據條件,如是否是工廠模式,或系統屬性配置,選擇性啟動,這裡不考慮條件判斷和異常處理。

自此,SystemServer相關原始碼分析完畢。

參考Blog

  1. https://blog.csdn.net/kingodc…
  2. https://blog.csdn.net/qq_2354…
  3. https://blog.csdn.net/gaugame…

相關文章