天天看點

Android系統啟動之SystemServer(二)

在前面的《Android系統啟動之SystemServer(一)》的部落格中,我們了解到SystemServer.main()方法是如何被調用的,至于在mai n()方法中又做了哪些事情并沒有闡述說明,那麼這篇部落格我們就來了解下SystemServer.main()主要都做了啥。

 SystemServer.main()方法主要完成了以下幾項工作

  • 設定系統屬性和初始化環境
  • 建立SystemServerManager對象,并添加到LocalService
  • 啟動服務

  我們先看下SystemServer.main()的源碼,在main()方法中建立了SystemServer對象,然後調用其run()方法,主要的邏輯也是在run()方法中。

//frameworks/base/services/java/com/android/server
/**
 * The main entry point from zygote.
 */
public static void main(String[] args) {
    new SystemServer().run();
}

public SystemServer() {
    // Check for factory test mode.
    mFactoryTestMode = FactoryTest.getMode();
    // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
    
           

設定系統屬性和初始化環境

 我們先看下SystemServer.run()方法中跟系統屬性和初始化相關的内容

private void run() {
    try {
        traceBeginAndSlog("InitBeforeStartServices");
        // If a device's clock is before 1970 (before 0), a lot of
        // APIs crash dealing with negative numbers, notably
        // java.io.File#setLastModified, so instead we fake it and
        // hope that time from cell towers or NTP fixes it shortly.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        //
        // Default the timezone property to GMT if not set.
        //
        String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
        if (timezoneProperty == null || timezoneProperty.isEmpty()) {
            Slog.w(TAG, "Timezone not set; setting to GMT.");
            SystemProperties.set("persist.sys.timezone", "GMT");
        }

        // If the system has "persist.sys.language" and friends set, replace them with
        // "persist.sys.locale". Note that the default locale at this point is calculated
        // using the "-Duser.locale" command line flag. That flag is usually populated by
        // AndroidRuntime using the same set of system properties, but only the system_server
        // and system apps are allowed to set them.
        //
        // NOTE: Most changes made here will need an equivalent change to
        // core/jni/AndroidRuntime.cpp
        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", "");
        }

        // The system server should never make non-oneway calls
        Binder.setWarnOnBlocking(true);

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
        }

        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can | xq oqi't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        // Mmmmmm... more memory!
        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.
        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.
        BinderInternal.disableBackgroundScheduling(true);

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

        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        // Initialize native 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();
}
           

主要内容有

  • 判斷系統時間,如果時間小于1970則修改時間避免某些api報錯;
  • 判斷時區,如果沒有設定時區則将時區設定為GMT;
  • 判斷

    persist.sys.language

    屬性,如果該屬性不為空,則将其替換為

    persist.sys.locale

  • 設定

    persist.sys.dalvik.vm.lib.2

    屬性;
  • 設定虛拟機記憶體;
  • 設定程序Binder調用以前台優先級運作;設定程序Binder線程數量;
  • 加載

    libandroid_server.so

    庫;
  • 判斷上次關機是否失敗,如果上次失敗且不是因為更新導緻的則會重新開機或關機
  • 建立系統Context對象

代碼中注釋還是比較詳細的,我們主要看下是如何建立系統Context對象。

private void createSystemContext() {
    //建立ActivityThread對象
    ActivityThread activityThread = ActivityThread.systemMain();
    //得到系統Context對象
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
    //得到SystemUI Context對象
    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
           

 createSystemContext()方法很簡潔,主要就是建立ActivityThread對象,然後通過該對象擷取系統和SystemUI Context對象,接着就是設定Context的theme。

//frameworks/base/core/java/android/app/ActivityThread.java
public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            //通過Context子類ContextImpl建立系統Context對象
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

public ContextImpl getSystemUiContext() {
    synchronized (this) {
        if (mSystemUiContext == null) {
            mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
        }
        return mSystemUiContext;
    }
}
           

建立SystemServerManager對象

 這部分代碼比較簡單,首先建立SystemServiceManager對象,設定RuntimeRestarted标志,然後将SystemserviceManager對象添加至LocalServices的ArrayMap集合中。

//frameworks/base/services/java/com/android/server/SystemServer.java
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
           

啟動服務

 啟動服務是SystemServer的主要工作,大部分我們所熟知的服務都是在這個過程中被建立并啟動的,甚至SystemUI也是在這個過程中被啟動的。啟動服務的過程又分為三個部分,分别是:

  • 啟動開機引導服務
  • 啟動核心服務
  • 啟動其他服務

啟動服務的代碼結構比較比較簡潔,啟動三類服務過程分别封裝在三個方法中,最後調用Looper.loop()方法。

// Start services.
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        //釋放線程池
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }

    // For debug builds, log event loop stalls to dropbox for analysis.
    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
        final int MAX_UPTIME_MILLIS = 60 * 1000;
        if (uptimeMillis > MAX_UPTIME_MILLIS) {
            Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                    "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
        }
    }

    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");

           

