相關文章
Android系統架構與系統原始碼目錄
Android系統啟動流程(一)解析init程式啟動過程
Android系統啟動流程(二)解析Zygote程式啟動過程
前言
上一篇我們學習了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.啟動各種系統服務。
歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。