当前位置:   article > 正文

SystemUI分析_android13 systemui启动流程

android13 systemui启动流程

简介

SystemUI是一个持续的进程,为系统提供UI,作为Android系统的核心应用,SystemUI负责反馈系统及应用状态并与用户保持大量的交付。

SystemUI的路径

代码位置在

frameworks\base\packages\SystemUI

apk安装目录

system/priv-app/SystemUI

不同手机的SystemUI可能有所不同,比如小米手机的安装目录就是system/priv-app/MiuiSystemUI

功能划分

  • StatusBar(状态栏):通知消息提示和状态展示
  • NavigationBar(导航栏):返回,HOME,Recent
  • KeyGuard(键盘锁):锁屏模块
  • Recents:近期应用管理,以堆叠的形式展示
  • Notification Panel(通知面板):展示系统或应用的通知内容,提供快速系统设置开关
  • Volume:展示或控制音量的变化:媒体、铃音、通知、通话音量
  • ScreenShot(截屏):长按电源键+音量下键后截屏,用以展示截取的屏幕照片/内容
  • PowerUI:主要处理和Power相关的事件。
  • RingtonePlayer:铃音播放
  • StackDivider:控制管理分屏
  • PipUI:画中画管理(Android7.0)

 

SystemUI启动流程分析

SystemUI的启动是由SystemServer开始。SystemServer由Zygote fork生成的,进程名为system_server,system_server是framework的核心服务。Zygote启动过程中会调用startSystemServer()。SystemUI的启动是从SystemUI的main方法开始。大致流程如下

frameworks/base/services/java/com/android/server/SystemServer.java

  1. /**
  2. * The main entry point from zygote.
  3. */
  4. public static void main(String[] args) {
  5. new SystemServer().run();
  6. }
  7. private void run() {
  8. /*
  9. *省略代码
  10. */
  11. // Start services.
  12. try {
  13. traceBeginAndSlog("StartServices");
  14. startBootstrapServices();
  15. startCoreServices();
  16. startOtherServices(); //systemUI在这个里面启动
  17. SystemServerInitThreadPool.shutdown();
  18. } catch (Throwable ex) {
  19. Slog.e("System", "******************************************");
  20. Slog.e("System", "************ Failure starting system services", ex);
  21. throw ex;
  22. } finally {
  23. traceEnd();
  24. }
  25. }
  26. /**
  27. * Starts a miscellaneous grab bag of stuff that has yet to be refactored
  28. * and organized.
  29. */
  30. private void startOtherServices() {
  31. ... //省略大概1000行
  32. mActivityManagerService.systemReady(() -> {
  33. Slog.i(TAG, "Making services ready");
  34. ...
  35. traceBeginAndSlog("StartSystemUI");
  36. try {
  37. startSystemUi(context, windowManagerF);
  38. } catch (Throwable e) {
  39. reportWtf("starting System UI", e);
  40. }
  41. ...
  42. }
  43. }
  44. static final void startSystemUi(Context context, WindowManagerService windowManager) {
  45. Intent intent = new Intent();
  46. intent.setComponent(new ComponentName("com.android.systemui",
  47. "com.android.systemui.SystemUIService"));
  48. intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
  49. //Slog.d(TAG, "Starting service: " + intent);
  50. context.startServiceAsUser(intent, UserHandle.SYSTEM);
  51. windowManager.onSystemUiStarted();
  52. }

SystemUI的run会启动各种重要的服务,在startOtherServices方法中启动SystemUI()。在startOtherServices()中,通过调用AMS的systemReady()方法通知AMS准备就绪。systemReady()拥有一个名为goingCallback的Runnable实例作为参数,当AMS完成对systemReady()的处理后将会回调这一Runnable的run()方法。startSystemUi这个方法主要是启动com.android.systemui.SystemUIService这个服务,但是需要注意的是,这时候SystemUI还没启动成功,因为startOtherService()方法都还没有执行完毕。所以暂时还不会发送ACTION_BOOT_COMPLETE广播,该广播是在AMS中的finishBooting()中发送的。(该广播在我们SystemUIService中有做监听,用来判断是否完成系统启动)。

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

  1. @Override
  2. 37 public void onCreate() {
  3. 38 super.onCreate();
  4. 39 ((SystemUIApplication) getApplication()).startServicesIfNeeded();
  5. 40
  6. 41 // For debugging RescueParty
  7. 42 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
  8. 43 throw new RuntimeException();
  9. 44 }
  10. 45
  11. 46 if (Build.IS_DEBUGGABLE) {
  12. 47 // b/71353150 - looking for leaked binder proxies
  13. 48 BinderInternal.nSetBinderProxyCountEnabled(true);
  14. 49 BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
  15. 50 BinderInternal.setBinderProxyCountCallback(
  16. 51 new BinderInternal.BinderProxyLimitListener() {
  17. 52 @Override
  18. 53 public void onLimitReached(int uid) {
  19. 54 Slog.w(SystemUIApplication.TAG,
  20. 55 "uid " + uid + " sent too many Binder proxies to uid "
  21. 56 + Process.myUid());
  22. 57 }
  23. 58 }, Dependency.get(Dependency.MAIN_HANDLER));
  24. 59 }
  25. 60 }

这里面的核心代码就只有一行

((SystemUIApplication) getApplication()).startServicesIfNeeded();

这里需要说明一下Service和Application的创建先后

    (1)实例Service;

     (2)实例Application;

     (3)Application实例执行onCreate方法;

     (4)Service实例执行onCrate方法。

所以在SystemUI启动过程中,SystemUIApplication.java的onCreate方法先于SystemUIService.java的oncreate方法。

  1. @Override
  2. 62 public void onCreate() {
  3. 63 super.onCreate();
  4. 64 // Set the application theme that is inherited by all services. Note that setting the
  5. 65 // application theme in the manifest does only work for activities. Keep this in sync with
  6. 66 // the theme set there. 设置主题
  7. 67 setTheme(R.style.Theme_SystemUI);
  8. 68 //android 7.0以后引入,方便定制
  9. 69 SystemUIFactory.createFromConfig(this);
  10. 70 //判断是系统还是切换到其它用户
  11. 71 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
  12. 72 IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
  13. 73 bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
  14. 74 registerReceiver(new BroadcastReceiver() {
  15. 75 @Override
  16. 76 public void onReceive(Context context, Intent intent) {
  17. 77 if (mBootCompleted) return;
  18. 78
  19. 79 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
  20. 80 unregisterReceiver(this);
  21. 81 mBootCompleted = true;
  22. 82 if (mServicesStarted) { //该变量表示SystemUIService是否已经启动了
  23. 83 final int N = mServices.length;
  24. 84 for (int i = 0; i < N; i++) {
  25. 85 mServices[i].onBootCompleted();
  26. 86 }
  27. 87 }
  28. 88
  29. 89
  30. 90 }
  31. 91 }, bootCompletedFilter);
  32. 92
  33. 93 IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
  34. 94 registerReceiver(new BroadcastReceiver() {
  35. 95 @Override
  36. 96 public void onReceive(Context context, Intent intent) {
  37. 97 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
  38. 98 if (!mBootCompleted) return;
  39. 99 // Update names of SystemUi notification channels
  40. 100 NotificationChannels.createAll(context);
  41. 101 }
  42. 102 }
  43. 103 }, localeChangedFilter);
  44. 104 } else {
  45. 105 // We don't need to startServices for sub-process that is doing some tasks.
  46. 106 // (screenshots, sweetsweetdesserts or tuner ..)
  47. 107 String processName = ActivityThread.currentProcessName();
  48. 108 ApplicationInfo info = getApplicationInfo();
  49. 109 if (processName != null && processName.startsWith(info.processName + ":")) {
  50. 110 return;
  51. 111 }
  52. 112 // For a secondary user, boot-completed will never be called because it has already
  53. 113 // been broadcasted on startup for the primary SystemUI process. Instead, for
  54. 114 // components which require the SystemUI component to be initialized per-user, we
  55. 115 // start those components now for the current non-system user.
  56. //非系统用户
  57. 116 startSecondaryUserServicesIfNeeded();
  58. 117 }
  59. 118 }
  60. 119

