当前位置:   article > 正文

安卓开发学习之SystemServer启动过程_initbeforestartservices

initbeforestartservices

背景

这两天有一个需求得联调,在等待服务端同事完事,等待过程中,阅读了一下Android8.0里SystemServer的启动过程,除了设置时区语言这些,其实主要就是初始化了系统上下文以及一些服务的启动。


main()方法

SystemServer是一个进程,由zygote进程fork出来,所以它的入口方法就是main方法,代码如下

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

直接就是new了一个SystemServer,而后执行run()方法


run()方法

方法比较长,代码如下

  1. private void run() {
  2. try {
  3. traceBeginAndSlog("InitBeforeStartServices");
  4. // 如果当前系统时间早于1970年元月1号,就更新之为1970年元月1号
  5. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
  6. SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
  7. }
  8. // 设置时区
  9. String timezoneProperty = SystemProperties.get("persist.sys.timezone");
  10. if (timezoneProperty == null || timezoneProperty.isEmpty()) {
  11. SystemProperties.set("persist.sys.timezone", "GMT"); // 默认时区是格林尼治时区
  12. }
  13. // 设置系统语言
  14. if (!SystemProperties.get("persist.sys.language").isEmpty()) {
  15. final String languageTag = Locale.getDefault().toLanguageTag();
  16. SystemProperties.set("persist.sys.locale", languageTag);
  17. SystemProperties.set("persist.sys.language", "");
  18. SystemProperties.set("persist.sys.country", "");
  19. SystemProperties.set("persist.sys.localevar", "");
  20. }
  21. // 系统Server不能进行非oneway通信,因为非oneway通信要等待对方的恢复,这个等待过程是阻塞的
  22. Binder.setWarnOnBlocking(true); // 所以设置阻塞时警告
  23. // 正式启动SystemServer
  24. int uptimeMillis = (int) SystemClock.elapsedRealtime();
  25. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
  26. if (!mRuntimeRestart) {
  27. MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
  28. }
  29. // 设置vmLibrary
  30. SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
  31. // Enable the sampling profiler.
  32. if (SamplingProfilerIntegration.isEnabled()) {
  33. SamplingProfilerIntegration.start();
  34. mProfilerSnapshotTimer = new Timer();
  35. mProfilerSnapshotTimer.schedule(new TimerTask() {
  36. @Override
  37. public void run() {
  38. SamplingProfilerIntegration.writeSnapshot("system_server", null);
  39. }
  40. }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
  41. }
  42. // 清除内存增长上限,因为加载SystemServer需要很多内存
  43. VMRuntime.getRuntime().clearGrowthLimit();
  44. // 设置内存利用率最大是0.8
  45. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
  46. // 初始化指纹系统
  47. Build.ensureFingerprintProperty();
  48. // 设置访问环境变量(例如sd卡路径等)时,必须指定用户
  49. Environment.setUserRequired(true);
  50. // 设置系统的Bundle是可defuse的,意为如果在解析bundle的时候,忽略发生的badParcelableException
  51. // 那个异常如果发送,就直接清空这个Bundle的内容。所以defuse使能最好在Bundle到了终点后再设置,因为这样总不会导致下流再失去bundle的内容
  52. BaseBundle.setShouldDefuse(true);
  53. // 保证进入SystemServer的binder都运行在前台
  54. BinderInternal.disableBackgroundScheduling(true);
  55. // 设置最大线程数为31
  56. BinderInternal.setMaxThreads(sMaxBinderThreads);
  57. // 设置当前线程(主线程)也是在前台进行
  58. android.os.Process.setThreadPriority(
  59. android.os.Process.THREAD_PRIORITY_FOREGROUND);
  60. android.os.Process.setCanSelfBackground(false); // 主线程不能自己切到后台
  61. Looper.prepareMainLooper(); // 主线程的消息循环开始
  62. // 加载native服务
  63. System.loadLibrary("android_servers");
  64. // 检测上次是否成功关机
  65. performPendingShutdown();
  66. // 初始化系统上下文
  67. createSystemContext();
  68. // 初始化SysytemServiceManager,并把它添加到LocalServices中
  69. mSystemServiceManager = new SystemServiceManager(mSystemContext);
  70. mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
  71. LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
  72. // 创建SystemServerInit线程池的单例
  73. SystemServerInitThreadPool.get();
  74. } finally {
  75. traceEnd();
  76. }
  77. // 启动一些服务
  78. // Start services.
  79. try {
  80. traceBeginAndSlog("StartServices");
  81. startBootstrapServices(); // 启动引导服务
  82. startCoreServices(); // 启动核心服务
  83. startOtherServices(); // 启动其他服务
  84. SystemServerInitThreadPool.shutdown();
  85. } catch (Throwable ex) {
  86. ...
  87. } finally {
  88. traceEnd();
  89. }
  90. ... // 日志
  91. // Loop forever.
  92. // 开始消息循环
  93. Looper.loop();
  94. throw new RuntimeException("Main thread loop unexpectedly exited"); // 消息循环是不能退出的
  95. }

