Android系統原始碼分析–Zygote和SystemServer啟動過程

墨香發表於2019-03-01

按計劃本來從這章開始寫四大元件的啟動過程的,但是看看原始碼結構發現為了說的更明白還是先寫一點系統framework層啟動的內容,幫助理解四大元件的啟動以及管理過程。我們知道四大元件管理是通過一些服務以及執行緒實現的,所以先把一些基本概念弄清楚比較好,比如AMS(ActivityManagerService)、PMS(PackageManagerService)等系統服務的作用以及呼叫方式,瞭解這些之後再看四大元件相對容易些,因此我們本章先介紹系統啟動、部分系統服務的作用。

Zygote啟動過程

Zygote是一個孕育器,Android系統所有的應用程式以及系統服務SystemServer都是有Zygote程式孕育(fork)而生的,因此Zygote在Android啟動過程中起著決定作用。Zygote的啟動是從它的main函式開始的,因此我們從這個函式開始分析。整個過程看下面的時序圖。

Zygote.jpg
Zygote.jpg

下面我們開始根據時序圖進行分析。

Step 0.ZygoteInit.main

    public static void main(String argv[]) {
        ...
        try {
            ...

            registerZygoteSocket(socketName);

            ...

            preload();

            ...

            gcAndFinalize();

            ...

            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

            runSelectLoop(abiList);

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            ...
        } catch (Throwable ex) {
            ...
        }
    }複製程式碼

首先呼叫registerZygoteSocket方法,建立一個socket介面,用來和ActivityManagerService通訊,然後呼叫preload方法預載入一些資源等;然後呼叫gcAndFinalize方法釋放一些記憶體;然後呼叫startSystemServer方法啟動SystemServer元件,然後呼叫runSelectLoop方法,建立一個無限迴圈,在socket介面上等待ActivityManagerService請求建立新的應用程式程式;最後呼叫closeServerSocket方法關閉上面建立的socket。

Step 1.ZygoteInit.registerZygoteSocket

   private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                ...
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket `" + fileDesc + "`", ex);
            }
        }
    }複製程式碼

這個sServerSocket是通過傳入FileDescriptor(檔案描述者)通過new一個來LocalServerSocket建立的。

Step 2.LocalServerSocket

    public LocalServerSocket(FileDescriptor fd) throws IOException
    {
        impl = new LocalSocketImpl(fd);
        impl.listen(LISTEN_BACKLOG);
        localAddress = impl.getSockAddress();
    }複製程式碼

在LocalServerSocket建構函式中又new了一個LocalSocketImpl,然後呼叫LocalSocketImpl的listen方法,最後通過getSockAddress方法獲取LocalSocketAddress物件。

Step 3.LocalSocketImpl

    /*package*/ LocalSocketImpl(FileDescriptor fd) throws IOException
    {
        this.fd = fd;
    }複製程式碼

這裡只是傳入了FileDescriptor(檔案描述者)。

Step 5.ZygoteInit.preload

    static void preload() {
        ...
        beginIcuCachePinning();
        ...
        preloadClasses();
        ...
        preloadResources();
        ...
        preloadOpenGL();
        ...
        preloadSharedLibraries();
        preloadTextResources();
        ...
    }複製程式碼

這裡主要是預載入,1.預載入ICU快取,2.執行Zygote程式初始化,預載入一些普通類,3.預載入mResources,4.預載入OpenGL,5.預載入共享庫,6.預載入TextView的字型快取。

Step 12.ZygoteInit.gcAndFinalize

    /*package*/ static void gcAndFinalize() {
        final VMRuntime runtime = VMRuntime.getRuntime();
        ...
        System.gc();
        runtime.runFinalizationSync();
        System.gc();
    }複製程式碼

這裡主要是呼叫System.gc來釋放一部分記憶體。

Step 13.ZygoteInit.startSystemServer

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...

        int pid;

        try {
            ...

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            ...
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }複製程式碼

首先Zygote會通過呼叫Zygote.forkSystemServer方法來建立一個新的程式來啟動SystemServer,並且返回這個程式的pid,如果pid為0,並且有另外一個Zygote則會執行waitForSecondaryZygote關閉另外的Zygote程式,然後呼叫handleSystemServerProcess方法。

Step 16.ZygoteInit.handleSystemServerProcess

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();

        ...

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
        }

        if (parsedArgs.invokeWith != null) {
            ...
        } else {
            ...
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }複製程式碼

首先呼叫closeServerSocket方法關閉socket,然後呼叫performSystemServerDexOpt來建立安裝連線InstallerConnection,最後呼叫RuntimeInit.zygoteInit方法。

Step 19.RuntimeInit.zygoteInit

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }複製程式碼

首先呼叫nativeZygoteInit函式來執行一個Binder程式間通訊機制初始化工作,然後就可以在程式間進行通訊了,然後執行applicationInit方法。

Step 21.RuntimeInit.applicationInit

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }複製程式碼

這裡主要是執行一個invokeStaticMain方法來呼叫SystemServer的main方法。

