Android原生系统SystemUI启动流程--SystemUI学习进度(一)

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) 中

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

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

注释中说明,SystemUI 是由 Zygote (Zygote相关参考文章) 进程启动的。

java 复制代码
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 方法实现如下。

java 复制代码
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
java 复制代码
372      /**
373       * @return The SystemUI service component name.
374       */
375      public abstract ComponentName getSystemUiServiceComponent();

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

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

java 复制代码
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 中

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()方法

java 复制代码
@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

  • 如果不是系统启动,例如多用户登录使用的情况,这时候系统其实已经启动过了,就会走 else 的分支进入到 startSecondaryUserServicesIfNeeded()用于启动 SystemUI 所需的服务组件,这个分支是根据用户来启动相应的服务的。

java 复制代码
    /**
     * Ensures that all the Secondary user SystemUI services are running. If they are already
     * running, this is a no-op. This is needed to conditionally 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>
     */
    void startSecondaryUserServicesIfNeeded() {
        String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponentsPerUser(
                getResources());
        startServicesIfNeeded(/* metricsPrefix= */ "StartSecondaryServices", names);
    }

通过SystemUIFactory获取到服务组件的名称,然后执行startServicesIfNeeded()启动服务组件。

java 复制代码
/**
 * Returns the list of system UI components that should be started per user.
 */    
 public String[] getSystemUIServiceComponentsPerUser(Resources resources) {
     return resources.getStringArray(R.array.config_systemUIServiceComponentsPerUser);
}

组件名为config_systemUIServiceComponentsPerUser

xml 复制代码
<!-- 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

java 复制代码
    @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

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 开发之启动流程 Zygote相关

相关推荐
雨白14 小时前
Android 快捷方式实战指南:静态、动态与固定快捷方式详解
android
hqk14 小时前
鸿蒙项目实战:手把手带你实现 WanAndroid 布局与交互
android·前端·harmonyos
LING14 小时前
RN容器启动优化实践
android·react native
恋猫de小郭17 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker1 天前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴1 天前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭1 天前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab1 天前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe2 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农2 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos