Android SystemUI之启动流程(一)

一、简介

          SystemUI是系统最重要的一个APK,它属于persistent app,什么是persistent app呢?简单的来说就是,具有系统签名,并且在AndroidMainfest中声明persistent=true,如果是使用flag来匹配查找的话:ApplicationInfo.FLAG_PERSISTENT。目前系统具有这类app还有com.mediatek.ims(短信),com.android.phone(电话)。这类的app是在android系统环境准备完成之后启动,比launcher和开机向导启动还早。具体的流程,可以看我之前写的:ActivityManagerService启动之旅(一)

      可能大家都知道SystemUI的重要,那SystemUI有哪些功能呢?导航栏,状态栏,通知栏,近期列表。这个可能是大家比较熟悉的功能,但是其实System所具有的功能远远不止这些。如下:
        com.android.systemui.util.NotificationChannels  通知信息
        com.android.systemui.keyguard.KeyguardViewMediator 锁屏
        com.android.systemui.recents.Recents 近期列表
        com.android.systemui.volume.VolumeUI 声音UI显示
        com.android.systemui.stackdivider.Divider控制管理分屏
        com.android.systemui.SystemBars状态栏以及下拉菜单
        com.android.systemui.usb.StorageNotification usb通知管理
        com.android.systemui.power.PowerUI  电源UI显示管理
        com.android.systemui.media.RingtonePlayer 播放铃声
        com.android.systemui.keyboard.KeyboardUI键盘UI
        com.android.systemui.pip.PipUI  提供对于画中画模式的管理
        com.android.systemui.shortcut.ShortcutKeyDispatcher
        @string/config_systemUIVendorServiceComponent  //com.android.systemui.VendorServices
        com.android.systemui.util.leak.GarbageMonitor$Service
        com.android.systemui.LatencyTester
        com.android.systemui.globalactions.GlobalActionsComponent  关机界面的显示
        com.android.systemui.ScreenDecorations
        com.android.systemui.fingerprint.FingerprintDialogImpl指纹信息
        com.android.systemui.SliceBroadcas

有一点需要说明一下,Android 10之后近期列表的显示被移到Launcher  app里面了。在Launcher3的一个 类中TouchInteractionService.java   IBinder mMyBinder = new IOverviewProxy.Stub() 通过AIDL的方法与systemUI通信。本文的还是以Android 9.0作为研究对象,所以近期列表还是在SystemUI中。

  今后的几章会围绕SystemUI的启动流程、状态栏的加载显示流程,导航栏的加载显示流程,通知栏的加载显示流程以及近期列表的加载显示流程,这五个方面对SystemUI的研究,至于其他,电源UI,锁屏等有时间再研究。

二、SystemUI的启动流程

     如果不讲SystemUI的里面的服务的话,单单讲SystemUI的启动是非常简单的。

  1.启动入口 SystemServer 

 static final void startSystemUi(Context context, WindowManagerService windowManager) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        windowManager.onSystemUiStarted();
    }

启动是不是很简单,startServiceAsUser方法启动SystemUIService。而startSystemUi函数是在什么时候调用呢?

 mActivityManagerService.systemReady(() -> {
			....................
            ....................
            traceBeginAndSlog("StartSystemUI");
            try {
                startSystemUi(context, windowManagerF);
            } catch (Throwable e) {
                reportWtf("starting System UI", e);
            }

在ActvityManagerService调用systemReady函数中有这行代码 if (goingCallback != null) goingCallback.run();当执行到这句话就会执行上面{}里面的代码。

2.SystemUIService

public class SystemUIService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();

        // For debugging RescueParty
        if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
            throw new RuntimeException();
        }

        if (Build.IS_DEBUGGABLE) {
            // b/71353150 - looking for leaked binder proxies
            BinderInternal.nSetBinderProxyCountEnabled(true);
            BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
            BinderInternal.setBinderProxyCountCallback(
                    new BinderInternal.BinderProxyLimitListener() {
                        @Override
                        public void onLimitReached(int uid) {
                            Slog.w(SystemUIApplication.TAG,
                                    "uid " + uid + " sent too many Binder proxies to uid "
                                    + Process.myUid());
                        }
                    }, Dependency.get(Dependency.MAIN_HANDLER));
        }
    }

从上面代码看就是一个service,在oncreate中启动SystemUIApplication.startServicesIfNeeded方法。

3.SystemUIApplication

public class SystemUIApplication extends Application implements SysUiServiceProvider {

    public static final String TAG = "SystemUIService";
    private static final boolean DEBUG = false;

    /**
     * Hold a reference on the stuff we start.
     */
    private SystemUI[] mServices;
    private boolean mServicesStarted;
    private boolean mBootCompleted;
    private final Map, Object> mComponents = new HashMap<>();

