Android SyetemServer程序啟動過程(基於7.0 N版本原始碼)
前言
上一篇我們學習了Zygote程序,並且知道Zygote程序啟動了SyetemServer程序,那麼這一篇我們就來學習Android7.0版本的SyetemServer程序的啟動過程。
1.Zygote啟動SyetemServer程序
在上一篇文章中我們講到在ZygoteInit.java的startSystemServer函式中啟動了SyetemServer程序,如下所示。frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
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.java
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層的程式碼。
啟動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函式:
... 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。從註釋3、4、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.啟動各種系統服務。