代码多但是逻辑并不复杂,值得注意的方法除了启动引导服务、核心服务和其他服务外,再就是检测上次关机是否成功的performPendingShutdown()方法,这个方法主要是针对recovery模式下系统更新引起的重启,这种情况要多重启一次。而这里只是设置了一下sys.powerctl属性,没有执行重启操作


performPendingShutdown()方法

代码如下

  1. private void performPendingShutdown() {
  2. final String shutdownAction = SystemProperties.get(
  3. ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); // 获取上次的关机信息
  4. if (shutdownAction != null && shutdownAction.length() > 0) {
  5. boolean reboot = (shutdownAction.charAt(0) == '1'); // 关机信息第一位表示关机是否是为了重启
  6. final String reason;
  7. if (shutdownAction.length() > 1) {
  8. reason = shutdownAction.substring(1, shutdownAction.length()); // 第一位往后表示关机的原因
  9. } else {
  10. reason = null;
  11. }
  12. if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
  13. /*
  14. * 关机原因是否是REBOOT_RECOVERY_UPDATE,也就是recovery模式下,为了执行系统更新而关的机
  15. * 这种情况下,一定会多重启一次,多的这一次重启,原因就不是REBOOT_RECOVERY_UPDATE了
  16. * @hide
  17.    public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
  18. */
  19. File packageFile = new File(UNCRYPT_PACKAGE_FILE);
  20. if (packageFile.exists()) {
  21. String filename = null;
  22. try {
  23. filename = FileUtils.readTextFile(packageFile, 0, null); // 读取uncrypt_file的内容,获取的是一个文件名
  24. } catch (IOException e) {
  25. Slog.e(TAG, "Error reading uncrypt package file", e);
  26. }
  27. if (filename != null && filename.startsWith("/data")) { // 如果读出来的文件名以/data开头,也就是在data目录内
  28. if (!new File(BLOCK_MAP_FILE).exists()) { // 如果block.map文件不存在,直接抛异常,重启失败
  29. Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
  30. "unexpected runtime restart?");
  31. return;
  32. }
  33. }
  34. }
  35. }
  36. ShutdownThread.rebootOrShutdown(null, reboot, reason);
  37. }
  38. }

主要是调用了ShutdownThread.rebootOrShutdown()方法,这个方法只是保存了一下sys.powerctl属性,代码如下

  1. public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
  2. if (reboot) {
  3. .. // 日志
  4. PowerManagerService.lowLevelReboot(reason);
  5. .. // 日志
  6. reason = null;
  7. } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
  8. // 关机前要进行振动
  9. Vibrator vibrator = new SystemVibrator(context); // 振动器
  10. try {
  11. vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES); // 传入振动持续时间和振动方式
  12. } catch (Exception e) {
  13. .. // 日志
  14. }
  15. try {
  16. Thread.sleep(SHUTDOWN_VIBRATE_MS); // 振动是异步的,所以当前线程要阻塞一会儿,保证振动完了,再关机
  17. } catch (InterruptedException unused) {
  18. }
  19. }
  20. // Shutdown power
  21. PowerManagerService.lowLevelShutdown(reason);

如果是进来这个方法是要重启,reboot就是真,先调用PowerManagerService.lowLevelReboot()方法,传入重启原因reason。此方法代码如下

  1. public static void lowLevelReboot(String reason) {
  2. if (reason == null) {
  3. reason = "";
  4. }
  5. if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
  6. sQuiescent = true;
  7. reason = "";
  8. } else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
  9. sQuiescent = true;
  10. reason = reason.substring(0,
  11. reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
  12. }
  13. if (reason.equals(PowerManager.REBOOT_RECOVERY)
  14. || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) { // 如果reason是或REBOOT_RECOVERY或REBOOT_RECOVERY_UPDATE,就把reason换成recovery
  15. reason = "recovery";
  16. }
  17. if (sQuiescent) {
  18. reason = reason + ",quiescent";
  19. }
  20. SystemProperties.set("sys.powerctl", "reboot," + reason); // 保存sys.powerctl属性
  21. try {
  22. Thread.sleep(20 * 1000L); // 阻塞20秒
  23. } catch (InterruptedException e) {
  24. Thread.currentThread().interrupt();
  25. }
  26. Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
  27. }

可以看到,主要是把重启原因进行转换和保存,然后把重启线程阻塞20s。方法执行完后,就会执行lowLevelShutdown(),代码如下

  1. public static void lowLevelShutdown(String reason) {
  2. if (reason == null) {
  3. reason = "";
  4. }
  5. SystemProperties.set("sys.powerctl", "shutdown," + reason); // 保存/更新sys.powerctl属性
  6. }

