SystemUi启动分析

//----------------------------StatusBarManagerService托管CommandQueue--------------------------------

开机后在com.android.server.SystemServer的initAndLoop中

            if (!disableSystemUI) {
                try {
                    Slog.i(TAG, "Status Bar");
                    statusBar = new StatusBarManagerService(context, wm);
                    ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
                } catch (Throwable e) {
                    reportWtf("starting StatusBarManagerService", e);
                }
            }
在其他地方可以通过
    IStatusBarService getStatusBarService() {
        synchronized (mServiceAquireLock) {
            if (mStatusBarService == null) {
                mStatusBarService = IStatusBarService.Stub.asInterface(
                        ServiceManager.getService("statusbar"));
            }
            return mStatusBarService;
        }
    }
得到com.android.server.StatusBarManagerService对象,StatusBarManagerService托管IStatusBar对象,IStatusBar为CommandQueue通过registerStatusBar传递进来
    // ================================================================================
    // Callbacks from the status bar service.
    // ================================================================================
    public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
            List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
            int switches[], List<IBinder> binders) {
        enforceStatusBarService();

        Slog.i(TAG, "registerStatusBar bar=" + bar);
        mBar = bar;
        synchronized (mIcons) {
            iconList.copyFrom(mIcons);
        }
        synchronized (mNotifications) {
            for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
                notificationKeys.add(e.getKey());
                notifications.add(e.getValue());
            }
        }
        synchronized (mLock) {
            switches[0] = gatherDisableActionsLocked(mCurrentUserId);
            switches[1] = mSystemUiVisibility;
            switches[2] = mMenuVisible ? 1 : 0;
            switches[3] = mImeWindowVis;
            switches[4] = mImeBackDisposition;
            binders.add(mImeToken);
        }
        switches[5] = mWindowManager.isHardKeyboardAvailable() ? 1 : 0;
        switches[6] = mWindowManager.isHardKeyboardEnabled() ? 1 : 0;
    }

在com.android.systemui.statusbar.BaseStatusBar的start()方法中对这个StatusBarManagerService进行了registerStatusBar,把registerStatusBar传递进去。BaseStatusBar被PhoneStatusBar继承了.

//-------------------------------------SystemUI的各项服务启动-------------------------------------

在Systemserver的ActivityManagerService的systemReady()回调中调用了startSystemUi()方法启动SystemUIService

    static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
    }
