Android12 源码分析 SystemUI 学习(1) --- SystemUI启动流程

SystemUI 学习(1) — SystemUI启动流程

启动流程主要有两个部分

  • 在 framework 中启动 SystemUIService
  • 在 SystemUIService 中启动 SystemUI 所需的各种组件

SystemUI 是一个系统应用,即为一个apk。所以它也会有入口 application 。它是由SystemServer 进程启动的。

注:参考 android-12.0.0_r3 分支中的代码(网站可能会出现无法打开的情况,可以参考Android官方的(需要外网)AndroidCodeSearch)

framework 中的流程
SystemServer

SystemServer.java (frameworks/base/services/java/com/android/server/SystemServer.java) 中

进程入口会启动很多和系统相关的应用、服务。

606    /**
607       * The main entry point from zygote.
608       */
609      public static void main(String[] args) {
610          new SystemServer().run();
611      }

注释中说明,SystemUI 是由 Zygote 进程启动的。

2929          t.traceBegin("StartSystemUI");
2930          try {
2931              startSystemUi(context, windowManagerF);
2932          } catch (Throwable e) {
2933              reportWtf("starting System UI", e);
2934          }
2935          t.traceEnd();
2936  
2937          t.traceEnd(); // startOtherServices

其中 startSystemUi 方法实现如下。

3024      private static void startSystemUi(Context context, WindowManagerService 			  windowManager) {
3025          PackageManagerInternal pm =                    									  LocalServices.getService(PackageManagerInternal.class);
3026          Intent intent = new Intent();
3027          intent.setComponent(pm.getSystemUiServiceComponent());
3028          intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
3029          //Slog.d(TAG, "Starting service: " + intent);
3030          context.startServiceAsUser(intent, UserHandle.SYSTEM);
3031          windowManager.onSystemUiStarted();
3032      }

这里通过 PackageManagerInternal.getSystemUiServiceComponent() 方法获取到了 SystemUIService 组件,然后通过 startServiceAsUser 方法启动了服务。

PackageManagerInternal
372      /**
373       * @return The SystemUI service component name.
374       */
375      public abstract ComponentName getSystemUiServiceComponent();

这个方法在 PackageManagerInternal中是个抽象方法。考虑 PMS(PackageManagerService)

里面有一个 PackageManagerInternalImpl 的内部类继承了 PackageManagerInternal 并实现了 getSystemUiServiceComponent() 方法。

