快速搞懂 SystemUI 的启动流程

不积跬步无以至千里
SystemUI,系统界面,一个系统级的应用,其中包括了很多功能模块,比如锁屏,状态栏,分屏,音量条,多任务等等,让我们一起看一下它的启动.
随着系统的启动通过调用第一个用户空间的init进程调用Zygote进程然后调用SystemServer启动各种系统服务,而我们的SystemUI在其中启动服务中的一项.

一.SystemServer中的启动
代码路径:
frameworks/base/services/java/com/android/server/SystemServer.java
1.

private void run() {
		...
		//AMS,PWS等等服务
		startBootstrapServices();
		//电量,WebView更新等等服务
        startCoreServices();
        //网络,WMS,震动等等服务
        startOtherServices();
        ...
}
//其它服务
private void startOtherServices() {
	...
	mActivityManagerService.systemReady(() -> {
	...
	try {
        startSystemUi(context, windowManagerF);
     } catch (Throwable e) {
        reportWtf("starting System UI", e);
    }
    ...
    }
	...
//启动SystemUI的代码
static final void startSystemUi(Context context, WindowManagerService windowManager) {
        Intent intent = new Intent();
        //指定了包名类名,启动Service
        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();
    }

二.SystemUI中的启动
1.应用的启动肯定是初始化Application类
代码路径:
/code/app/src/com/android/systemui/SystemUIApplication.java
主要为了注册开机广播,来获取开机完成的事件,用来作为启动各个服务的条件.

@Override
    public void 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);

        mContext = getApplicationContext();
        SystemUIFactory.createFromConfig(this);
	
        if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
        	//注册开机完成的广播
            IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
            filter.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();
                        }
                    }
                }
            }, filter);
       ...
    }

2.SystemUIService的初始化
代码路径:
/code/app/src/com/android/systemui/SystemUIService.java

//在onCreate中会调用SystemUIApplication的startServicesIfNeeded()的方法
@Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
}

3.SystemUIApplication的startServicesIfNeeded调用
代码路径:
/code/app/src/com/android/systemui/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() {
        startServicesIfNeeded(SERVICES);
    }

所有的SystemUI功能模块

/**
     * The classes of the stuff to start.
     */
    private final Class<?>[] SERVICES = new Class[] {
            Dependency.class,//
            NotificationChannels.class,//通知
            CommandQueue.CommandQueueStart.class,//StatusBar的与StatusBarManagerService.java的通信
            KeyguardViewMediator.class,//锁屏
            Recents.class,//多任务
            VolumeUI.class,//音量条
            Divider.class,//分屏的窗口
            SystemBars.class,//状态栏
            StorageNotification.class,//贮存的插拔(SD卡,U盘),不常用
            PowerUI.class,//电量
            RingtonePlayer.class,//铃声
            KeyboardUI.class,键盘
            PipUI.class,//分屏
            ShortcutKeyDispatcher.class,
            VendorServices.class,
            GarbageMonitor.Service.class,
            LatencyTester.class,
            GlobalActionsComponent.class,
            RoundedCorners.class,
    };

循环启动

    private void startServicesIfNeeded(Class<?>[] services) {
       	//是否service已经启动过了
        if (mServicesStarted) {
            return;
        }
		//如果开机标志未至成功,查看prop,有可能已经完成很久了,在我们查看AMS启动完成之前
        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++) {
            Class<?> cl = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + cl);
            log.traceBegin("StartServices" + cl.getSimpleName());
            long ti = System.currentTimeMillis();
            try {

                Object newService = SystemUIFactory.getInstance().createInstance(cl);
                mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
            } 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();
            log.traceEnd();

            // Warn if initialization of component takes too long
            ti = System.currentTimeMillis() - ti;
            if (ti > 1000) {
                Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms");
            }
            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }

4.所有服务的父类SystemUI.java
代码路径:
app/src/com/android/systemui/SystemUI.java

public abstract class SystemUI implements SysUiServiceProvider {
    public Context mContext;
    public Map<Class<?>, Object> mComponents;

    public abstract void start();

    protected void onConfigurationChanged(Configuration newConfig) {
    }

    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) {
        final Bundle extras = new Bundle();
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                context.getString(com.android.internal.R.string.android_system_label));

        n.addExtras(extras);
    }
}

所有子类实现了父类的抽象方法start方法,因此调用各自的start启动逻辑.
SystemUI的初步启动流程就先到这.

发布了103 篇原创文章 · 获赞 58 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/WDYShowTime/article/details/100017239