当前位置:   article > 正文

[Android14] SystemUI的启动_android 14 systemui getstartables

android 14 systemui getstartables

1. 什么是System UI

        SystemUI是Android系统级应用,负责反馈系统及应用状态并与用户保持大量的交互。业务主要涉及的组成部分包括状态栏(Status Bar),通知栏(Notification Panel),锁屏(Keyguard),控制中心(Quick Setting),音量调节(VolumeUI), 近期任务(Recents)等等。

图例如下所示:

2. 源码位置

package name:    com.android.systemui

SystemUI源码目录位于: framework/base/packages/SystemUI

Application位于:        frameworks\base\packages\SystemUI\SystemUIApplication

Service位于:            frameworks\base\services\java\com\android\server\

3. systemUI 启动流程

SystemServer.run()-> startOtherServices()-> startSystemUi()

SystemServer由ZygoteInit进程创建并启动

  1. frameworks/base/services/java/com/android/server/SystemServer.java
  2. /**
  3. * The main entry point from zygote.
  4. */
  5. public static void main(String[] args) {
  6. new SystemServer().run();
  7. }
  8. private void run() {
  9. ......
  10. // Start services.
  11. try {
  12. t.traceBegin("StartServices");
  13. startBootstrapServices(t);
  14. startCoreServices(t);
  15. startOtherServices(t); //在这里会启动startSystemUi()
  16. } catch (Throwable ex) {
  17. Slog.e("System", "******************************************");
  18. Slog.e("System", "************ Failure starting system services", ex);
  19. throw ex;
  20. } finally {
  21. t.traceEnd(); // StartServices
  22. }
  23. ......
  24. }
  25. /**
  26. * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
  27. */
  28. private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
  29. ......
  30. try {
  31. startSystemUi(context, windowManagerF);
  32. } catch (Throwable e) {
  33. reportWtf("starting System UI", e);
  34. }
  35. ......
  36. }
  37. private static void startSystemUi(Context context, WindowManagerService windowManager) {
  38. PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
  39. Intent intent = new Intent();
  40. intent.setComponent(pm.getSystemUiServiceComponent()); //这里
  41. intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
  42. //Slog.d(TAG, "Starting service: " + intent);
  43. context.startServiceAsUser(intent, UserHandle.SYSTEM);
  44. windowManager.onSystemUiStarted();
  45. }

注意看这一段 

intent.setComponent(pm.getSystemUiServiceComponent());

pm是PackageManagerInternal实例,它的getSystemUiServiceComponent()方法是一个抽象方法

  1. frameworks/base/services/core/java/android/content/pm/PackageManagerInternal.java
  2. /**
  3. * @return The SystemUI service component name.
  4. */
  5. public abstract ComponentName getSystemUiServiceComponent();

PackageManagerService实现了该方法,如下:

  1. frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
  2. @Override
  3. public ComponentName getSystemUiServiceComponent() {
  4. return ComponentName.unflattenFromString(mContext.getResources().getString(
  5. com.android.internal.R.string.config_systemUIServiceComponent));
  6. }

 com.android.internal.R.string.config_systemUIServiceComponent的值是

  1. frameworks/base/core/res/res/values/config.xml
  2. <!-- SystemUi service component -->
  3. <string name="config_systemUIServiceComponent" translatable="false"
  4. >com.android.systemui/com.android.systemui.SystemUIService</string>

 unflattenFromString返回的是ComponentName(“com.android.systemui”, “com.android.systemui.SystemUIService”);

unflattenFromString 具体方法如下,很简单,感兴趣的可以看看,不感兴趣的直接跳过就好,这个方法不是重点。

  1. /**
  2. * Recover a ComponentName from a String that was previously created with
  3. * {@link #flattenToString()}. It splits the string at the first '/',
  4. * taking the part before as the package name and the part after as the
  5. * class name. As a special convenience (to use, for example, when
  6. * parsing component names on the command line), if the '/' is immediately
  7. * followed by a '.' then the final class name will be the concatenation
  8. * of the package name with the string following the '/'. Thus
  9. * "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah".
  10. *
  11. * @param str The String that was returned by flattenToString().
  12. * @return Returns a new ComponentName containing the package and class
  13. * names that were encoded in <var>str</var>
  14. *
  15. * @see #flattenToString()
  16. */
  17. public static @Nullable ComponentName unflattenFromString(@NonNull String str) {
  18. int sep = str.indexOf('/');
  19. if (sep < 0 || (sep+1) >= str.length()) {
  20. return null;
  21. }
  22. String pkg = str.substring(0, sep);
  23. String cls = str.substring(sep+1);
  24. if (cls.length() > 0 && cls.charAt(0) == '.') {
  25. cls = pkg + cls;
  26. }
  27. return new ComponentName(pkg, cls);
  28. }

以上代码功能为通过Intent启动了SystemUIService。

于是走到SystemUIService的onCreate()方法

  1. frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
  2. public void onCreate() {
  3. super.onCreate();
  4. // Start all of SystemUI
  5. ((SystemUIApplication) getApplication()).startServicesIfNeeded();
  6. ......
  7. }
  8. public void startServicesIfNeeded() {
  9. String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
  10. startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
  11. }

