Android系統啓動流程(三)解析SyetemServer進程啓動過程

相關文章
Android系統架構與系統源碼目錄
Android系統啓動流程(一)解析init進程啓動過程
Android系統啓動流程(二)解析Zygote進程啓動過程javascript

前言

上一篇咱們學習了Zygote進程,而且知道Zygote進程啓動了SyetemServer進程,那麼這一篇咱們就來學習Android7.0版本的SyetemServer進程。java

1.Zygote啓動SyetemServer進程

在上一篇文章中咱們講到在ZygoteInit.java的startSystemServer函數中啓動了SyetemServer進程,以下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaandroid

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
     ...
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }複製代碼

在startSystemServer函數中調用handleSystemServerProcess來啓動SyetemServer進程。數組

2.SyetemServer進程啓動過程

handleSystemServerProcess函數的代碼以下所示。微信

private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        closeServerSocket();//1
      ...
        if (parsedArgs.invokeWith != null) {
           ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//2
        }
    }複製代碼

SyetemServer進程是複製了Zygote進程的地址空間,所以也會獲得Zygote進程建立的Socket,這個Socket對於SyetemServer進程沒有用處,所以,須要註釋1處的代碼來關閉該Socket。在註釋2處調用RuntimeInit的zygoteInit函數,它的代碼以下所示。架構

frameworks/base/core/java/com/android/internal/os/RuntimeInit.javaapp

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);//2
    }複製代碼

註釋1處調用nativeZygoteInit函數,一看函數的名稱就知道調用Native層的代碼。socket

啓動Binder線程池

接着咱們來查看nativeZygoteInit函數對用的JNI文件,以下所示。
frameworks/base/core/jni/AndroidRuntime.cpp函數

static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};複製代碼

經過JNI的gMethods數組,能夠看出nativeZygoteInit函數對應的是JNI文件AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函數:post

...
static AndroidRuntime* gCurRuntime = NULL;
...
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}複製代碼

這裏gCurRuntime是AndroidRuntime類型的指針,AndroidRuntime的子類AppRuntime在app_main.cpp中定義,咱們來查看AppRuntime的onZygoteInit函數,代碼以下所示。
frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//1
    }複製代碼

註釋1處的代碼用來啓動一個Binder線程池,這樣SyetemServer進程就可使用Binder來與其餘進程進行通訊了。看到這裏咱們知道RuntimeInit.java的nativeZygoteInit函數主要作的就是啓動Binder線程池。

invokeStaticMain

咱們再回到RuntimeInit.java的代碼,在註釋2處調用了applicationInit函數,代碼以下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }複製代碼

applicationInit函數中主要調用了invokeStaticMain函數:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
        try {
            cl = Class.forName(className, true, classLoader);//1
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });//2
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
    }複製代碼

註釋1處className爲「com.android.server.SystemServer",所以經過反射返回的cl爲SystemServer類。註釋2處找到SystemServer中的main函數。在註釋3處將找到的main函數傳入到MethodAndArgsCaller異常中並拋出該異常。截獲MethodAndArgsCaller異常的代碼在ZygoteInit.java的main函數中,以下所示。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
       ...
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();//1
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }複製代碼

在註釋1處調用了MethodAndArgsCaller的run函數:

public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
         ...
        }
    }
}複製代碼

這裏mMethod指的就是SystemServer的main函數,所以main函數被動態調用。

3.解析SyetemServer進程

咱們先來查看SystemServer的main函數:
frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
        new SystemServer().run();
    }複製代碼

main函數中只調用了SystemServer的run函數,以下所示。

private void run() {
        ...
            System.loadLibrary("android_servers");//1
        ...
            mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        ...    
         try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            startBootstrapServices();//3
            startCoreServices();//4
            startOtherServices();//5
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        ...
    }複製代碼

