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相关

相关推荐
游戏开发爱好者87 分钟前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码203512 分钟前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥28 分钟前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓39 分钟前
[JDBC]元数据
android
独行soc1 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能1 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿1 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市
独行soc1 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
2501_915106322 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview