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

相关推荐
yan123684 小时前
Linux 驱动之设备树
android·linux·驱动开发·linux驱动
aningxiaoxixi6 小时前
android stdio 的布局属性
android
CYRUS STUDIO8 小时前
FART 自动化脱壳框架一些 bug 修复记录
android·bug·逆向·fart·脱壳
寻找优秀的自己9 小时前
Cocos 打包 APK 兼容环境表(Android API Level 10~15)
android·cocos2d
大胃粥9 小时前
WMS& SF& IMS: 焦点窗口更新框架
android
QING6189 小时前
Gradle 核心配置属性详解 - 新手指南(二)
android·前端·gradle
QING6189 小时前
Gradle 核心配置属性详解 - 新手指南(一)
android·前端·gradle
_一条咸鱼_12 小时前
Android Runtime内存管理子系统启动流程原理(13)
android·面试·android jetpack
法迪13 小时前
Android的uid~package~pid的关系
android