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张图片

更多相关文章

  1. Android SDK23以上(包括23)无法使用httpclient的处理方法
  2. android 属性android:visibility及 view的setVisibility方法值的
  3. Android中使用WebView, WebChromeClient和WebViewClient加载网页
  4. [Android] AsyncTask使用实例---加载网络图片
  5. Android中使用animation的方法
  6. Android禁止EditText自动弹出软键盘的方法及遇到问题
  7. Android 获取未读短信同时,一并获取该短信内容的方法

随机推荐

  1. android中导入数据
  2. Android静态变量的生命周期
  3. Android(安卓)基于dpi的资源加载
  4. Android系统固件包解包、修改(涉及root提
  5. 底层之旅——Android显示驱动(framebuffe
  6. Android核心分析之四 ---手机的软件形态
  7. Android(安卓)组件硬知识点
  8. 谷歌二季度发布Android5.0:捆绑Chrome系统
  9. MySQL索引失效的几种情况详析
  10. mybatis-plus分页传入参数后sql where条