安卓彩38平臺出租開發學習之SystemServer啟動過程
main()方法
SystemServer是一個進程,由zygote進程fork出來,所以它的入口方法就是main方法,代碼如下
public static void main(String[] args) {
new SystemServer().run();
}
直接就是new了一個SystemServer,而後執行run()方法
run()方法
方法比較長,代碼如下
private void run() { try { traceBeginAndSlog("InitBeforeStartServices"); // 如果當前系統時間早於1970年元月1號,就更新之為1970年元月1號 if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // 設置時區 String timezoneProperty = SystemProperties.get("persist.sys.timezone"); if (timezoneProperty == null || timezoneProperty.isEmpty()) { 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", ""); } // 系統Server不能進行非oneway通信,因為非oneway通信要等待對方的恢復,這個等待過程是阻塞的 Binder.setWarnOnBlocking(true); // 所以設置阻塞時警告 // 正式啟動SystemServer int uptimeMillis = (int) SystemClock.elapsedRealtime(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis); if (!mRuntimeRestart) { MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis); } // 設置vmLibrary SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); // Enable the sampling profiler. if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // 清除內存增長上限,因為加載SystemServer需要很多內存 VMRuntime.getRuntime().clearGrowthLimit(); // 設置內存利用率最大是0.8 VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // 初始化指紋系統 Build.ensureFingerprintProperty(); // 設置訪問環境變量(例如sd卡路徑等)時,必須指定用戶 Environment.setUserRequired(true); // 設置系統的Bundle是可defuse的,意為如果在解析bundle的時候,忽略發生的badParcelableException // 那個異常如果發送,就直接清空這個Bundle的內容。所以defuse使能最好在Bundle到了終點後再設置,因為這樣總不會導致下流再失去bundle的內容 BaseBundle.setShouldDefuse(true); // 保證進入SystemServer的binder都運行在前臺 BinderInternal.disableBackgroundScheduling(true); // 設置最大線程數為31 BinderInternal.setMaxThreads(sMaxBinderThreads); // 設置當前線程(主線程)也是在前臺進行 android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); // 主線程不能自己切到後臺 Looper.prepareMainLooper(); // 主線程的消息循環開始 // 加載native服務 System.loadLibrary("android_servers"); // 檢測上次是否成功關機 performPendingShutdown(); // 初始化系統上下文 createSystemContext(); // 初始化SysytemServiceManager,並把它添加到LocalServices中 mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // 創建SystemServerInit線程池的單例 SystemServerInitThreadPool.get(); } finally { traceEnd(); } // 啟動一些服務 // Start services. try { traceBeginAndSlog("StartServices"); startBootstrapServices(); // 啟動引導服務 startCoreServices(); // 啟動核心服務 startOtherServices(); // 啟動其他服務 SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { ... } finally { traceEnd(); } ... // 日誌 // Loop forever. // 開始消息循環 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); // 消息循環是不能退出的 }
代碼多但是邏輯並不復雜,值得註意的方法除了啟動引導服務、核心服務和其他服務外,再就是檢測上次關機是否成功的performPendingShutdown()方法,這個方法主要是針對recovery模式下系統更新引起的重啟,這種情況要多重啟一次。而這裏只是設置了一下sys.powerctl屬性,沒有執行重啟操作
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 (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { /* * 關機原因是否是REBOOT_RECOVERY_UPDATE,也就是recovery模式下,為了執行系統更新而關的機 * 這種情況下,一定會多重啟一次,多的這一次重啟,原因就不是REBOOT_RECOVERY_UPDATE了 * @hide public static final String REBOOT_RECOVERY_UPDATE = "recovery-update"; */ File packageFile = new File(UNCRYPT_PACKAGE_FILE); if (packageFile.exists()) { String filename = null; try { filename = FileUtils.readTextFile(packageFile, 0, null); // 讀取uncrypt_file的內容,獲取的是一個文件名 } catch (IOException e) { Slog.e(TAG, "Error reading uncrypt package file", e); } if (filename != null && filename.startsWith("/data")) { // 如果讀出來的文件名以/data開頭,也就是在data目錄內 if (!new File(BLOCK_MAP_FILE).exists()) { // 如果block.map文件不存在,直接拋異常,重啟失敗 Slog.e(TAG, "Can‘t find block map file, uncrypt failed or " + "unexpected runtime restart?"); return; } } } } ShutdownThread.rebootOrShutdown(null, reboot, reason); } }
主要是調用了ShutdownThread.rebootOrShutdown()方法,這個方法只是保存了一下sys.powerctl屬性,代碼如下
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
if (reboot) {
.. // 日誌
PowerManagerService.lowLevelReboot(reason);
.. // 日誌
reason = null;
} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
// 關機前要進行振動
Vibrator vibrator = new SystemVibrator(context); // 振動器
try {
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES); // 傳入振動持續時間和振動方式
} catch (Exception e) {
.. // 日誌
}
try {
Thread.sleep(SHUTDOWN_VIBRATE_MS); // 振動是異步的,所以當前線程要阻塞一會兒,保證振動完了,再關機
} catch (InterruptedException unused) {
}
}
// Shutdown power
PowerManagerService.lowLevelShutdown(reason);
如果是進來這個方法是要重啟,reboot就是真,先調用PowerManagerService.lowLevelReboot()方法,傳入重啟原因reason。此方法代碼如下
public static void lowLevelReboot(String reason) {
if (reason == null) {
reason = "";
}
if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
sQuiescent = true;
reason = "";
} else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
sQuiescent = true;
reason = reason.substring(0,
reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
}
if (reason.equals(PowerManager.REBOOT_RECOVERY)
|| reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) { // 如果reason是或REBOOT_RECOVERY或REBOOT_RECOVERY_UPDATE,就把reason換成recovery
reason = "recovery";
}
if (sQuiescent) {
reason = reason + ",quiescent";
}
SystemProperties.set("sys.powerctl", "reboot," + reason); // 保存sys.powerctl屬性
try {
Thread.sleep(20 * 1000L); // 阻塞20秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
}
可以看到,主要是把重啟原因進行轉換和保存,然後把重啟線程阻塞20s。方法執行完後,就會執行lowLevelShutdown(),代碼如下
public static void lowLevelShutdown(String reason) {
if (reason == null) {
reason = "";
}
SystemProperties.set("sys.powerctl", "shutdown," + reason); // 保存/更新sys.powerctl屬性
}
回到SystemServer.run()方法,檢測完上次是否正常關機後,調用了createSystemContext()方法獲取系統上下文,代碼如下
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
這個方法主要是調用了ActivityThread的一系列方法來實現,參見文章安卓開發學習之獲取系統上下文。然後就是調用startBootstrapServices()、startCoreServices()、startOtherServices()方法啟動一些服務,以前兩個方法為例看一下代碼
startBootstrapServices()方法
啟動一些引導服務,代碼如下
private void startBootstrapServices() {
// 創建SystemConfig,進行權限的獲取
SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
// 開啟安裝器服務
Installer installer = mSystemServiceManager.startService(Installer.class);
// 設備識別器服務
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
// 啟動並初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
// 啟動電量管理服務
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 初始化電量管理器
mActivityManagerService.initPowerManagement();
if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
traceBeginAndSlog("StartRecoverySystemService");
// 啟動RecoverySystem服務
mSystemServiceManager.startService(RecoverySystemService.class);
}
// 標記裸機已經啟動完了,如果我們困在了運行時的重啟循環中,這個標記可以跳出這個循環
RescueParty.noteBoot(mSystemContext);
// 啟動燈光服務,包括背景亮度、閃光燈等
mSystemServiceManager.startService(LightsService.class);
// 啟動顯示服務,用來顯示UI
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
// 開始開機動畫
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// 加密模式下,只運行內核應用,此處先設置標誌位
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
mOnlyCore = true;
}
// 開啟包管理器服務
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
// 獲取包管理器
mPackageManager = mSystemContext.getPackageManager();
if (!mOnlyCore) {
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
false);
if (!disableOtaDexopt) {
try {
// OTADexOpt(空中下載dex並優化,用於OTA升級)使能時,啟動OTA升級服務
OtaDexoptService.main(mSystemContext, mPackageManagerService);
} catch (Throwable e) {
..
} finally {
..
}
}
}
// 啟動用戶管理服務
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
traceBeginAndSlog("InitAttributerCache");
// 從系統包中初始化屬性資源
AttributeCache.init(mSystemContext);
// 設置系統進程
mActivityManagerService.setSystemProcess();
// 設置ui的調度策略
mDisplayManagerService.setupSchedulerPolicies();
// 啟動OverlayManagerService,用於定制系統界面
mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
// 開啟傳感器服務
mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
traceLog.traceBegin(START_SENSOR_SERVICE);
startSensorService();
traceLog.traceEnd();
}, START_SENSOR_SERVICE);
}
開啟了一些服務,無需多解釋
startCoreServices()方法
也是啟動一些服務,代碼如下
private void startCoreServices() {
// 啟動DropBox服務,用來記錄系統日誌
mSystemServiceManager.startService(DropBoxManagerService.class);
// 啟動電池服務
mSystemServiceManager.startService(BatteryService.class);
traceBeginAndSlog("StartUsageService");
// 啟動使用狀態服務
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// 啟動WebView更新服務
mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
}
結語
SystemService的啟動過程就是如此,主要還是啟動一些服務
安卓彩38平臺出租開發學習之SystemServer啟動過程