Android 8.1 中Systemui中的常见修改(八)SystemUI加载流程

SystemUI作为系统应用,在开机的时候就会开始加载启动,今天来学习一下它的启动流程。

SystemServer.java (frameworks\base\services\java\com\android\server)  

1.最开始会调用SystemServer里面的StartOtherService方法,我们可以看到startSystemUi方法实际上是启动了一个SystemUIService的服务。

  private void startOtherServices() {
   ........
         try {
                startSystemUi(context, windowManagerF);
            } catch (Throwable e) {
                reportWtf("starting System UI", e);
            }
    ......
   }

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();
    }

这里我们需要注意的是,SystemUI到这里还没有启动成功,因为startOtherService()方法都还没有执行完毕。所以暂时还不会发送ACTION_BOOT_COMPLETE广播,该广播是在AMS中的finishBooting()中发送的。(该广播在我们SystemUIService中有做监听,用来判断是否完成系统启动)。 

2.现在我们来看一下SystemUIService的里面的onCreate方法,实际上又调用了SystemUIApplication里面的startServicesIfNeeded方法。

SystemUIService.java (frameworks\base\packages\systemui\src\com\android\systemui) 
 

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

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

3.这里面把SystemUIApplication的onCreate方法都贴上了,大致的操作就是判断是否加载完成。

SystemUIApplication.java (frameworks\base\packages\systemui\src\com\android\systemui) 

这里面需要注意的是对于安卓系统来说,当一个应用启动,系统会保证其Application类是第一个被实例化的类,并且Application的onCreate方法,一定先于应用中所有的Activity,Service和BroadcastReceiver的创建。

@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)) {
            //注册ACTION_BOOT_COMPLATETED广播
            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);
        } 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.
            startServicesIfNeeded(SERVICES_PER_USER);
        }
    }

我们在接着看startServicesIfNeeded方法,这里面就是把对应的服务启动起来。这里的服务不是Android的service,它们其实是一个普通的java文件,里面的start方法是用来进行一些初始化操作

 private void startServicesIfNeeded(Class[] services) {
......
  final int N = services.length;
  for (int i = 0; i < N; i++) {
  mServices[i].start();//启动对应的服务
 }
......
  mServicesStarted = true;
}

需要启动的服务:

private final Class[] SERVICES = new Class[] {
            Dependency.class,
            NotificationChannels.class,
            CommandQueue.CommandQueueStart.class,
            KeyguardViewMediator.class,
            Recents.class,
            VolumeUI.class,
            Divider.class,
            SystemBars.class,
            StorageNotification.class,
            PowerUI.class,
            RingtonePlayer.class,
            KeyboardUI.class,
            PipUI.class,
            ShortcutKeyDispatcher.class,
            VendorServices.class,
            GarbageMonitor.Service.class,
            LatencyTester.class,
            GlobalActionsComponent.class,
            RoundedCorners.class,
    };

4.我们以启动SystemBars为例子,可以看到会调用mStatusBar.start(),来启动StatusBar。

SystemBars.java (frameworks\base\packages\systemui\src\com\android\systemui)  

 @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        createStatusBarFromConfig();
    }

    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        //com.android.systemui.statusbar.phone.StatusBar
        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 {
           //StatusBar继承自SystemUI,反射生成的为StatusBar类型对象,引用为SystemUI类型引用
            mStatusBar = (SystemUI) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        //在这里调用的statusBar的start方法
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

5.在这里面我们就不做过多的阐述了,通过调用StatusBar里面的start方法来加载Statusbar上面的资源。

StatusBar.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone)   
可以查看之前的文章继续看流程。

Android 8.1 中Systemui中的常见修改(六)NavigationBar加载流程

这里,要注意的是SystemBars和StatusBar类都是继承自SystemUI,前者用于在systemui进程启动时和SystemUIApplication进行交互,并且包含一个SystemUI属性,用来指向一个StatusBar对象,并start()该对象。总结一下SystemBars的作用

在SystemUIApplication中通过反射得到SystemBars实例
通过反射得到StatusBar实例
start StatusBar实例


下面是SystemUIService的执行log

Android 8.1 中Systemui中的常见修改(八)SystemUI加载流程_第1张图片

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