啟動引導服務

 在這個過程中,主要是啟動系統啟動時所需的關鍵服務,這些服務具有複雜的互相依賴關系,是以把它們放在這個方法中。

private void startBootstrapServices() {
    Slog.i(TAG, "Reading configuration...");
    final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
    traceBeginAndSlog(TAG_SYSTEM_CONFIG);
    //讀取系統配置,這裡包括/system/etc/sysconfig 配置檔案和/system/etc/permissions下的權限檔案
    SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
    traceEnd();

    // Wait for installd to finish starting up so that it has a chance to
    // create critical directories such as /data/user with the appropriate
    // permissions.  We need this to complete before we initialize other services.
    traceBeginAndSlog("StartInstaller");
    Installer installer = mSystemServiceManager.startService(Installer.class);
    traceEnd();

    // In some cases after launching an app we need to access device identifiers,
    // therefore register the device identifier policy before the activity manager.
    traceBeginAndSlog("DeviceIdentifiersPolicyService");
    mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
    traceEnd();

    // Activity manager runs the show.
    traceBeginAndSlog("StartActivityManager");
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    traceEnd();

    // Power manager needs to be started early because other services need it.
    // Native daemons may be watching for it to be registered so it must be ready
    // to handle incoming binder calls immediately (including being able to verify
    // the permissions for those calls).
    traceBeginAndSlog("StartPowerManager");
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    traceEnd();

    // Now that the power manager has been started, let the activity manager
    // initialize power management features.
    traceBeginAndSlog("InitPowerManagement");
    mActivityManagerService.initPowerManagement();
    traceEnd();

    // Bring up recovery system in case a rescue party needs a reboot
    if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
        traceBeginAndSlog("StartRecoverySystemService");
        mSystemServiceManager.startService(RecoverySystemService.class);
        traceEnd();
    }

    // Now that we have the bare essentials of the OS up and running, take
    // note that we just booted, which might send out a rescue party if
    // we're stuck in a runtime restart loop.
    RescueParty.noteBoot(mSystemContext);

    // Manages LEDs and display backlight so we need it to bring up the display.
    traceBeginAndSlog("StartLightsService");
    mSystemServiceManager.startService(LightsService.class);
    traceEnd();

    // Display manager is needed to provide display metrics before package manager
    // starts up.
    traceBeginAndSlog("StartDisplayManager");
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    traceEnd();

    // We need the default display before we can initialize the package manager.
    traceBeginAndSlog("WaitForDisplay");
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    traceEnd();

    // Only run "core" apps if we're encrypting the device.
    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        Slog.w(TAG, "Device encrypted - only parsing core apps");
        mOnlyCore = true;
    }

    // Start the package manager.
    if (!mRuntimeRestart) {
        MetricsLogger.histogram(null, "boot_package_manager_init_start",
                (int) SystemClock.elapsedRealtime());
    }
    traceBeginAndSlog("StartPackageManagerService");
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    traceEnd();
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        MetricsLogger.histogram(null, "boot_package_manager_init_ready",
                (int) SystemClock.elapsedRealtime());
    }
    // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
    // A/B artifacts after boot, before anything else might touch/need them.
    // Note: this isn't needed during decryption (we don't have /data anyways).
    if (!mOnlyCore) {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                false);
        if (!disableOtaDexopt) {
            traceBeginAndSlog("StartOtaDexOptService");
            try {
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } catch (Throwable e) {
                reportWtf("starting OtaDexOptService", e);
            } finally {
                traceEnd();
            }
        }
    }

    traceBeginAndSlog("StartUserManagerService");
    mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
    traceEnd();

    // Initialize attribute cache used to cache resources from packages.
    traceBeginAndSlog("InitAttributerCache");
    AttributeCache.init(mSystemContext);
    traceEnd();

    // Set up the Application instance for the system process and get started.
    traceBeginAndSlog("SetSystemProcess");
    mActivityManagerService.setSystemProcess();
    traceEnd();

    // DisplayManagerService needs to setup android.display scheduling related policies
    // since setSystemProcess() would have overridden policies due to setProcessGroup
    mDisplayManagerService.setupSchedulerPolicies();

    // Manages Overlay packages
    traceBeginAndSlog("StartOverlayManagerService");
    mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
    traceEnd();

    // The sensor service needs access to package manager service, app ops
    // service, and permissions service, therefore we start it after them.
    // Start sensor service in a separate thread. Completion should be checked
    // before using it.
    mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
        TimingsTraceLog traceLog = new TimingsTraceLog(
                SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
        traceLog.traceBegin(START_SENSOR_SERVICE);
        startSensorService();
        traceLog.traceEnd();
    }, START_SENSOR_SERVICE);
}
           

 在startBootstrapServices()方法中主要啟動的服務有:Installer,DeviceIdentifierPolicyService,ActivityManagerService.Lifecycle,PowerManagerService,RecoverySystemService,LightsService, DisplayManagerService,PackageManagerService,OtaDexopService,UserManagerService,OverlayManagerService, SensorService(實作類是SensorService.cpp)。每個服務的具體作用這裡不展開,我們看下服務的啟動過程,先從SystemServiceManager.startService()方法實作開始,我們以泛型方法為例:

