SystemUI 启动流程

作者: BlueSocks | 来源:发表于2023-01-28 17:34 被阅读0次

    SystemUI 主要模块

    • StatusBar:通知消息提示和状态展现
    • NavigationBar:返回,HOME,Recent
    • KeyGuard:锁屏模块可以看做单独的应用,提供基本的手机个人隐私保护
    • Recents:近期应用管理,以堆叠栈的形式展现。
    • Notification Panel:展示系统或应用通知内容。提供快速系统设置开关。
    • Volume:来用展示或控制音量的变化:媒体音量、铃声音量与闹钟音量
    • 截屏界面:长按电源键+音量下键后截屏,用以展示截取的屏幕照片/内容
    • PowerUI:主要处理和Power相关的事件,比如省电模式切换、电池电量变化和开关屏事件等。
    • RingtonePlayer:铃声播放
    • StackDivider:控制管理分屏
    • PipUI:提供对于画中画模式的管理

    简单的说下 SystemUI 的启动过程

    由init进程->Zygote进程->SystemServer进程。

    那init进程又是怎么起来的?当你按下电源键,系统上电,从固定地址开始加载固化在ROM的Bootloader代码到RAM中并执行,Bootloader引导程序负责将系统OS拉起。当系统OS被拉起,并完成一些列初始化和系统设置后,就会首先在系统文件中寻找“init”文件并启动这个咱们用户空间的第一个进程。

    image

    SystemUI

    每个模块的公共方法 所以系统抽取了 SystemUI 公共类

    • 处理各自模块的初始化
    • 处理系统的状态变化
    • 执行dump
    • 系统启动完成时,要处理相应逻辑
    // SystemUI 
    public abstract class SystemUI implements SysUiServiceProvider {
        public Context mContext;
        public Map<Class<?>, Object> mComponents;
    
        // 完成初始化操作
        public abstract void start();
    
        // 是处理系统状态变化的回调,这里的状态变化包括:时区变更,
        // 字体大小变更,输入模式变更,屏幕大小变更,屏幕方向变更等。
        protected void onConfigurationChanged(Configuration newConfig) {
        }
        
        // dump方法用来将模块的内部状态dump到输出流中,这个方法主要是辅助
        // 调试所用。开发者可以在开发过程中,通过adb shell执行dump来了解系统的内部状态。
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        }
        
        // 系统启动完成的回调方法
        protected void onBootCompleted() {
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getComponent(Class<T> interfaceType) {
            return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
        }
    
        public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
            if (mComponents != null) {
                mComponents.put(interfaceType, component);
            }
        }
    
        public static void overrideNotificationAppName(Context context, Notification.Builder n,
                boolean system) {
            final Bundle extras = new Bundle();
            String appName = system
                    ? context.getString(com.android.internal.R.string.notification_app_name_system)
                    : context.getString(com.android.internal.R.string.notification_app_name_settings);
            extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);
    
            n.addExtras(extras);
        }
    
        public interface Injector extends Function<Context, SystemUI> {
        }
    }
    
    

    除了截屏服务,提及模块均继承抽象类SystemUI并在应用启动时被分别初始化。从这种角度来看,SystemUI应用更像是这些功能模块的容器。

    SystemUIApplication

    从 AndroidManifest.XML 中可以看到

     <application
            android:name=".SystemUIApplication"
            android:persistent="true"
            android:allowClearUserData="false"
            android:allowBackup="false"
            android:hardwareAccelerated="true"
            android:label="@string/app_label"
            android:icon="@drawable/icon"
            android:process="com.android.systemui"
            android:supportsRtl="true"
            android:theme="@style/Theme.SystemUI"
            android:defaultToDeviceProtectedStorage="true"
            android:directBootAware="true"
            android:appComponentFactory="androidx.core.app.CoreComponentFactory">
            <!-- Keep theme in sync with SystemUIApplication.onCreate().
    
    

    所以我们去康康 SystemUIApplicationOncreate 方法

       @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);
            
            // 这里有设置一个广播 但是只接受一次
            if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
                IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
                bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
                registerReceiver(new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        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 {
                ···
                startSecondaryUserServicesIfNeeded();
            }
        }
    
    
    /**
         * 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];
            ···
            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++) {
                ···
                mServices[i].mContext = this;
                mServices[i].mComponents = mComponents;
                if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
                // 这里可以看到启动了每个 Service
                mServices[i].start();
                ···
            }
            ···
        }
    
    

    到这里SystemUI的启动流程就完了

    如有错误欢迎指出 共同学习 共同进步哈~


    本文转自 https://juejin.cn/post/6844904180365131784,如有侵权,请联系删除。

    相关文章

      网友评论

        本文标题:SystemUI 启动流程

        本文链接:https://www.haomeiwen.com/subject/ahmehdtx.html