Step 24.ZygoteInit.runSelectLoop

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        while (true) {
            ...
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                ...
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }複製程式碼

這裡通過acceptCommandPeer來建立ActivityManagerService與Socket的連線,然後呼叫ZygoteConnection.runOnce方法來建立新的應用程式。

SystemServer啟動過程

我們從上面的Step 13 知道了SystemServer的main函式呼叫位置,下面我們分析一下SystemServer的啟動過程。

SystemServer.jpg
SystemServer.jpg

在main方法中new了一個SystemServer然後呼叫它的run方法:

   private void run() {
        try {
            ...

            // Mmmmmm... more memory!
            // 清除vm記憶體增長上限,由於啟動過程需要較多的虛擬機器記憶體空間
            VMRuntime.getRuntime().clearGrowthLimit();

            // The system server has to run all of the time, so it needs to be
            // as efficient as possible with its memory usage.
            // 設定記憶體的可能有效使用率為0.8
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            // Some devices rely on runtime fingerprint generation, so make sure
            // we`ve defined it before booting further.
            Build.ensureFingerprintProperty();

            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            // 訪問環境變數前,需要明確地指定使用者
            Environment.setUserRequired(true);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);

            // Ensure binder calls into the system always run at foreground priority.
            // 確保當前系統程式的binder呼叫,總是執行在前臺優先順序(foreground priority)
            BinderInternal.disableBackgroundScheduling(true);

            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            ...

            // 準備主執行緒的Looper
            Looper.prepareMainLooper();

            // Initialize native services.
            // 載入android_servers.so庫,該庫包含的原始碼在frameworks/base/services/目錄下
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            // 初始化系統上下文
            createSystemContext();

            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            //將mSystemServiceManager新增到本地服務的成員sLocalServiceObjects
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            ...
        }

        // Start services.
        try {
            ...
            startBootstrapServices(); // 啟動引導服務
            startCoreServices();      // 啟動核心服務
            startOtherServices();     // 啟動其他服務
        } catch (Throwable ex) {
            ...
        } finally {
            ...
        }

        ...

        // Loop(迴圈) forever.
        Looper.loop();
        ...
    }複製程式碼

Step 3.Build.ensureFingerprintProperty

    public static void ensureFingerprintProperty() {
        if (TextUtils.isEmpty(SystemProperties.get("ro.build.fingerprint"))) {
            try {
                SystemProperties.set("ro.build.fingerprint", FINGERPRINT);
            } catch (IllegalArgumentException e) {
                Slog.e(TAG, "Failed to set fingerprint property", e);
            }
        }
    }複製程式碼

確認裝置的指紋屬性。

Step 7.Looper.prepareMainLooper()

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }複製程式碼

準備main looper,這個詳細的過程我們下一章再講,這裡先看一下流程。

Step 10.SystemServer.performPendingShutdown

    private void performPendingShutdown() {
        final String shutdownAction = SystemProperties.get(
                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
        if (shutdownAction != null && shutdownAction.length() > 0) {
            // 是否重啟
            boolean reboot = (shutdownAction.charAt(0) == `1`);

            final String reason;
            if (shutdownAction.length() > 1) {
                reason = shutdownAction.substring(1, shutdownAction.length());
            } else {
                reason = null;
            }

            if (PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
                File packageFile = new File(UNCRYPT_PACKAGE_FILE);
                if (packageFile.exists()) {
                    String filename = null;
                    try {
                        filename = FileUtils.readTextFile(packageFile, 0, null);
                    } catch (IOException e) {
                        Slog.e(TAG, "Error reading uncrypt package file", e);
                    }

                    if (filename != null && filename.startsWith("/data")) {
                        if (!new File(BLOCK_MAP_FILE).exists()) {
                            ...
                            return;
                        }
                    }
                }
            }
            ShutdownThread.rebootOrShutdown(null, reboot, reason);
        }
    }複製程式碼

這裡主要是通過關機的action來判斷是否重啟或者關機。

Step 13.SystemServer.createSystemContext

    private void createSystemContext() {
        // 初始化ActivityThread,並設定預設主題
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
    }複製程式碼

首先呼叫ActivityThread.systemMain方法建立ActivityThread物件然後獲取mSystemContext,並且設定預設系統主題。

Step 15.ActivityThread.systemMain

    public static ActivityThread systemMain() {
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }複製程式碼

建立ActivityThread物件,並呼叫attach方法。

Step 17.ResourcesManager.getInstance

    public static ResourcesManager getInstance() {
        synchronized (ResourcesManager.class) {
            if (sResourcesManager == null) {
                sResourcesManager = new ResourcesManager();
            }
            return sResourcesManager;
        }複製程式碼

單例模式建立ResourcesManager物件並且返回。

Step 19.ActivityThread.attach

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
        } else {
            ...
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                ...
            }
        }

        ...
    }複製程式碼

因為引數傳入的是true,表明是系統的執行緒,所以執行else裡面的內容,首先建立Instrumentation,然後呼叫ContextImpl.createAppContext方法建立ContextImpl,然後通過呼叫LoadedApk.makeApplication方法建立Application,然後呼叫Application.onCreate方法。