回到SystemServer.run()方法,检测完上次是否正常关机后,调用了createSystemContext()方法获取系统上下文,代码如下

  1. private void createSystemContext() {
  2. ActivityThread activityThread = ActivityThread.systemMain();
  3. mSystemContext = activityThread.getSystemContext();
  4. mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
  5. final Context systemUiContext = activityThread.getSystemUiContext();
  6. systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
  7. }
这个方法主要是调用了ActivityThread的一系列方法来实现,参见文章 安卓开发学习之获取系统上下文。然后就是调用startBootstrapServices()、startCoreServices()、startOtherServices()方法启动一些服务,以前两个方法为例看一下代码

startBootstrapServices()方法

启动一些引导服务,代码如下

  1. private void startBootstrapServices() {
  2. // 创建SystemConfig,进行权限的获取
  3. SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
  4. // 开启安装器服务
  5. Installer installer = mSystemServiceManager.startService(Installer.class);
  6. // 设备识别器服务
  7. mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
  8. // 启动并初始化ActivityManagerService
  9. mActivityManagerService = mSystemServiceManager.startService(
  10. ActivityManagerService.Lifecycle.class).getService();
  11. mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
  12. mActivityManagerService.setInstaller(installer);
  13. // 启动电量管理服务
  14. mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
  15. // 初始化电量管理器
  16. mActivityManagerService.initPowerManagement();
  17. if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
  18. traceBeginAndSlog("StartRecoverySystemService");
  19. // 启动RecoverySystem服务
  20. mSystemServiceManager.startService(RecoverySystemService.class);
  21. }
  22. // 标记裸机已经启动完了,如果我们困在了运行时的重启循环中,这个标记可以跳出这个循环
  23. RescueParty.noteBoot(mSystemContext);
  24. // 启动灯光服务,包括背景亮度、闪光灯等
  25. mSystemServiceManager.startService(LightsService.class);
  26. // 启动显示服务,用来显示UI
  27. mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
  28. // 开始开机动画
  29. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
  30. // 加密模式下,只运行内核应用,此处先设置标志位
  31. String cryptState = SystemProperties.get("vold.decrypt");
  32. if (ENCRYPTING_STATE.equals(cryptState)) {
  33. mOnlyCore = true;
  34. } else if (ENCRYPTED_STATE.equals(cryptState)) {
  35. mOnlyCore = true;
  36. }
  37. // 开启包管理器服务
  38. mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
  39. mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
  40. mFirstBoot = mPackageManagerService.isFirstBoot();
  41. // 获取包管理器
  42. mPackageManager = mSystemContext.getPackageManager();
  43. if (!mOnlyCore) {
  44. boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
  45. false);
  46. if (!disableOtaDexopt) {
  47. try {
  48. // OTADexOpt(空中下载dex并优化,用于OTA升级)使能时,启动OTA升级服务
  49. OtaDexoptService.main(mSystemContext, mPackageManagerService);
  50. } catch (Throwable e) {
  51. ..
  52. } finally {
  53.                    ..      
  54. }
  55. }
  56. }
  57. // 启动用户管理服务
  58. mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
  59. traceBeginAndSlog("InitAttributerCache");
  60. // 从系统包中初始化属性资源
  61. AttributeCache.init(mSystemContext);
  62. // 设置系统进程
  63. mActivityManagerService.setSystemProcess();
  64. // 设置ui的调度策略
  65. mDisplayManagerService.setupSchedulerPolicies();
  66. // 启动OverlayManagerService,用于定制系统界面
  67. mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
  68. // 开启传感器服务
  69. mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
  70. BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
  71. SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
  72. traceLog.traceBegin(START_SENSOR_SERVICE);
  73. startSensorService();
  74. traceLog.traceEnd();
  75. }, START_SENSOR_SERVICE);
  76. }

开启了一些服务,无需多解释


startCoreServices()方法

也是启动一些服务,代码如下

  1. private void startCoreServices() {
  2. // 启动DropBox服务,用来记录系统日志
  3. mSystemServiceManager.startService(DropBoxManagerService.class);
  4. // 启动电池服务
  5. mSystemServiceManager.startService(BatteryService.class);
  6. traceBeginAndSlog("StartUsageService");
  7. // 启动使用状态服务
  8. mSystemServiceManager.startService(UsageStatsService.class);
  9. mActivityManagerService.setUsageStatsManager(
  10. LocalServices.getService(UsageStatsManagerInternal.class));
  11. // 启动WebView更新服务
  12. mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
  13. }

结语

SystemService的启动过程就是如此,主要还是启动一些服务

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/227797
推荐阅读
相关标签
  

闽ICP备14008679号