在Application的oncreate中会区分系统用户和非系统用户来区分流程。如果是系统用户会接收两个广播Intent.ACTION_BOOT_COMPLETED和Intent.ACTION_LOCALE_CHANGED。 Intent.ACTION_BOOT_COMPLETED是监听开机启动,从android 7.0以后,android提供FBE加密方式(https://source.android.google.cn/security/encryption/file-based),在这种情况下,要等到系统启动并锁屏界面解锁后,在进入到桌面过程中,系统才会发送该广播,所以接收该广播的处理逻辑比较延后,SystemUIService启动完后才接收到该广播,所以startServicesIfNeeded方法会先执行,开机广播只会处理一次,就会注销该广播,以后就不会再接收了。mService[]数组存储的是SystemUI的子服务,当整个系统启动完成后,这里面的每个子服务都会执行onBootCompleted()方法,让各个子服务知道系统启动完成了,开始执行任务。

 Intent.ACTION_LOCALE_CHANGED广播是用于监听设备当前区域设置已更改时发出的广播,简单来说就是修改语言时发出的广播(暂时不知道其它动作是否也会发送该广播)。

startSecondaryUserServicesIfNeeded

只会发生在系统启动之后。

  1. /**
  2. 133 * Ensures that all the Secondary user SystemUI services are running. If they are already
  3. 134 * running, this is a no-op. This is needed to conditinally start all the services, as we only
  4. 135 * need to have it in the main process.
  5. 136 * <p>This method must only be called from the main thread.</p>
  6. 137 */
  7. 138 void startSecondaryUserServicesIfNeeded() {
  8. 139 String[] names =
  9. 140 getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser);//需要启动的服务
  10. 141 startServicesIfNeeded(names);
  11. 142 }

config_systemUIServiceComponentsPerUser在frameworks/base/packages/SystemUI/res/values/config.xml中,需要说明的是,Android9.0才引入这种模式,之前版本都是通过数组直接写在代码中。

  1. <!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents -->
  2. 359 <string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
  3. 360 <item>com.android.systemui.Dependency</item> //一种静态依赖项
  4. 361 <item>com.android.systemui.util.NotificationChannels</item> //通知
  5. 362 <item>com.android.systemui.recents.Recents</item> //多任务
  6. 363 </string-array>

再看一下

  1. /**
  2. 121 * Makes sure that all the SystemUI services are running. If they are already running, this is a
  3. 122 * no-op. This is needed to conditinally start all the services, as we only need to have it in
  4. 123 * the main process.
  5. 124 * <p>This method must only be called from the main thread.</p>
  6. 125 */
  7. 126
  8. 127 public void startServicesIfNeeded() {
  9. 128 String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
  10. 129 startServicesIfNeeded(names);
  11. 130 }

需要启动以下服务

  1. <!-- SystemUI Services: The classes of the stuff to start. -->
  2. 331 <string-array name="config_systemUIServiceComponents" translatable="false">
  3. 332 <item>com.android.systemui.Dependency</item>
  4. 333 <item>com.android.systemui.util.NotificationChannels</item>
  5. 334 <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
  6. 335 <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
  7. 336 <item>com.android.systemui.recents.Recents</item>
  8. 337 <item>com.android.systemui.volume.VolumeUI</item>
  9. 338 <item>com.android.systemui.stackdivider.Divider</item>
  10. 339 <item>com.android.systemui.SystemBars</item>
  11. 340 <item>com.android.systemui.usb.StorageNotification</item>
  12. 341 <item>com.android.systemui.power.PowerUI</item>
  13. 342 <item>com.android.systemui.media.RingtonePlayer</item>
  14. 343 <item>com.android.systemui.keyboard.KeyboardUI</item>
  15. 344 <item>com.android.systemui.pip.PipUI</item>
  16. 345 <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
  17. 346 <item>@string/config_systemUIVendorServiceComponent</item>
  18. 347 <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
  19. 348 <item>com.android.systemui.LatencyTester</item>
  20. 349 <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
  21. 350 <item>com.android.systemui.ScreenDecorations</item>
  22. 351 <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
  23. 352 <item>com.android.systemui.SliceBroadcastRelayHandler</item>
  24. 353 </string-array>