    @Override
    public void onCreate() {
        super.onCreate();
        // Set the application theme that is inherited by all services. Note that setting the
        // application theme in the manifest does only work for activities. Keep this in sync with
        // the theme set there.
        setTheme(R.style.Theme_SystemUI);
				

        SystemUIFactory.createFromConfig(this);
//正常情况下SystemUI是有SystemServer启动的,Process.myUserHandle()=UserHandle.SYSTEM
        if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
            IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
            bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);//优先接受开机广播
            //接收开机广播,并且启动所有继承SystemUI的类的onBootCompleted方法。
            //继承systemUI的类有哪些?
            //config  里面有一个数组config_systemUIServiceComponents里面罗列了继承systeUI的类
            /*
         
        com.android.systemui.Dependency
        com.android.systemui.util.NotificationChannels
        com.android.systemui.statusbar.CommandQueue$CommandQueueStart
        com.android.systemui.keyguard.KeyguardViewMediator
        com.android.systemui.recents.Recents
        com.android.systemui.volume.VolumeUI
        com.android.systemui.stackdivider.Divider
        com.android.systemui.SystemBars
        com.android.systemui.usb.StorageNotification
        com.android.systemui.power.PowerUI
        com.android.systemui.media.RingtonePlayer
        com.android.systemui.keyboard.KeyboardUI
        com.android.systemui.pip.PipUI
        com.android.systemui.shortcut.ShortcutKeyDispatcher
        @string/config_systemUIVendorServiceComponent  //com.android.systemui.VendorServices
        com.android.systemui.util.leak.GarbageMonitor$Service
        com.android.systemui.LatencyTester
        com.android.systemui.globalactions.GlobalActionsComponent
        com.android.systemui.ScreenDecorations
        com.android.systemui.fingerprint.FingerprintDialogImpl
        com.android.systemui.SliceBroadcas

            */
            registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
              if (StatusBar.SYSTEMUI_START_DEBUG) Log.i(StatusBar.TAG_XIAO, "BOOT_COMPLETED received");
                    if (mBootCompleted) return;

                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
                    unregisterReceiver(this);
                    mBootCompleted = true;
                    if (mServicesStarted) {
                        final int N = mServices.length;
                        for (int i = 0; i < N; i++) {
                            mServices[i].onBootCompleted();
                        }
                    }


                }
            }, bootCompletedFilter);

            IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);//监听本地变化的,比如语言
            registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
                        if (!mBootCompleted) return;
                        // Update names of SystemUi notification channels
                        NotificationChannels.createAll(context);//更新通知栏的信息
                    }
                }
            }, localeChangedFilter);
        } else {
            // 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();
        }
		
		//@along add
		registerReceiver(new LauncherReceiver(), new IntentFilter("android.intent.action.INST_LAUNCHER"));
    }

    /**
     * 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.
     * 

This method must only be called from the main thread.

*/ public void startServicesIfNeeded() { String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents); startServicesIfNeeded(names); } /** * Ensures that all the Secondary user 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. *

This method must only be called from the main thread.

*/ void startSecondaryUserServicesIfNeeded() { String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser); startServicesIfNeeded(names); } private void startServicesIfNeeded(String[] services) { if (mServicesStarted) { return; } mServices = new SystemUI[services.length]; if (!mBootCompleted) { // check to see if maybe it was already completed long before we began // see ActivityManagerService.finishBooting() if ("1".equals(SystemProperties.get("sys.boot_completed"))) { mBootCompleted = true; if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent"); } } Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming", Trace.TRACE_TAG_APP); log.traceBegin("StartServices"); final int N = services.length; for (int i = 0; i < N; i++) { String clsName = services[i]; if (DEBUG) Log.d(TAG, "loading: " + clsName); log.traceBegin("StartServices" + clsName); long ti = System.currentTimeMillis(); Class cls; try { cls = Class.forName(clsName); mServices[i] = (SystemUI) cls.newInstance(); } catch(ClassNotFoundException ex){ throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start();//启动继承SystemUI的类。具体有哪些类可以查看config 里面有一个数组config_systemUIServiceComponents log.traceEnd(); // Warn if initialization of component takes too long ti = System.currentTimeMillis() - ti; if (ti > 1000) { Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms"); } if (mBootCompleted) { mServices[i].onBootCompleted(); } } log.traceEnd(); Dependency.get(PluginManager.class).addPluginListener( new PluginListener() { private ArraySet mOverlays; @Override public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) { StatusBar statusBar = getComponent(StatusBar.class); Log.i(StatusBar.TAG_XIAO,"SystemUIApplication onPluginConnected plugin "+ plugin+",pluginContext:"+pluginContext); if (statusBar != null) { plugin.setup(statusBar.getStatusBarWindow(), statusBar.getNavigationBarView()); } // Lazy init. if (mOverlays == null) mOverlays = new ArraySet<>(); if (plugin.holdStatusBarOpen()) { mOverlays.add(plugin); Dependency.get(StatusBarWindowManager.class).setStateListener(b -> mOverlays.forEach(o -> o.setCollapseDesired(b))); Dependency.get(StatusBarWindowManager.class).setForcePluginOpen( mOverlays.size() != 0); } } @Override public void onPluginDisconnected(OverlayPlugin plugin) { Log.i(StatusBar.TAG_XIAO,"SystemUIApplication onPluginDisconnected plugin "+ plugin); mOverlays.remove(plugin); Dependency.get(StatusBarWindowManager.class).setForcePluginOpen( mOverlays.size() != 0); } }, OverlayPlugin.class, true /* Allow multiple plugins */); mServicesStarted = true;//systemui servcie启动完成 }

从上面的代码来看就是加载一堆服务,这些服务都定义在config_systemUIServiceComponents,这些类都有一个特点就是继承SystemUI类。到这里SystemUI就算加载完成,之后的就是每个服务快的加载流程。所以回顾代码看是不是很简单

你可能感兴趣的:(#,SystemUI,Android)