SystemUIService中对如下Service进行了构造,并且启动了start方法
    private final Class<?>[] SERVICES = new Class[] {
            com.android.systemui.recent.Recents.class,
            com.android.systemui.statusbar.SystemBars.class,
            com.android.systemui.usb.StorageNotification.class,
            com.android.systemui.power.PowerUI.class,
            com.android.systemui.media.RingtonePlayer.class,
            com.android.systemui.settings.SettingsUI.class,
            com.android.systemui.sim.SimDetectorUI.class,
            com.android.systemui.storage.DataProtect.class,
        };

    /**
     * Hold a reference on the stuff we start.
     */
    private final SystemUI[] mServices = new SystemUI[SERVICES.length];

    @Override
    public void onCreate() {
        HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
        final int N = SERVICES.length;
        for (int i=0; i<N; i++) {
            Class<?> cl = SERVICES[i];
            Log.d(TAG, "loading: " + cl);
            try {
                mServices[i] = (SystemUI)cl.newInstance();
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }
            mServices[i].mContext = this;
            mServices[i].mComponents = components;
            Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        for (SystemUI ui: mServices) {
            ui.onConfigurationChanged(newConfig);
        }
    }

如上PowerUI中的start方法内对电池电量变化以及屏幕亮灭进行了注册监听.

//-----------------------------------------通知栏、状态栏-----------------------------------------------------

SystemBars内构造了PhoneStatusBar并调用start方法。

    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        final String clsName = mContext.getString(R.string.config_statusBarComponent);
        if (clsName == null || clsName.length() == 0) {
            throw andLog("No status bar component configured", null);
        }
        Class<?> cls = null;
        try {
            cls = mContext.getClassLoader().loadClass(clsName);
        } catch (Throwable t) {
            throw andLog("Error loading status bar component: " + clsName, t);
        }
        try {
            mStatusBar = (BaseStatusBar) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

下面看PhoneStatusBar的start方法

    @Override
    public void start() {
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();

        CustomTheme currentTheme = mContext.getResources().getConfiguration().customTheme;
        if (currentTheme != null) {
            mCurrentTheme = (CustomTheme)currentTheme.clone();
        }

        super.start(); // calls createAndAddWindows()

        addNavigationBar();

        SettingsObserver observer = new SettingsObserver(mHandler);
        observer.observe();
        // Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext);
    }

 super.start()中调用了抽象方法createAndAddWindows(),createAndAddWindows()中

    @Override
    public void createAndAddWindows() {
        addStatusBarWindow();
    }
    private void addStatusBarWindow() {
        // Put up the view
        final int height = getStatusBarHeight();

        // Now that the status bar window encompasses the sliding panel and its
        // translucent backdrop, the entire thing is made TRANSLUCENT and is
        // hardware-accelerated.
        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);

        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

        lp.gravity = getStatusBarGravity();
        lp.setTitle("StatusBar");
        lp.packageName = mContext.getPackageName();

        makeStatusBarView();
        mStatusBarContainer.addView(mStatusBarWindow);
        mWindowManager.addView(mStatusBarContainer, lp);
    }


在makeStatusBarView()中开始构建状态栏与通知栏,使用布局文件super_status_bar.xml,status_bar.xml是状态栏的布局,包含了顶上显示的电源、信号、跳动通知等信息或者图标,super_status_bar中include的status_bar_expanded.xml为下拉展开的布局里面包含ribbon_settings.xml为快捷设置栏,super_status_bar.xml中所include的布局文件quick_settings.xml为切换到所有显示的快捷设置栏。


//-------------------------------------------快捷方式按钮流程-----------------------------------------------------

以网格快捷设置栏为例,在makeStatusBarView()方法中

                mQS = new QuickSettingsController(mContext, mSettingsContainer, this,
                        Settings.System.QUICK_SETTINGS_TILES, false);


如上第4个参数是从Settings.System中取条目的key值,第5个参数决定是哪种模式的快捷设置。QuickSettingsController控制了整个设置的加载,其主要方法

    protected void setupQuickSettings() {
        shutdown();
        mReceiver = new QSBroadcastReceiver();
        mReceiverMap.clear();
        mObserver = new QuickSettingsObserver(mHandler);
        mObserverMap.clear();
        mTileStatusUris.clear();
        loadTiles();
        setupBroadcastReceiver();
        setupContentObserver();
        if (mRibbonMode) {
            for (QuickSettingsTile t : mQuickSettingsTiles) {
                t.switchToRibbonMode();
            }
        }
    }

loadTiles()加载条目

        String tiles = Settings.System.getStringForUser(resolver,
                mSettingsKey, UserHandle.USER_CURRENT);
        if (tiles == null) {
            Log.i(TAG, "Default tiles being loaded");
            tiles = TextUtils.join(TILE_DELIMITER, TILES_DEFAULT);
        }

初始条目由Setting应用中进行设置,默认是QSConstants的静态对象。

对于每个Tile,在构造后都进行了初始化

        for (String tile : tiles.split("\\|")) {
            QuickSettingsTile qs = null;
            if (tile.equals(TILE_BLUETOOTH)) {
               qs = new BluetoothTile(mContext, this, mStatusBarService.mBluetoothController);

            } else if (tile.equals(TILE_AUTOROTATE)) {
                qs = new AutoRotateTile(mContext, this, mHandler);
            } else if (tile.equals(TILE_AIRPLANE)) {
                qs = new AirplaneModeTile(mContext, this, mStatusBarService.mNetworkController);
            } else if (tile.equals(TILE_GPS)) {
                qs = new GPSTile(mContext, this);
            } else if (tile.equals(TILE_MOBILEDATA) && mobileDataSupported) {
                qs = new MobileNetworkTile(mContext, this, mStatusBarService.mNetworkController);
            } else if (tile.equals(TILE_WIFI)) {
                qs = new WiFiTile(mContext, this, mStatusBarService.mNetworkController);
            } else if (tile.equals(TILE_RINGER)) {
                qs = new RingerModeTile(mContext, this);
            } else if (tile.equals(TILE_TORCH)) {
            	qs = new TorchTile(mContext,this);
            }

            if (qs != null) {
                qs.setupQuickSettingsTile(inflater, mContainerView);
                mQuickSettingsTiles.add(qs);
            }
        }

setupBroadcastReceiver()方法为注册监听广播,当收到广播时对所有Tile都调用了onReceive方法进行更新。

如何新增一个Tile?

1、在QSConstants中增加一条对应的String,并且在static方法中add你要增加的。

2、在com.android.systemui.quicksettings内新建一个类继承QuickSettingsTile并实现方法。

3、在QuickSettingsController的loadTiles()方法中for循环内的if判断中增加你要新增的。

4、在Setting App中的QuickSettingsUtil.java中static中register你新增的条目对应的名称以及图标。

主要,由于值是保存在全局数据库内,所以修改后是看不到结果的,如果要看结果,方法一:重新刷版本。方法二:让手机从默认设置中读取值

    public static String getCurrentTiles(Context context, boolean isRibbon) {
        String tiles = Settings.System.getString(context.getContentResolver(),
                isRibbon ? Settings.System.QUICK_SETTINGS_RIBBON_TILES
                         : Settings.System.QUICK_SETTINGS_TILES);
        if (tiles == null) {
            tiles = getDefaultTiles(context);
        }
        return tiles;
    }


比如把上面这个方法内的if判断去掉,让手机把默认值改了后再改回来就行了。


 

### Android 14 SystemUI 源码详解 #### 系统概述 SystemUI 是 Android 系统中的一个重要组件,负责管理系统的用户界面部分,包括但不限于状态栏、通知栏、锁屏界面以及快捷设置等功能。在 Android 14 中,SystemUI 的设计和实现延续了之前版本的核心架构,但在功能扩展性和性能优化方面进行了改进。 #### 启动流程解析 SystemUI启动过程主要依赖于 `config_systemUIServiceComponent` 和 `config_systemUIFactoryComponent` 的配置文件定义。以下是其核心机制: - **Service 定义** 在 `frameworks/base/core/res/res/values/config.xml` 文件中,通过 `<string>` 节点指定了 `config_systemUIServiceComponent` 的值为 `com.android.systemui/com.android.systemui.SystemUIService`[^2]。这表明 SystemUI 使用了一个名为 `SystemUIService` 的服务来初始化并运行整个模块。 - **工厂模式引入** 另外,在 `frameworks/base/packages/SystemUI/res/values/config.xml` 文件中,还存在一个 `config_systemUIFactoryComponent` 的定义,指向 `com.android.systemui.SystemUIFactory`[^1]。该类的作用是作为 Factory 工厂方法的一部分,用于动态创建特定的 UI 组件实例。 这些配置项共同决定了 SystemUI 如何被加载到系统进程中,并为其后续的功能调用提供了基础支持。 #### 架构层次剖析 从整体上看,SystemUI 的架构可以分为以下几个层面: 1. **入口层** - 主要由 `SystemUIApplication` 类构成,它是整个应用程序的起点。 - 在此阶段会完成一些必要的初始化操作,比如绑定 Service 或者注册广播接收器等。 2. **中间管理层** - 包含多个 Manager 类型的对象,例如 `StatusBarManager`, `NotificationManager` 等。 - 这些对象承担着协调不同子模块之间交互的任务。 3. **具体实现层** - 实现具体的 UI 功能逻辑,如绘制状态栏图标、处理手势事件等等。 - 此处涉及大量自定义 View 和动画效果的设计与开发工作。 下面给出一段简化版代码示例展示如何构建基本框架结构: ```java public class SystemUIApplication extends Application { @Override public void onCreate() { super.onCreate(); // 初始化全局变量和服务连接 initializeGlobalVariables(); // 创建并启动 SystemUIService Intent intent = new Intent(this, SystemUIService.class); startForegroundService(intent); // 注意这里使用的是前台服务形式 Log.d("SystemUI", "Application created."); } private void initializeGlobalVariables(){ // 设置默认参数和其他准备工作... } } ``` 以上片段展示了当设备开机完成后,操作系统会自动触发 `onCreate()` 方法从而激活整个 SystemUI 应用程序生命周期的过程。 #### 关键特性增强 (基于Android 14的新变化) 随着新版本发布,Google 对原有的一些细节做了调整或者新增了一些实用性的功能: - 改进了暗黑模式下的颜色适配方案; - 增加更多个性化选项供开发者定制主题风格; - 提升多窗口切换流畅度体验; - 加强隐私保护措施,减少敏感数据暴露风险; 值得注意的是,虽然官方文档尚未完全公开所有改动之处,但从现有资料推测可知上述几点均属于重点升级方向之一。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值