27032      private class PackageManagerInternalImpl extends PackageManagerInternal {
           ...
27449          @Override
27450          public ComponentName getSystemUiServiceComponent() {
27451              return  ComponentName.unflattenFromString(mContext
							.getResources()
							.getString(
27452                          com.android.internal.R.string.config_systemUIServiceComponent));
27453          }

其中 config_systemUIServiceComponent 在 frameworks/base/core/res/res/values/config.xml 中

2865     <!-- SystemUi service component -->
2866     <string name="config_systemUIServiceComponent" translatable="false"
2867             >com.android.systemui/com.android.systemui.SystemUIService</string>

小结: framework中的 SystemServer 中的 run 方法启动了系统所需要的各种服务,其中就包括了 SystemUIService。

具体: 通过 PackageManagerInternal 获取到 SystemUIService 的配置名称,然后通过 startServiceAsUser 方法在 startSystemUi 中启动了服务。

SystemUI中的流程

路径 frameworks/base/packages/SystemUI/

SystemUIApplication

onCreate()方法

@Override
public void onCreate() {

    super.onCreate();

    Log.v(TAG, "SystemUIApplication created.");
    ...
    ...
    if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
        // 一般情况下走这里来,例如开关机启动系统
		...
        registerReceiver(new BroadcastReceiver() {
        	@Override
        	public void onReceive(Context context, Intent intent) {
        		if (mBootCompleteCache.isBootComplete()) return;

        		if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
        		unregisterReceiver(this);
        		mBootCompleteCache.setBootComplete();
        		if (mServicesStarted) {
        			final int N = mServices.length;
            		for (int i = 0; i < N; i++) {
            			mServices[i].onBootCompleted();
            		}
        		}
        	}
        }, bootCompletedFilter);
        ...
        
        } else {
        	//多用户或其它非系统操作启动 SystemUi
            // We don't need to startServices for sub-process that is doing some tasks.
            // (screenshots, sweetsweetdesserts or tuner ..)            
            String processName = ActivityThread.currentProcessName();
            ApplicationInfo info = getApplicationInfo();
            if (processName != null && processName.startsWith(info.processName + ":")) {

                return;
            }

            // For a secondary user, boot-completed will never be called because it has already
            // been broadcasted on startup for the primary SystemUI process.  Instead, for
            // components which require the SystemUI component to be initialized per-user, we
            // start those components now for the current non-system user.
            startSecondaryUserServicesIfNeeded();
        }  
    }

  • 如果是系统启动的就会进入到这个分支中,注册监听 boot completed 的通知,最后启动完全启动后就会通知各个组件 onBootCompleted

        /**
         * Makes sure that all the SystemUI services are running. If they are already running, 	       this is a
         * no-op. This is needed to conditinally start all the services, as we only need to have       it in
         * the main process.
         * <p>This method must only be called from the main thread.</p>
         */
    
        public void startServicesIfNeeded() {
            String[] names = SystemUIFactory.getInstance()
                .getSystemUIServiceComponents(getResources());
            startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
        }
    

    定位到SystemUIFactory中的getSystemUIServiceComponents方法

        /** Returns the list of system UI components that should be started. */
        public String[] getSystemUIServiceComponents(Resources resources) {
            return resources.getStringArray(R.array.config_systemUIServiceComponents);
        }
    

    找到资源文件中的config.xml文件,找到config_systemUIServiceComponents

        <!-- SystemUI Services: The classes of the stuff to start. -->
        <string-array name="config_systemUIServiceComponents" translatable="false">
            <item>com.android.systemui.util.NotificationChannels</item>
            <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
            <item>com.android.systemui.recents.Recents</item>
            <item>com.android.systemui.volume.VolumeUI</item>
            <item>com.android.systemui.statusbar.phone.StatusBar</item>
            <item>com.android.systemui.usb.StorageNotification</item>
            <item>com.android.systemui.power.PowerUI</item>
            <item>com.android.systemui.media.RingtonePlayer</item>
            <item>com.android.systemui.keyboard.KeyboardUI</item>
            <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
            <item>@string/config_systemUIVendorServiceComponent</item>
            <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
            <item>com.android.systemui.LatencyTester</item>
            <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
            <item>com.android.systemui.ScreenDecorations</item>
            <item>com.android.systemui.biometrics.AuthController</item>
            <item>com.android.systemui.SliceBroadcastRelayHandler</item>
            <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
            <item>com.android.systemui.theme.ThemeOverlayController</item>
            <item>com.android.systemui.accessibility.WindowMagnification</item>
            <item>com.android.systemui.accessibility.SystemActions</item>
            <item>com.android.systemui.toast.ToastUI</item>
            <item>com.android.systemui.wmshell.WMShell</item>
        </string-array>
    
  • 如果不是系统启动,例如多用户登录使用的情况,这时候系统其实已经启动过了,就会走 else 的分支进入到 startSecondaryUserServicesIfNeeded()用于启动 SystemUI 所需的服务组件,这个分支是根据用户来启动相应的服务的。

    同上可已找到,组件名为config_systemUIServiceComponentsPerUser

    <!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents -->
    <string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
        <item>com.android.systemui.util.NotificationChannels</item>
    </string-array>
    

SystemUIService

    @Override
    public void onCreate() {
        super.onCreate();

        // Start all of SystemUI
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();

        // Finish initializing dump logic
        mLogBufferFreezer.attach(mBroadcastDispatcher);

		...
        ...
        
        // Bind the dump service so we can dump extra info during a bug report
        startServiceAsUser(
                new Intent(getApplicationContext(), SystemUIAuxiliaryDumpService.class),
                UserHandle.SYSTEM);
    }

SystemUIApplication.java

    /**
     * Makes sure that all the SystemUI services are running. If they are already running, 
     this is a
     * no-op. This is needed to conditinally start all the services, 
     as we only need to have it in
     * the main process.
     * <p>This method must only be called from the main thread.</p>
     */

    public void startServicesIfNeeded() {
        String[] names = SystemUIFactory.getInstance()
            .getSystemUIServiceComponents(getResources());
        startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
    }

getSystemUIServiceComponentsgetSystemUIServiceComponentsPerUser流程一致

小结: SystemServer 启动 SystemUIService 之后,就进入到了应用层中,SystemUIApplicationSystemUI 的入口,在 onCreate 方法中做了一些初始化工作,注册监听通知等操作;如果是多用户则会启动了一个组件 NotificationChannels; 然后就进入到 SystemUIService 中,它在 onCreate 方法中也是执行了 SystemUIApplication 中的 startServicesIfNeeded() 方法,并把所有的服务都存在 mServices 数组中。

总结

SystemUI 是一个 persistent 应用,它由操作系统启动,主要流程为

  • Android 系统在开机后会创建 SystemServer 进程,它会启动各种系统所需要的服务,其中就包括 SystemUIService
  • SystemUIService 启动后进入到应用层 SystemUI 中,在 SystemUIApplication 它首先会初始化监听boot completed 等通知,待系统完成启动后会通知各个组件 onBootCompleted
  • 在进入 SystemUIService 中依然执行的 SystemUIApplication 中的startServicesIfNeeded() 方法启动所有 SystemUI 中的组件。
  • 最终的服务启动逻辑都是在 SystemUIApplication 里面,并且都保存在 mServices 数组中。

参考文章:SystemUI 开发之启动流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-情绪零碎-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值