run函數代碼不少,關鍵就是在註釋1處加載了libandroid_servers.so。接下來在註釋2處建立SystemServiceManager,它會對系統的服務進行建立、啓動和生命週期管理。啓動系統的各類服務,在註釋3中的startBootstrapServices函數中用SystemServiceManager啓動了ActivityManagerService、PowerManagerService、PackageManagerService等服務。在註釋4處的函數中則啓動了BatteryService、UsageStatsService和WebViewUpdateService。註釋5處的startOtherServices函數中則啓動了CameraService、AlarmManagerService、VrManagerService等服務,這些服務的父類爲SystemService。從註釋三、四、5的函數能夠看出,官方把系統服務分爲了三種類型,分別是引導服務、核心服務和其餘服務,其中其餘服務爲一些非緊要和一些不須要當即啓動的服務。系統服務大約有80多個,這裏列出部分系統服務以及它們的做用以下表所示:

引導服務 做用
Installer 系統安裝apk時的一個服務類,啓動完成Installer服務以後才能啓動其餘的系統服務
ActivityManagerService 負責四大組件的啓動、切換、調度。
PowerManagerService 計算系統中和Power相關的計算,而後決策系統應該如何反應
LightsService 管理和顯示背光LED
DisplayManagerService 用來管理全部顯示設備
UserManagerService 多用戶模式管理
SensorService 爲系統提供各類感應器服務
PackageManagerService 用來對apk進行安裝、解析、刪除、卸載等等操做
核心服務
BatteryService 管理電池相關的服務
UsageStatsService 收集用戶使用每個APP的頻率、使用時常
WebViewUpdateService WebView更新服務
其餘服務
CameraService 攝像頭相關服務
AlarmManagerService 全局定時器管理服務
InputManagerService 管理輸入事件
WindowManagerService 窗口管理服務
VrManagerService VR模式管理服務
BluetoothService 藍牙管理服務
NotificationManagerService 通知管理服務
DeviceStorageMonitorService 存儲相關管理服務
LocationManagerService 定位管理服務
AudioService 音頻相關管理服務
... ....

好比要啓動PowerManagerService則會調用以下代碼:

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);複製代碼

SystemServiceManager的startService函數啓動了PowerManagerService,startService函數以下所示。

frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public <T extends SystemService> T startService(Class<T> serviceClass) {
  ...
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);//1
            } catch (InstantiationException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            }
...
            // Register it.
            mServices.add(service);//2
            // Start it.
            try {
                service.onStart();
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }複製代碼

註釋1處的代碼用來建立SystemService,這裏的SystemService是PowerManagerService,在註釋2處將PowerManagerService添加到mServices中,這裏mServices是一個存儲SystemService類型的ArrayList。接着調用PowerManagerService的onStart函數啓動PowerManagerService並返回,這樣就完成了PowerManagerService啓動的過程。
除了用mSystemServiceManager的startService函數來啓動系統服務外,也能夠經過以下形式來啓動系統服務,以PackageManagerService爲例:

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);複製代碼

直接調用了PackageManagerService的main函數:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // Self-check for initial settings.
    PackageManagerServiceCompilerMapping.checkProperties();
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);//1
    m.enableSystemUserPackages();
    // Disable any carrier apps. We do this very early in boot to prevent the apps from being
    // disabled after already being started.
    CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
            UserHandle.USER_SYSTEM);
    ServiceManager.addService("package", m);//2
    return m;
}複製代碼

註釋1處直接建立PackageManagerService並在註釋2處將PackageManagerService註冊到ServiceManager中,ServiceManager用來管理系統中的各類Service,用於系統C/S架構中的Binder機制通訊:Client端要使用某個Service,則須要先到ServiceManager查詢Service的相關信息,而後根據Service的相關信息與Service所在的Server進程創建通信通路,這樣Client端就可使用Service了。還有的服務是直接註冊到ServiceManager中的,以下所示。

frameworks/base/services/java/com/android/server/SystemServer.java

telephonyRegistry = new TelephonyRegistry(context);
  ServiceManager.addService("telephony.registry", telephonyRegistry);複製代碼

4.總結SyetemServer進程

SyetemServer在啓動時作了以下工做:
1.啓動Binder線程池,這樣就能夠與其餘進程進行通訊。
2.建立SystemServiceManager用於對系統的服務進行建立、啓動和生命週期管理。
3.啓動各類系統服務。


歡迎關注個人微信公衆號,第一時間得到博客更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,便可關注。

相關文章
相關標籤/搜索