Zygote家的大兒子 —— SystemServer

  • 2019 年 10 月 13 日
  • 筆記

本文基於 Android 9.0 , 程式碼倉庫地址 : android_9.0.0_r45

文中源碼鏈接:

SystemServer.java

SystemServiceManager.java

SystemService.java

首先來回顧一下上篇文章 Java 世界的盤古和女媧 —— Zygote ,主要介紹了 Android 世界中的第一個 Java 進程 Zygote,它的主要工作流程如下:

  1. registerServerSocketFromEnv(), 註冊服務端 socket,用於和客戶端進程通訊
  2. preload(),預載入一系列資源,提高應用啟動速度
  3. forkSystemServer(),創建 system_server 進程
  4. 功成身退,調用 runSelectLoop() 等待響應客戶端請求,創建應用進程

本篇文章的主角 system_server 進程是 Zygote 進程 fork 出的第一個進程,它負責管理和啟動整個 Framework 層。

再來看看 Gityuan 的這張圖片,找一下 System Server 的位置,它承載了各類系統服務的創建和啟動。關於 system_server 進程的創建流程,上篇文章中已經做了詳細介紹,這裡再簡單看一下流程圖:

最終會調用到 SystemServer.main() 方法。下面就以此為起點,來具體分析 SystemServer 都做了些什麼。

SystemServer 啟動流程

public static void main(String[] args) {      new SystemServer().run();  }

接著看 run() 方法。

