SystemServer進程在Android中的角色
SystemServer進程是Android系統(tǒng)的核心之一,大部分Android提供的服務都運行在這個進程里,如AMS,PMS,等六十多種服務。我們都知道Android的應用進程沒有權限直接訪問設備的底層資源,只能通過SystemServer中的服務代理訪問,這樣做的目的是為了防止應用進程對系統(tǒng)造成破壞。
SystemServer進程的創(chuàng)建過程
一、 創(chuàng)建SystemServer進程
ZygoteInit類的main()方法里調用startSystemServer()方法來啟動SystemServer。
//位于ZygoteInit.java
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
// 準備啟動參數
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準備啟動參數。
SystemServer進程的uid和gid都被指定為1000。SystemServer進程的名字是system_server,其執(zhí)行類是com.android.server.SystemServer。
2.調用Zygote類的forkSystemServer()來fork出SystemServer子進程。
forkSystemServer()方法最終會調用native層的nativeForkSystemServer()函數,最終調用ForkAndSpecializeCommon函數來執(zhí)行實際的fork操作。
在native層調用完forkAndSpecializeCommon()函數后,如果啟動的是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()函數中將調用fork()函數來創(chuàng)建子進程之前還調用了SetSigChldHandler函數設置處理SIGCHLD信號的函數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函數接收到子進程死亡的信號后,除了調用waitpid()來防止子進程變“僵尸”外,還會判斷死亡的子進程是否是SystemServer進程,如果是,Zygote進程會“自殺”,這樣將導致Init進程殺死所有用戶進程并重啟Zygote。整個手機相當于重啟了一扁,從而達到系統(tǒng)“軟重啟”的目的。
3.在fork出SystemServer進程后,在fork出的進程中調用handleSystemServerProcess()來初始化SystemServer進程。
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
// 關閉父進程zygote復制而來的Socket
closeServerSocket();
// 接SystemServer進程的umask設為0077(S_IRWXG|S_IRWXO),
// 這樣SystemServer創(chuàng)建的文件的屬性就是0077,只有SystemServer進程可以訪問。
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
// 設置當前進程名為 "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);
}
// 啟動應用進程
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);
}
}
因為參數invokeWith通常為null,所以會調用RuntimeInit.zygoteInit()方法。在zygoteInit()方法中,它最終會以拋出MethodAndArgsCaller異常的方式返回,實現(xiàn)真正調用SystemServer類的main()方法。
二、SystemServer的初始化
SystemServer是一個java類,其main()方法中調用了對象的run()方法。
public static void main(String[] args) {
//先初始化SystemServer對象,再調用對象的run()方法
new SystemServer().run();
}
private void run() {
try {
//當系統(tǒng)時間比1970年更早,就設置當前系統(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小時采用一次,并保存結果到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");
// 檢查上次關機過程是否失敗,該方法可能不會返回
performPendingShutdown();
// 初始化系統(tǒng)上下文
createSystemContext();
//創(chuàng)建系統(tǒng)服務管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//將mSystemServiceManager添加到本地服務的成員sLocalServiceObjects
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// 創(chuàng)建并運行所有的Java服務
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
startBootstrapServices(); //啟動引導服務
startCoreServices(); //啟動核心服務
startOtherServices(); //啟動其它服務
} 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.調用時間,如果當前系統(tǒng)時間比1970年更早,就設置當前系統(tǒng)時間為1970年 。
2.設置屬性persist.sys.dalvik.vm.lib.2的值為當前虛擬機的運行庫的路徑。
3.調整虛擬機堆的內存。設定虛擬機利用率為0.8。
4.加載android_servers.so庫。
5.調用createSystemContext()來獲取Context。
6.創(chuàng)建SystemServiceManager的對象mSystemServiceManager,這個對象負責系統(tǒng)Service的啟動。
7.啟動服務。startBootstrapServices(),startBootstrapServices(),startBootstrapServices()三大方法。
8.調用Loop.loop(),進入處理消息的循環(huán)。
private void createSystemContext() {
//創(chuàng)建ActivityThread對象
ActivityThread activityThread = ActivityThread.systemMain();
//創(chuàng)建ContextImpl、LoadedApk對象
mSystemContext = activityThread.getSystemContext();
//設置主題
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}
在createSystemContext()方法里,通過ActivityThread的靜態(tài)方法systemMain()創(chuàng)建了一個activityThread。然后調用它的getSystemContext()方法來獲取系統(tǒng)的Context,最后設置主題。
接下來看看systemMain()方法。
public static ActivityThread systemMain() {
//對于低內存的設備,禁用硬件加速
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
// 創(chuàng)建ActivityThread
ActivityThread thread = new ActivityThread();
// 創(chuàng)建Application以及調用其onCreate()方法
thread.attach(true);//代表是系統(tǒng)的應用進程
return thread;
}
上面的代碼主要是new了一個ActivityThread對象。
同樣的我們知道,ActivityThread是應用程序的主線程類,該類同時也存在一個main()主方法,zygote進程在啟動過程的最后會在拋出的MethodAndArgsCaller異常中,通過反射來執(zhí)行ActivityThread類的main()方法。那么這里為什么要用new來創(chuàng)建ActivityThread對象呢?
實際上SystemServer不僅是一個單純的后臺進程,它也是一個運行著組件Service的進程,很多系統(tǒng)的對話框就是從SystemServer中顯示出來的,因此,SystemServer本身也需要一個和APK應用類似的上下文環(huán)境,創(chuàng)建ActivityThread是獲取這個環(huán)境的第一步,后面還需要創(chuàng)建SystemContext對象。ActivityThread的attach(boolean)方法中,傳入參數true時,表示是在SystemServer中調用。如下代碼:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//進入應用進程的處理流程
...
} else { //進入系統(tǒng)進程。該情況只在SystemServer中處理,設置DDMS時看到的systemserver進程名為system_process
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
// 創(chuàng)建應用上下文SystemContext
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
// 創(chuàng)建Application
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
// 調用Application的onCreate()方法
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
...
}
system為true時,創(chuàng)建了ContextImpl和Application對象,最后還調用了Application的onCreate()方法,完全模擬創(chuàng)建一個應用的過程。但是,創(chuàng)建應用上下文環(huán)境需要對應的一個apk文件,這個的apk文件是哪個呢?上面的參數中getSystemContext().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)境。
總結:
SystemServer進程是一個應用進程訪問底層資源的中間層代理,通過它來啟動和管理AMS,PMS等眾多服務。