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 开发之发动流程

  • AndroidCodeSearch
  • Android源码在线
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。