最终是在

  1. private void startServicesIfNeeded(String[] services) {
  2. 145 if (mServicesStarted) { //如果SystemUI已经启动就返回
  3. 146 return;
  4. 147 }
  5. 148 mServices = new SystemUI[services.length];
  6. 149
  7. 150 if (!mBootCompleted) {
  8. 151 // check to see if maybe it was already completed long before we began
  9. 152 // see ActivityManagerService.finishBooting()
  10. 153 if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
  11. 154 mBootCompleted = true;
  12. 155 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
  13. 156 }
  14. 157 }
  15. 158
  16. 159 Log.v(TAG, "Starting SystemUI services for user " +
  17. 160 Process.myUserHandle().getIdentifier() + ".");
  18. 161 TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
  19. 162 Trace.TRACE_TAG_APP);
  20. 163 log.traceBegin("StartServices");
  21. 164 final int N = services.length;
  22. 165 for (int i = 0; i < N; i++) {
  23. 166 String clsName = services[i];
  24. 167 if (DEBUG) Log.d(TAG, "loading: " + clsName);
  25. 168 log.traceBegin("StartServices" + clsName);
  26. 169 long ti = System.currentTimeMillis();
  27. 170 Class cls;
  28. 171 try {
  29. 172 cls = Class.forName(clsName);
  30. 173 mServices[i] = (SystemUI) cls.newInstance();
  31. 174 } catch(ClassNotFoundException ex){
  32. 175 throw new RuntimeException(ex);
  33. 176 } catch (IllegalAccessException ex) {
  34. 177 throw new RuntimeException(ex);
  35. 178 } catch (InstantiationException ex) {
  36. 179 throw new RuntimeException(ex);
  37. 180 }
  38. 181
  39. 182 mServices[i].mContext = this;
  40. 183 mServices[i].mComponents = mComponents;
  41. 184 if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
  42. 185 mServices[i].start(); //启动子服务
  43. 186 log.traceEnd();
  44. 187
  45. 188 // Warn if initialization of component takes too long
  46. 189 ti = System.currentTimeMillis() - ti;
  47. 190 if (ti > 1000) {
  48. 191 Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
  49. 192 }
  50. 193 if (mBootCompleted) { //如果已经启动完成
  51. 194 mServices[i].onBootCompleted();
  52. 195 }
  53. 196 }
  54. 197 log.traceEnd();
  55. 198 Dependency.get(PluginManager.class).addPluginListener(
  56. 199 new PluginListener<OverlayPlugin>() {
  57. 200 private ArraySet<OverlayPlugin> mOverlays;
  58. 201
  59. 202 @Override
  60. 203 public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
  61. 204 StatusBar statusBar = getComponent(StatusBar.class);
  62. 205 if (statusBar != null) {
  63. 206 plugin.setup(statusBar.getStatusBarWindow(),
  64. 207 statusBar.getNavigationBarView());
  65. 208 }
  66. 209 // Lazy init.
  67. 210 if (mOverlays == null) mOverlays = new ArraySet<>();
  68. 211 if (plugin.holdStatusBarOpen()) {
  69. 212 mOverlays.add(plugin);
  70. 213 Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
  71. 214 mOverlays.forEach(o -> o.setCollapseDesired(b)));
  72. 215 Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
  73. 216 mOverlays.size() != 0);
  74. 217
  75. 218 }
  76. 219 }
  77. 220
  78. 221 @Override
  79. 222 public void onPluginDisconnected(OverlayPlugin plugin) {
  80. 223 mOverlays.remove(plugin);
  81. 224 Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
  82. 225 mOverlays.size() != 0);
  83. 226 }
  84. 227 }, OverlayPlugin.class, true /* Allow multiple plugins */);
  85. 228
  86. 229 mServicesStarted = true;
  87. 230 }

这里主要通过反射的方式将前面的各个子服务实例化,并执行对这些对象中的start方法,来启动这些服务。

至此,SystemUI的启动分析完成,后面分析单个功能。

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

闽ICP备14008679号