Android源碼學習--SystemServer進程

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等眾多服務。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容