通过工厂模式获得SystemUI组件列表

  1. frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
  2. public String[] getSystemUIServiceComponents(Resources resources) {
  3. return resources.getStringArray(R.array.config_systemUIServiceComponents);
  4. }

 列表如下:

  1. frameworks/base/packages/SystemUI/res/values/config.xml
  2. <!-- SystemUI Services: The classes of the stuff to start. -->
  3. <string-array name="config_systemUIServiceComponents" translatable="false">
  4. <item>com.android.systemui.util.NotificationChannels</item>
  5. <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
  6. <item>com.android.systemui.recents.Recents</item>
  7. <item>com.android.systemui.volume.VolumeUI</item>
  8. <item>com.android.systemui.stackdivider.Divider</item>
  9. <item>com.android.systemui.statusbar.phone.StatusBar</item>
  10. <item>com.android.systemui.usb.StorageNotification</item>
  11. <item>com.android.systemui.power.PowerUI</item>
  12. <item>com.android.systemui.media.RingtonePlayer</item>
  13. <item>com.android.systemui.keyboard.KeyboardUI</item>
  14. <item>com.android.systemui.pip.PipUI</item>
  15. <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
  16. <item>@string/config_systemUIVendorServiceComponent</item>
  17. <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
  18. <item>com.android.systemui.LatencyTester</item>
  19. <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
  20. <item>com.android.systemui.ScreenDecorations</item>
  21. <item>com.android.systemui.biometrics.AuthController</item>
  22. <item>com.android.systemui.SliceBroadcastRelayHandler</item>
  23. <item>com.android.systemui.SizeCompatModeActivityController</item>
  24. <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
  25. <item>com.android.systemui.theme.ThemeOverlayController</item>
  26. <item>com.android.systemui.accessibility.WindowMagnification</item>
  27. <item>com.android.systemui.accessibility.SystemActions</item>
  28. <item>com.android.systemui.toast.ToastUI</item>
  29. </string-array>

 这个列表是要传到上面的String[] names里的,作为参数,下一步执行startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);

方法如下:

大致内容就是通过反射获得上面列表的类的构造函数,然后通过构造函数创建上面那些类的实例,然后调用这些类的start方法,启动这些systemuI组件。

  1. private void startServicesIfNeeded(String metricsPrefix, String[] services) {
  2. if (mServicesStarted) {
  3. return;
  4. }
  5. mServices = new SystemUI[services.length];
  6. if (!mBootCompleteCache.isBootComplete()) {
  7. // check to see if maybe it was already completed long before we began
  8. // see ActivityManagerService.finishBooting()
  9. if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
  10. mBootCompleteCache.setBootComplete();
  11. if (DEBUG) {
  12. Log.v(TAG, "BOOT_COMPLETED was already sent");
  13. }
  14. }
  15. }
  16. final DumpManager dumpManager = mRootComponent.createDumpManager();
  17. Log.v(TAG, "Starting SystemUI services for user " +
  18. Process.myUserHandle().getIdentifier() + ".");
  19. TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
  20. Trace.TRACE_TAG_APP);
  21. log.traceBegin(metricsPrefix);
  22. final int N = services.length;
  23. for (int i = 0; i < N; i++) {
  24. String clsName = services[i]; //获取类名
  25. if (DEBUG) Log.d(TAG, "loading: " + clsName);
  26. log.traceBegin(metricsPrefix + clsName);
  27. long ti = System.currentTimeMillis();
  28. try {
  29. SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
  30. if (obj == null) {
  31. Constructor constructor = Class.forName(clsName).getConstructor(Context.class); //获取构造函数
  32. obj = (SystemUI) constructor.newInstance(this); //通过构造函数获取实例
  33. }
  34. mServices[i] = obj; //把实例放入到mServices数组中
  35. } catch (ClassNotFoundException
  36. | NoSuchMethodException
  37. | IllegalAccessException
  38. | InstantiationException
  39. | InvocationTargetException ex) {
  40. throw new RuntimeException(ex);
  41. }
  42. if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
  43. mServices[i].start(); //执行start方法
  44. log.traceEnd();
  45. // Warn if initialization of component takes too long
  46. ti = System.currentTimeMillis() - ti;
  47. if (ti > 1000) {
  48. Log.w(TAG, "Initialization of " + clsName + " took " + ti + " ms");
  49. }
  50. if (mBootCompleteCache.isBootComplete()) {
  51. mServices[i].onBootCompleted();
  52. }
  53. dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]);
  54. }
  55. mRootComponent.getInitController().executePostInitTasks();
  56. log.traceEnd();
  57. mServicesStarted = true;
  58. }

SystemUI的启动就是这样。剩下的就是启动具体组件了,例如com.android.systemui.statusbar.phone.StatusBar。

StatusBar也就是状态栏,想看状态栏怎么启动的可以跟到它的start方法,这篇就先到这里。

 

 

 

 

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号