@SuppressWarnings("unchecked")
public <T extends SystemService> T startService(Class<T> serviceClass) {
    try {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);

        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            //通過反射方式得到serviceClass的帶Context參數的構造方法Constructord對象
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            //建立serviceClass對應的執行個體
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service constructor threw an exception", ex);
        }

        startService(service);
        return service;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}

public void startService(@NonNull final SystemService service) {
    // 添加到服務集合
    mServices.add(service);
    long time = SystemClock.elapsedRealtime();
    try {
        //調用SystemService的onStart()方法,至此服務就被緩存到集合并啟動
        service.onStart();
    } catch (RuntimeException ex) {
        throw new RuntimeException("Failed to start service " + service.getClass().getName()
                + ": onStart threw an exception", ex);
    }
    warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
           

 除了啟動服務,在startBootStrapServices()方法中還會通過SystemServiceManager.startBootPhase()設定Service的狀态。在startBootPahse方法中會周遊SystemService集合mServices,調用SystemService.onBootPahse()方法,各個SystemService就可以根據不同的狀态執行自身服務對應的操作。

public void startBootPhase(final int phase) {
    if (phase <= mCurrentPhase) {
        throw new IllegalArgumentException("Next phase must be larger than previous");
    }
    mCurrentPhase = phase;

    Slog.i(TAG, "Starting phase " + mCurrentPhase);
    try {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
        final int serviceLen = mServices.size();
        for (int i = 0; i < serviceLen; i++) {
            final SystemService service = mServices.get(i);
            long time = SystemClock.elapsedRealtime();
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
            try {
                service.onBootPhase(mCurrentPhase);
            } catch (Exception ex) {
                throw new RuntimeException("Failed to boot service "
                        + service.getClass().getName()
                        + ": onBootPhase threw an exception during phase "
                        + mCurrentPhase, ex);
            }
            warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}
           

 比如

mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

最終會調用到DisplayManagerService.onBootPhase(),該方法會阻塞一段時間以擷取預設的屏顯。在後面的 啟動其他服務 階段會多次調用SystemServiceManager.startBootPahse()方法。

啟動核心服務

 在此階段主要啟動了四個服務,分别為:DropBoxManagerService,BatteryService,UsageStatsService,WebViewUpdateService。

/**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        // Records errors and logs, for example wtf()
        traceBeginAndSlog("StartDropBoxManager");
        mSystemServiceManager.startService(DropBoxManagerService.class);
        traceEnd();

        traceBeginAndSlog("StartBatteryService");
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        traceEnd();

        // Tracks application usage stats.
        traceBeginAndSlog("StartUsageService");
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        traceEnd();

        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        traceBeginAndSlog("StartWebViewUpdateService");
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
        traceEnd();
    }
           

啟動其他服務

 在該方法中啟動了很多服務,大概有97個,這裡具體就不展開了,以後遇到再讨論。

總結

 最後用兩張圖總結下,作為大家分析SystemServer參考

Android系統啟動之SystemServer(二)
Android系統啟動之SystemServer(二)