private void run() {      try {          ......          // 如果設備時間早於 1970 年,很多 API 處理負數時會 crash。所以直接設置為 1970 年 1 月 1 日          if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {              Slog.w(TAG, "System clock is before 1970; setting to 1970.");              SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);          }            // 未設置時區的話默認設為 GMT          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 (!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);          // The system server should always load safe labels          PackageItemInfo.setForceSafeLabels(true);            // Default to FULL within the system server.          SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;            // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized          SQLiteCompatibilityWalFlags.init(null);            // 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);          }            // 設置虛擬機運行庫路徑          SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());            // Mmmmmm... more memory!          // 清除虛擬機記憶體增長限制,允許應用申請更多記憶體          VMRuntime.getRuntime().clearGrowthLimit();            // 設置堆記憶體的有效利用率為 0.8,(可能被忽略)          VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);            // 確保指紋資訊已經定義          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);            // Within the system server, when parceling exceptions, include the stack trace          Parcel.setStackTraceParceling(true);            // 確保系統的 Binder 調用總是運行在前台優先順序          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);          // 1. 創建主執行緒 Looper          Looper.prepareMainLooper();          Looper.getMainLooper().setSlowLogThresholdMs(                  SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);            // 初始化 native 服務,載入 libandroid_servers.so          System.loadLibrary("android_servers");            // 檢查上次關機是否失敗,可能不會有返回值          performPendingShutdown();            // 2. 初始化系統上下文          createSystemContext();            // 3. 創建系統服務管理 SystemServiceManager          // 並將 mSystemServiceManager 註冊到 sLocalServiceObjects 中          mSystemServiceManager = new SystemServiceManager(mSystemContext);          mSystemServiceManager.setStartInfo(mRuntimeRestart,                  mRuntimeStartElapsedTime, mRuntimeStartUptime);          LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);          // Prepare the thread pool for init tasks that can be parallelized          SystemServerInitThreadPool.get();      } finally {          traceEnd();  // InitBeforeStartServices      }        // Start services.      try {          traceBeginAndSlog("StartServices");          startBootstrapServices(); // 4. 啟動系統引導服務          startCoreServices();      // 5. 啟動系統核心服務          startOtherServices();     // 6. 啟動其他服務          SystemServerInitThreadPool.shutdown();      } catch (Throwable ex) {          Slog.e("System", "******************************************");          Slog.e("System", "************ Failure starting system services", ex);          throw ex;      } finally {          traceEnd();      }        StrictMode.initVmDefaults(null);        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);          }      }        // 7. Loop forever.      Looper.loop();      throw new RuntimeException("Main thread loop unexpectedly exited");  }

程式碼雖然比較長,但是邏輯很清晰。我在注釋里標記了比較重要的 7 個步驟,逐一分析。

Looper.prepareMainLooper()

初始化 Looper。關於 Handler 消息機制,可以閱讀我的另一篇文章 深入理解 Handler 消息機制 。最後會調用 Looper.loop() 開啟消息循環,開始處理消息。

createSystemContext()

private void createSystemContext() {      // 創建 system_server 上下文資訊      ActivityThread activityThread = ActivityThread.systemMain();      mSystemContext = activityThread.getSystemContext();      mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);        final Context systemUiContext = activityThread.getSystemUiContext();      // 設置主題,用於系統 dialog 等      systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);  }

創建系統上下文。首先調用 ActivityThread.systemMain() 方法獲取 ActivityThread 對象,然後再獲取上下文。

public static ActivityThread systemMain() {      // 判斷是否是大記憶體設備,在低記憶體設備上不啟用硬體加速      if (!ActivityManager.isHighEndGfx()) {          ThreadedRenderer.disable(true);      } else {          ThreadedRenderer.enableForegroundTrimming();      }      ActivityThread thread = new ActivityThread();      thread.attach(true, 0);      return thread;  }

關於 ActivityThread.attach() 方法這裡不做具體分析了,後面文章說到應用啟動時再來詳細解析。

創建完系統上下文,接下來就是啟動各種系統服務了。源碼中把服務大致分為了三類,再來回顧一下:

startBootstrapServices(); // 4. 啟動系統引導服務  startCoreServices();      // 5. 啟動系統核心服務  startOtherServices();     // 6. 啟動其他服務

逐一進行分析。

startBootstrapServices()

private void startBootstrapServices() {      final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";      SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);        // 阻塞等待與 installd 建立 socket 通道      Installer installer = mSystemServiceManager.startService(Installer.class);        // 啟動 DeviceIdentifiersPolicyService,在 ActivityManagerService 之前      mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);        // 啟動服務 ActivityManagerService      mActivityManagerService = mSystemServiceManager.startService(              ActivityManagerService.Lifecycle.class).getService();      mActivityManagerService.setSystemServiceManager(mSystemServiceManager);      mActivityManagerService.setInstaller(installer);        // 啟動服務 PowerManagerService      mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);        // Now that the power manager has been started, let the activity manager      // initialize power management features.      mActivityManagerService.initPowerManagement();        // 啟動服務 RecoverySystemService      mSystemServiceManager.startService(RecoverySystemService.class);        // 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);        // 啟動服務 LightsService      mSystemServiceManager.startService(LightsService.class);        // Package manager isn't started yet; need to use SysProp not hardware feature      if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {          mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);      }        // 啟動 DisplayManagerService,在 PackageManagerService 之前      mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);        // We need the default display before we can initialize the package manager.      mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);        // 正在加密設備時只運行核心 app      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;      }        // 啟動服務 PackageManagerService      if (!mRuntimeRestart) {          MetricsLogger.histogram(null, "boot_package_manager_init_start",                  (int) SystemClock.elapsedRealtime());      }      mPackageManagerService = PackageManagerService.main(mSystemContext, installer,              mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);      mFirstBoot = mPackageManagerService.isFirstBoot();      mPackageManager = mSystemContext.getPackageManager();      if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {          MetricsLogger.histogram(null, "boot_package_manager_init_ready",                  (int) SystemClock.elapsedRealtime());      }      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();              }          }      }        // 啟動服務 UserManagerService      mSystemServiceManager.startService(UserManagerService.LifeCycle.class);        // 初始化屬性 cache 以快取包資源      AttributeCache.init(mSystemContext);        // 設置 AMS      mActivityManagerService.setSystemProcess();        // DisplayManagerService needs to setup android.display scheduling related policies      // since setSystemProcess() would have overridden policies due to setProcessGroup      mDisplayManagerService.setupSchedulerPolicies();        // 啟動服務 OverlayManagerService      OverlayManagerService overlayManagerService = new OverlayManagerService(              mSystemContext, installer);      mSystemServiceManager.startService(overlayManagerService);        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {          // DisplayManager needs the overlay immediately.          overlayManagerService.updateSystemUiContext();          LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();      }        // 在單獨的執行緒中啟動 SensorService      mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {          TimingsTraceLog traceLog = new TimingsTraceLog(                  SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);          startSensorService();      }, START_SENSOR_SERVICE);  }

startBootstrapServices() 方法中的都是系統啟動過程中的關鍵服務,且相互依賴,主要下列服務 :

Installer DeviceIdentifiersPolicyService ActivityManagerService PowerManagerService RecoverySystemService LightsService StartSidekickService DisplayManagerService

SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY (100)

PackageManagerService UserManagerService OverlayManagerService SensorService

一共啟動了十二個核心服務。注意中間的 SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY,它並不是代表什麼系統服務,而是一個 int 值 100,類似的 int 值還有一些,定義在 SystemService 類中,它的作用是給服務啟動過程劃分階段,每個階段都有特定的含義,可以做不同的事情。這裡先混個臉熟,等介紹完所有的服務,再回過頭來總結一下有哪些階段。

startCoreServices()

private void startCoreServices() {      // 啟動服務 BatteryService,需要 LightService      mSystemServiceManager.startService(BatteryService.class);        // 啟動服務 UsageStatsService,統計應用使用情況      mSystemServiceManager.startService(UsageStatsService.class);      mActivityManagerService.setUsageStatsManager(              LocalServices.getService(UsageStatsManagerInternal.class));        // 檢查是否存在可更新的 WebView。存在就啟動服務 WebViewUpdateService      if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {          mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);      }        // 啟動服務 BinderCallsStatsService,跟蹤 Binder 調用的 cpu 時間消耗      BinderCallsStatsService.start();  }

啟動了四個服務,BatteryService UsageStatsService WebViewUpdateServiceBinderCallsStatsService

startOtherServices()

startOtherServices() 源碼有一千多行,就像一個雜貨鋪,啟動了一系列的服務。下面盡量精簡一下程式碼:

KeyAttestationApplicationIdProviderService/KeyChainSystemService  SchedulingPolicyService/TelecomLoaderService/TelephonyRegistry    mContentResolver = context.getContentResolver();    AccountManagerService/ContentService    mActivityManagerService.installSystemProviders();    DropBoxManagerService/VibratorService/ConsumerIrService/AlarmManagerService    final Watchdog watchdog = Watchdog.getInstance();  watchdog.init(context, mActivityManagerService);    InputManagerService/WindowManagerService/VrManagerService/BluetoothService  IpConnectivityMetrics/NetworkWatchlistService/PinnerService  InputMethodManagerService/AccessibilityManagerService/StorageManagerService  StorageStatsService/UiModeManagerService/LockSettingsService  PersistentDataBlockService/OemLockService/DeviceIdleController  DevicePolicyManagerService/StatusBarManagerService/ClipboardService  NetworkManagementService/IpSecService/TextServicesManagerService  TextClassificationManagerService/NetworkScoreService/NetworkStatsService  NetworkPolicyManagerService/WifiScanningService/RttService  WifiAware/WifiP2P/Lowpan/Ethernet/ConnectivityService/NsdService  SystemUpdateManagerService/UpdateLockService/NotificationManagerService  DeviceStorageMonitorService/LocationManagerService/CountryDetectorService  SearchManagerService/WallpaperManagerService/AudioService/BroadcastRadioService  DockObserver/ThermalObserver/WiredAccessoryManager/MidiManager/UsbService  SerialService/HardwarePropertiesManagerService/TwilightService  ColorDisplayService/JobSchedulerService/SoundTriggerService/TrustManagerService  BackupManager/AppWidgerService/VoiceRecognitionManager/GestureLauncherService  SensorNotificationService/ContextHubSystemService/DiskStatsService  TimeZoneRulesManagerService/NetworkTimeUpdateService/CommonTimeManagementService  CertBlacklister/EmergencyAffordanceService/DreamManagerService/GraphicsStatsService  CoverageService/PrintManager/CompanionDeviceManager/RestrictionsManagerService  MediaSessionService/MediaUpdateService/HdmiControlService/TvInputManagerService  MediaResourceMonitorService/TvRemoteService/MediaRouterService/FingerprintService  BackgroundDexOptService/PruneInstantAppsJobService/ShortcutService  LauncherAppsService/CrossProfileAppsService/MediaProjectionManagerService  WearConfigService/WearConnectivityService/WearTimeService/WearLeftyService  WearGlobalActionsService/SliceManagerService/CameraServiceProxy/IoTSystemService  MmsServiceBroker/AutoFillService    // It is now time to start up the app processes...  vibrator.systemReady();  lockSettings.systemReady();    // 480  mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);  // 500  mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);    wm.systemReady();  mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());  mPackageManagerService.systemReady();  mDisplayManagerService.systemReady(safeMode, mOnlyCore);    // Start device specific services  final String[] classes = mSystemContext.getResources().getStringArray(          R.array.config_deviceSpecificSystemServices);  for (final String className : classes) {      try {          mSystemServiceManager.startService(className);      } catch (Throwable e) {          reportWtf("starting " + className, e);      }  }    // 520  mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);    mActivityManagerService.systemReady(() -> {      // 550      mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);        startSystemUi(context, windowManagerF);        networkManagementF.systemReady();      ipSecServiceF.systemReady();      networkStatsF.systemReady();      connectivityF.systemReady();        Watchdog.getInstance().start      mPackageManagerService.waitForAppDataPrepared();        // 600      mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);        locationF.systemRunning();      countryDetectorF.systemRunning();      networkTimeUpdaterF.systemRunning();      commonTimeMgmtServiceF.systemRunning();      inputManagerF.systemRunning();      telephonyRegistryF.systemRunning();      mediaRouterF.systemRunning();      mmsServiceF.systemRunning();      incident.systemRunning();  }

通過上面的程式碼可以看到啟動了相當多的系統服務。startOtherServices() 方法共經歷了五個啟動階段,如下所示:

SystemService.PHASE_LOCK_SETTINGS_READY             // 480  SystemService.PHASE_SYSTEM_SERVICES_READY           // 500  SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY  // 520  SystemService.PHASE_ACTIVITY_MANAGER_READY          // 550  SystemService.PHASE_THIRD_PARTY_APPS_CAN_START      // 600

最後調用的 mActivityManagerService.systemReady() 方法。該方法中會調用 startHomeActivityLocked 來啟動桌面 Activity,這樣桌面應用就啟動了。

Looper.loop()

至此,system_server 進程的主要工作就算完成了,進入 Looper.loop() 狀態,等待其他執行緒通過 Handler 發送消息到主執行緒並處理。

SystemServer 啟動階段分類

回過頭再來看看前面提到的啟動階段分類,定義在 com.android.server.SystemService 類中:

/*   * Boot Phases   *   * 啟動階段   */  public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?    /**   * After receiving this boot phase, services can obtain lock settings data.   */  public static final int PHASE_LOCK_SETTINGS_READY = 480;    /**   * After receiving this boot phase, services can safely call into core system services   * such as the PowerManager or PackageManager.   *   * 在這個階段之後,可以安全的調用系統核心服務,如 PowerManager 和 PackageManager   */  public static final int PHASE_SYSTEM_SERVICES_READY = 500;    /**   * After receiving this boot phase, services can safely call into device specific services.   *   * 在這個階段之後,可以安全調用設備特定的服務   */  public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520;    /**   * After receiving this boot phase, services can broadcast Intents.   *   * 在這個階段之後,服務可以廣播   */  public static final int PHASE_ACTIVITY_MANAGER_READY = 550;    /**   * After receiving this boot phase, services can start/bind to third party apps.   * Apps will be able to make Binder calls into services at this point.   *   * 在這個階段之後,服務可以啟動/綁定第三方應用   * 應用此時可以進行 Binder 調用   */  public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;    /**   * After receiving this boot phase, services can allow user interaction with the device.   * This phase occurs when boot has completed and the home application has started.   * System services may prefer to listen to this phase rather than registering a   * broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.   *   * 在這個階段之後,允許用戶和設備交互。   * 這個階段發生在啟動完成,home 應用已經開始。   * 系統服務更傾向於監聽這個階段,而不是監聽啟動廣播 ACTION_BOOT_COMPLETED,以降低延遲   */  public static final int PHASE_BOOT_COMPLETED = 1000;

system_server 啟動過程中各個階段的位置大致如下:

private void startBootstrapServices() {      ...      // 100      mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);      ...  }    private void startOtherServices() {      ...      // 480      mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);      // 500      mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);        ...      // 520      mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);        mActivityManagerService.systemReady(() -> {          mSystemServiceManager.startBootPhase(                      SystemService.PHASE_ACTIVITY_MANAGER_READY); // 550            ...          mSystemServiceManager.startBootPhase(                      SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // 600      }  }

最後的 SystemService.PHASE_BOOT_COMPLETED(1000) 在 AMS 的 finishBooting() 方法中調用。另外注意 480500 兩個階段是連在一起的,中間沒有發生任何事情。

那麼,劃分階段的具體作用是什麼呢?答案就在 startBootPhase() 方法中:

public void startBootPhase(final int phase) {      if (phase <= mCurrentPhase) {          throw new IllegalArgumentException("Next phase must be larger than previous");      }      mCurrentPhase = phase;        try {          final int serviceLen = mServices.size();          for (int i = 0; i < serviceLen; i++) {              final SystemService service = mServices.get(i);              long time = SystemClock.elapsedRealtime();              try {                  // 回調系統服務的 onBootPhase() 方法                  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");          }      } finally {          Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);      }  }

核心就在於 service.onBootPhase(mCurrentPhase);。所有系統服務都是繼承於 SystemService 的,startBootPhase() 方法會回調當前階段已經加入 mServices 的所有系統服務的 onBootPhase() 方法,在合適的階段做一些合適的事情。以 AMS 為例:

@Override  public void onBootPhase(int phase) {      mService.mBootPhase = phase;      if (phase == PHASE_SYSTEM_SERVICES_READY) {          mService.mBatteryStatsService.systemServicesReady();          mService.mServices.systemServicesReady();      }  }

SystemServer 是如何啟動服務的 ?

看完 SystemServer 的源碼,它最重要的工作就是創建和啟動各種系統服務。那麼服務一般是如何創建的呢?下面以 startBootstrapServices() 中創建的第一個服務 Installer 為例來看一下:

Installer installer = mSystemServiceManager.startService(Installer.class);

進入 SystemServiceManagerstartService() 方法:

public <T extends SystemService> T startService(Class<T> serviceClass) {      try {          // 獲取服務名稱          final String name = serviceClass.getName();            // 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 {              // 獲取服務類的構造器              Constructor<T> constructor = serviceClass.getConstructor(Context.class);              // 反射創建 service              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);      }  }

創建並啟動一個系統服務。這個系統服務必須是 com.android.server.SystemService 的子類。根據參數傳入的 Class 對象反射創建其實例,再調用重載方法 startService()

public void startService(@NonNull final SystemService service) {      // Register it.      mServices.add(service);      // Start it.      long time = SystemClock.elapsedRealtime();      try {          // 回調系統服務的 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");  }

就兩步。第一步,註冊服務,mServices 是一個 ArrayList<SystemService> 對象,用來保存已經創建的系統服務。第二步,回調服務的 onStart() 方法,還是以 Installer 為例:

@Override  public void onStart() {      if (mIsolated) {          mInstalld = null;      } else {          connect();      }  }

這樣一個服務就啟動完成了。這是一種比較普遍的啟動方式,當然還有一些系統服務具有不一樣的啟動方式,這裡就不一一分析了,後面有機會解析具體服務的時候再來分析。

總結

SystemServer 的啟動流程比較耿直,沒有那麼多彎彎繞,下面簡單總結一下:

  1. 語言、時區、地區等設置
  2. 虛擬機記憶體設置
  3. 指紋資訊,Binder 調用設置
  4. Looper.prepareMainLooper() ,創建主執行緒 Looper
  5. 初始化 native 服務,載入 libandroid_servers.so
  6. createSystemContext(),初始化系統上下文
  7. 創建系統服務管理 SystemServiceManager
  8. startBootstrapServices,啟動系統引導服務
  9. startCoreServices,啟動系統核心服務
  10. startOtherServices,啟動其他服務
  11. Looper.loop(),開啟消息循環

另外,在 startOtherServices 的最後會調用 AMS 的 onSystemReady() 方法啟動桌面 Activity。

預告

還記得 Zygote 進程的 runSelectLoop() 方法嗎?Zygote 在創建完 system_server 進程之後,就開始默默的等待客戶端請求創建應用進程。下一篇,我們將從源碼角度來捋一遍客戶端是如何發送請求,Zygote 是如何處理請求,應用進程是如何創建的,敬請期待!

文章首發微信公眾號: 秉心說 , 專註 Java 、 Android 原創知識分享,LeetCode 題解。

更多最新原創文章,掃碼關注我吧!