Step 22.ContextImpl.createAppContext

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread,
                packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
    }複製程式碼

通過new ContextImpl來建立ContextImpl物件。

Step 22.LoadedApk.makeApplication

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        ...

        Application app = null;

        ...

        try {
            ...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
        ...

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ...
            }
        }

        ...

        return app;
    }複製程式碼

通過ContextImpl.createAppContext方法建立ContextImpl物件,然後呼叫mActivityThread.mInstrumentation.newApplication方法建立Application物件,然後呼叫instrumentation.callApplicationOnCreate方法。

Step 23.ContextImpl.createAppContext

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread,
                packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
    }複製程式碼

建立ContextImpl物件並返回。

Step 26.Instrumentation.createAppContext

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }複製程式碼

這裡主要是呼叫newApplication方法返回Application。

Step 28.Instrumentation.newApplication

    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }複製程式碼

呼叫class.newInstance方法建立Application,然後呼叫Application.attach方法,向Application中傳入context。

Step 32.Application.attach

    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }複製程式碼

通過ContextImpl.getImpl方法獲取LoadedApk物件。

Step 34.Instrumentation.callApplicationOnCreate

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }複製程式碼

這裡開始呼叫Application的onCreate方法。

Step 39.ActivityThread.getSystemContext

    public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }複製程式碼

通過ContextImpl.createSystemContext建立mSystemContext。

Step 40.ContextImpl.createSystemContext

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread,
                packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    }複製程式碼

建立ContextImpl並且返回。

Step 43.SystemServer.startBootstrapServices

    private void startBootstrapServices() {
        ...
        // 安裝服務
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity管理服務
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        ...
        // 電量管理服務
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        ...

        // 管理LEDs和背光燈服務
        mSystemServiceManager.startService(LightsService.class);

        // 顯示管理服務
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // 包管理服務
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        ...
        // 啟動使用者管理服務
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

        //初始化安裝包資源的屬性快取
        AttributeCache.init(mSystemContext);

        // 啟動系統程式的應用例項
        mActivityManagerService.setSystemProcess();

        // 啟動感測器服務
        startSensorService();
    }複製程式碼

這裡主要是啟動系統引導服務。

Step 44.SystemServer.startCoreServices

    private void startCoreServices() {
        // 啟動電池服務
        mSystemServiceManager.startService(BatteryService.class);

        // 啟動應用統計服務
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));

        // 啟動WebView更新服務
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
    }複製程式碼

啟動核心服務。

Step 45.SystemServer.startOtherServices

這裡程式碼就不貼了,都是啟動服務的程式碼,這裡有很多服務,我簡單列一下服務並說一下服務基本功能。

服務 名稱 服務 名稱
SchedulingPolicyService CameraService
TelecomLoaderService AccountManagerService.Lifecycle
ContentService.Lifecycle VibratorService
ConsumerIrService AlarmManagerService
InputManagerService WindowManagerService
VrManagerService PersistentDataBlockService
MetricsLoggerService IpConnectivityMetrics
PinnerService InputMethodManagerService.Lifecycle
MountService.Lifecycle UiModeManagerService
LockSettingsService.Lifecycle BluetoothService
DeviceIdleController NsdService
StatusBarManagerService ClipboardService
NetworkManagementService WifiService
NetworkScoreService NetworkStatsService
NetworkPolicyManagerService WifiNanService
WifiP2pService TextServicesManagerService.Lifecycle
WifiScanningService ConnectivityService
RttService DevicePolicyManagerService.Lifecycle
UpdateLockService RecoverySystemService
NotificationManagerService DeviceStorageMonitorService
LocationManagerService CountryDetectorService
SearchManagerService.Lifecycle DropBoxManagerService
AudioService.Lifecycle DockObserver
ThermalObserver MidiService.Lifecycle
UsbService.Lifecycle SerialService
HardwarePropertiesManagerService NightDisplayService
JobSchedulerService SoundTriggerService
BackupManagerService.Lifecycle AppWidgetService
VoiceInteractionManagerService GestureLauncherService
SensorNotificationService ContextHubSystemService
DiskStatsService SamplingProfilerService
NetworkTimeUpdateService CommonTimeManagementService
EmergencyAffordanceService DreamManagerService
AssetAtlasService GraphicsStatsService
PrintManagerService RestrictionsManagerService
MediaSessionService HdmiControlService
TvInputManagerService MediaResourceMonitorService
TvRemoteService MediaRouterService
TrustManagerService FingerprintService
ShortcutService.Lifecycle LauncherAppsService
MediaProjectionManagerService WearBluetoothService
WearWifiMediatorService WearTimeService
MmsServiceBroker RetailDemoModeService
NsdService WallpaperManagerService.Lifecycle

參考:

Android系統啟動-SystemServer下篇
Android系統程式Zygote啟動過程的原始碼分析

原文地址:Android系統原始碼分析–Zygote和SystemServer啟動過程

Android開發群:192508518

微信公眾賬號:Code-MX

注:本文原創,轉載請註明出處,多謝。

相關文章