SystemServer進程在Android中的角色
SystemServer進程是Android系統(tǒng)的核心之一蚂且,大部分Android提供的服務(wù)都運行在這個進程里隘梨,如AMS舌菜,PMS,等六十多種服務(wù)场梆。我們都知道Android的應(yīng)用進程沒有權(quán)限直接訪問設(shè)備的底層資源,只能通過SystemServer中的服務(wù)代理訪問纯路,這樣做的目的是為了防止應(yīng)用進程對系統(tǒng)造成破壞或油。
SystemServer進程的創(chuàng)建過程
一、 創(chuàng)建SystemServer進程
ZygoteInit類的main()方法里調(diào)用startSystemServer()方法來啟動SystemServer驰唬。
//位于ZygoteInit.java
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
// 準備啟動參數(shù)
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,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
...
int pid;
try {
...
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// 進入子進程system_server
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 完成system_server進程剩余的工作
handleSystemServerProcess(parsedArgs);
}
return true;
}
在startSystemServer()方法中顶岸,主要做了3件事:
1.為SystemServer準備啟動參數(shù)。
SystemServer進程的uid和gid都被指定為1000叫编。SystemServer進程的名字是system_server辖佣,其執(zhí)行類是com.android.server.SystemServer。
2.調(diào)用Zygote類的forkSystemServer()來fork出SystemServer子進程搓逾。
forkSystemServer()方法最終會調(diào)用native層的nativeForkSystemServer()函數(shù)卷谈,最終調(diào)用ForkAndSpecializeCommon函數(shù)來執(zhí)行實際的fork操作。
在native層調(diào)用完forkAndSpecializeCommon()函數(shù)后霞篡,如果啟動的是SystemServer世蔗,Zygote會檢查SystemServer是否啟動成功,如果失敗朗兵,Zygote進程會讓進程自己退出污淋,重啟zygote進程。
//位于com_android_internal_os_Zygote.cpp
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) {
// fork子進程
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0) {
// zygote進程檢測子進程是否創(chuàng)建
gSystemServerPid = pid;
int status;
if (waitpid(pid, &status, WNOHANG) == pid) {
// system_server進程死亡后余掖,重啟zygote進程
RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
}
}
return pid;
}
在ForkAndSpecializeCommon()函數(shù)中將調(diào)用fork()函數(shù)來創(chuàng)建子進程之前還調(diào)用了SetSigChldHandler函數(shù)設(shè)置處理SIGCHLD信號的函數(shù)SigChldHandler()寸爆。
static void SigChldHandler(int /*signal_number*/) {
pid_t pid;
...
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
...
if (pid == gSystemServerPid) {
ALOGE("Exit zygote because system server (%d) has terminated", pid);
kill(getpid(), SIGKILL); // 如果死亡的是SystemServer進程,zygote將退出
}
}
...
}
SigChldHandler函數(shù)接收到子進程死亡的信號后盐欺,除了調(diào)用waitpid()來防止子進程變“僵尸”外而昨,還會判斷死亡的子進程是否是SystemServer進程,如果是找田,Zygote進程會“自殺”歌憨,這樣將導(dǎo)致Init進程殺死所有用戶進程并重啟Zygote。整個手機相當于重啟了一扁墩衙,從而達到系統(tǒng)“軟重啟”的目的务嫡。
3.在fork出SystemServer進程后,在fork出的進程中調(diào)用handleSystemServerProcess()來初始化SystemServer進程漆改。
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
// 關(guān)閉父進程zygote復(fù)制而來的Socket
closeServerSocket();
// 接SystemServer進程的umask設(shè)為0077(S_IRWXG|S_IRWXO)心铃,
// 這樣SystemServer創(chuàng)建的文件的屬性就是0077,只有SystemServer進程可以訪問挫剑。
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
// 設(shè)置當前進程名為 "system_server"
Process.setArgV0(parsedArgs.niceName);
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
// 執(zhí)行dex優(yōu)化操作
performSystemServerDexOpt(systemServerClasspath);
}
if (parsedArgs.invokeWith != null) {// invokeWith通常為null
String[] args = parsedArgs.remainingArgs;
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
// 啟動應(yīng)用進程
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
//創(chuàng)建類加載器去扣,并賦予當前線程
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
因為參數(shù)invokeWith通常為null,所以會調(diào)用RuntimeInit.zygoteInit()方法樊破。在zygoteInit()方法中愉棱,它最終會以拋出MethodAndArgsCaller異常的方式返回唆铐,實現(xiàn)真正調(diào)用SystemServer類的main()方法。
二奔滑、SystemServer的初始化
SystemServer是一個java類艾岂,其main()方法中調(diào)用了對象的run()方法。
public static void main(String[] args) {
//先初始化SystemServer對象朋其,再調(diào)用對象的run()方法
new SystemServer().run();
}
private void run() {
try {
//當系統(tǒng)時間比1970年更早王浴,就設(shè)置當前系統(tǒng)時間為1970年
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
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", "");
}
//變更虛擬機的庫文件,對于Android 6.0默認采用的是libart.so
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
mProfilerSnapshotTimer = new Timer();
//system_server每隔1小時采用一次梅猿,并保存結(jié)果到system_server文件
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
VMRuntime.getRuntime().clearGrowthLimit();
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Build.ensureFingerprintProperty();
Environment.setUserRequired(true);
BaseBundle.setShouldDefuse(true);
BinderInternal.disableBackgroundScheduling(true);
BinderInternal.setMaxThreads(sMaxBinderThreads);
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
// 主線程looper就在當前線程運行
Looper.prepareMainLooper();
//加載android_servers.so庫氓辣,該庫包含的源碼在frameworks/base/services/目錄下
System.loadLibrary("android_servers");
// 檢查上次關(guān)機過程是否失敗,該方法可能不會返回
performPendingShutdown();
// 初始化系統(tǒng)上下文
createSystemContext();
//創(chuàng)建系統(tǒng)服務(wù)管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//將mSystemServiceManager添加到本地服務(wù)的成員sLocalServiceObjects
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// 創(chuàng)建并運行所有的Java服務(wù)
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
startBootstrapServices(); //啟動引導(dǎo)服務(wù)
startCoreServices(); //啟動核心服務(wù)
startOtherServices(); //啟動其它服務(wù)
} catch (Throwable ex) {
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// 進入處理消息的循環(huán)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
main()方法的主要是有:
1.調(diào)用時間袱蚓,如果當前系統(tǒng)時間比1970年更早钞啸,就設(shè)置當前系統(tǒng)時間為1970年 。
2.設(shè)置屬性persist.sys.dalvik.vm.lib.2的值為當前虛擬機的運行庫的路徑癞松。
3.調(diào)整虛擬機堆的內(nèi)存爽撒。設(shè)定虛擬機利用率為0.8入蛆。
4.加載android_servers.so庫响蓉。
5.調(diào)用createSystemContext()來獲取Context。
6.創(chuàng)建SystemServiceManager的對象mSystemServiceManager哨毁,這個對象負責系統(tǒng)Service的啟動枫甲。
7.啟動服務(wù)。startBootstrapServices()扼褪,startBootstrapServices()想幻,startBootstrapServices()三大方法。
8.調(diào)用Loop.loop()话浇,進入處理消息的循環(huán)脏毯。
private void createSystemContext() {
//創(chuàng)建ActivityThread對象
ActivityThread activityThread = ActivityThread.systemMain();
//創(chuàng)建ContextImpl、LoadedApk對象
mSystemContext = activityThread.getSystemContext();
//設(shè)置主題
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}
在createSystemContext()方法里幔崖,通過ActivityThread的靜態(tài)方法systemMain()創(chuàng)建了一個activityThread食店。然后調(diào)用它的getSystemContext()方法來獲取系統(tǒng)的Context,最后設(shè)置主題赏寇。
接下來看看systemMain()方法吉嫩。
public static ActivityThread systemMain() {
//對于低內(nèi)存的設(shè)備,禁用硬件加速
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
// 創(chuàng)建ActivityThread
ActivityThread thread = new ActivityThread();
// 創(chuàng)建Application以及調(diào)用其onCreate()方法
thread.attach(true);//代表是系統(tǒng)的應(yīng)用進程
return thread;
}
上面的代碼主要是new了一個ActivityThread對象嗅定。
同樣的我們知道自娩,ActivityThread是應(yīng)用程序的主線程類,該類同時也存在一個main()主方法渠退,zygote進程在啟動過程的最后會在拋出的MethodAndArgsCaller異常中忙迁,通過反射來執(zhí)行ActivityThread類的main()方法脐彩。那么這里為什么要用new來創(chuàng)建ActivityThread對象呢?
實際上SystemServer不僅是一個單純的后臺進程动漾,它也是一個運行著組件Service的進程丁屎,很多系統(tǒng)的對話框就是從SystemServer中顯示出來的,因此旱眯,SystemServer本身也需要一個和APK應(yīng)用類似的上下文環(huán)境晨川,創(chuàng)建ActivityThread是獲取這個環(huán)境的第一步,后面還需要創(chuàng)建SystemContext對象删豺。ActivityThread的attach(boolean)方法中共虑,傳入?yún)?shù)true時,表示是在SystemServer中調(diào)用呀页。如下代碼:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//進入應(yīng)用進程的處理流程
...
} else { //進入系統(tǒng)進程妈拌。該情況只在SystemServer中處理,設(shè)置DDMS時看到的systemserver進程名為system_process
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
// 創(chuàng)建應(yīng)用上下文SystemContext
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
// 創(chuàng)建Application
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
// 調(diào)用Application的onCreate()方法
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
...
}
system為true時蓬蝶,創(chuàng)建了ContextImpl和Application對象尘分,最后還調(diào)用了Application的onCreate()方法,完全模擬創(chuàng)建一個應(yīng)用的過程丸氛。但是培愁,創(chuàng)建應(yīng)用上下文環(huán)境需要對應(yīng)的一個apk文件,這個的apk文件是哪個呢缓窜?上面的參數(shù)中g(shù)etSystemContext().mPackageInfo正是定续。
通過跟蹤getSystemContext()的代碼,最終可以找到在ContextImpl類的createSystemContext(ActivityThread)方法中創(chuàng)建了一個LoadedApk對象禾锤。
LoadedApk(ActivityThread activityThread) {
mActivityThread = activityThread;
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.packageName = "android";
mPackageName = "android";
...
}
LoadedApk對象保存了一個apk文件的信息私股,它指明了將使用的包名為“android”,而framework-res.apk的包名正是“android”恩掷。因此倡鲸,getSystemContext()方法返回的對象所對象的apk文件就是framework-res.apk。
因此黄娘,ActivityThread的SystemMain()方法相當于創(chuàng)建了一個framework-res.apk的上下文環(huán)境峭状。
總結(jié):
SystemServer進程是一個應(yīng)用進程訪問底層資源的中間層代理,通過它來啟動和管理AMS寸宏,PMS等眾多服務(wù)宁炫。