Android SystemUI之启动流程(一)

发布时间:2025-12-10 11:44:38 浏览次数:14

Android  SystemUI系列:

     1.Android  SystemUI之启动流程(一)

     2.Android SystemUI之StatusBar,状态栏(二)

     3.Android SystemUI之下拉菜单,通知栏,快捷面板(三)

     4.Android SystemUI之NavigationBar,导航栏(四)

     5.Android SystemUI之Recent,近期列表(五)

一、简介

          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所具有的功能远远不止这些。如下:
        <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> 声音UI显示
        <item>com.android.systemui.stackpider.Divider</item>控制管理分屏
        <item>com.android.systemui.SystemBars</item>状态栏以及下拉菜单
        <item>com.android.systemui.usb.StorageNotification</item> usb通知管理
        <item>com.android.systemui.power.PowerUI</item>  电源UI显示管理
        <item>com.android.systemui.media.RingtonePlayer</item> 播放铃声
        <item>com.android.systemui.keyboard.KeyboardUI</item>键盘UI
        <item>com.android.systemui.pip.PipUI</item>  提供对于画中画模式的管理
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
        <item>@string/config_systemUIVendorServiceComponent</item>  //com.android.systemui.VendorServices
        <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.fingerprint.FingerprintDialogImpl</item>指纹信息
        <item>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 {@Overridepublic void onCreate() {super.onCreate();((SystemUIApplication) getApplication()).startServicesIfNeeded();// For debugging RescuePartyif (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {throw new RuntimeException();}if (Build.IS_DEBUGGABLE) {// b/71353150 - looking for leaked binder proxiesBinderInternal.nSetBinderProxyCountEnabled(true);BinderInternal.nSetBinderProxyCountWatermarks(1000,900);BinderInternal.setBinderProxyCountCallback(new BinderInternal.BinderProxyLimitListener() {@Overridepublic 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<Class<?>, Object> mComponents = new HashMap<>();@Overridepublic 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.SYSTEMif (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的类/*<string-array name="config_systemUIServiceComponents" translatable="false"><item>com.android.systemui.Dependency</item><item>com.android.systemui.util.NotificationChannels</item><item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</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.stackpider.Divider</item><item>com.android.systemui.SystemBars</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.pip.PipUI</item><item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item><item>@string/config_systemUIVendorServiceComponent</item> //com.android.systemui.VendorServices<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.fingerprint.FingerprintDialogImpl</item><item>com.android.systemui.SliceBroadcas*/registerReceiver(new BroadcastReceiver() {@Overridepublic 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() {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {if (!mBootCompleted) return;// Update names of SystemUi notification channelsNotificationChannels.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 addregisterReceiver(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.* <p>This method must only be called from the main thread.</p>*/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.* <p>This method must only be called from the main thread.</p>*/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_systemUIServiceComponentslog.traceEnd();// Warn if initialization of component takes too longti = 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<OverlayPlugin>() {private ArraySet<OverlayPlugin> mOverlays;@Overridepublic 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);}}@Overridepublic 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就算加载完成,之后的就是每个服务快的加载流程。所以回顾代码看是不是很简单

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477