,文章

SystemUI源码分析之PhoneStatusBar启动流程简单分析

文章目录

下面两图让我们大概的了解了SystemUI代码结构和布局范围。

下面是Android SystemUI中包含的各项功能简介,虽然很多,但我这里只是讲解Status Bar,也就是系统上方的状态栏。看第二张图第一部分的顶部部分。

Status Bar 系统上方的状态栏

Navigator Bar 系统下方的导航栏

Keyguard 锁屏界面

PowerUI 电源界面

Recents Screen 近期任务界面

VolumeUI 音量调节对话框

Stack Divider 分屏功能调节器

PipUI 画中画界面

Screenshot 截屏界面

RingtonePlayer 铃声播放器界面

Settings Activity 系统设置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。

原归正传,我们从代码中查看SystemUI是如何启动的。我用的源码是Android 6.0 的,不过各个Android版本的启动过程大致是相同的。

 1.SystemServer中启动SystemUIService

SystemService路径: base\services\java\com\android\server\SystemServer.java

SystemUIService的启动是在SystemServer中startSystemUi中启动的

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

startSystemUi()在SystemServer中启动startOtherServices()中调用的。

private void startOtherServices() {
    ......
    
    mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
            .......     
                try {
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
            ......
          } 
     }
     ......
}

2. SystemUIService服务的启动

SystemUIService所在路径: src\com\android\systemui\SystemUIService.java

SystemUIApplication所在路径: src\com\android\systemui\SystemUIApplication.java

根据上面设置的包名,我们知道SystemUIService是在/frameworks/base/packages/SystemUI中,也就是SystemUI系统应用。

在Android中,我们第一次启动应用会先启动application模块(如果在AndroidMainfest.xml有配置的话),然后才会启动application中包含的Activity、Service、广播等组件。

因此我们先看SystemUI中的application模块也就是SystemUIApplication.java(具体看AndroidMainfest.xml中的配置)代码:

public class SystemUIApplication extends Application {
      ......
    /**
     * 假“服务”,这些“服务”都继承抽象了SystemUI,也不是真正的“服务”
     */
    private final Class<?>[] SERVICES = new Class[] {
            com.android.systemui.tuner.TunerService.class,
            com.android.systemui.keyguard.KeyguardViewMediator.class,
            com.android.systemui.recents.Recents.class,
            com.android.systemui.volume.VolumeUI.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,
    };

    ......
   
    @Override
    public void onCreate() {
        super.onCreate();
        setTheme(R.style.systemui_theme);
         //注册开机完成广播监听
        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);
    }

    // 启动上面那些“服务”,在SystemUIService中被调用
    public void startServicesIfNeeded() {
        if (mServicesStarted) {
            return;
        }

        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.");
        final int N = SERVICES.length;
        for (int i=0; i<N; i++) {
            Class<?> cl = SERVICES[i];
            if (DEBUG) 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 = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start(); //调用start()方法

            if (mBootCompleted) {
                mServices[i].onBootCompleted();//调用onBootCompleted方法
            }
        }
        mServicesStarted = true;
    }

    //横竖改变了,需要通知对应的“Service”进行相对应的配置
    @Override
    public void onConfigurationChanged(Configuration newConfig) { 
        if (mServicesStarted) {
            int len = mServices.length;
            for (int i = 0; i < len; i++) {
                mServices[i].onConfigurationChanged(newConfig);
            }
        }
    }

    ......
}

启动完SystemUIApplication后,才启动SystemUIService.java

public class SystemUIService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded(); //这里SystemUIApplication中的startServicesIfNeeded,启动“服务”
    }
    ......
}

在上面中,启动了的“服务”有TunerService、KeyguardViewMediator、Recents、VolumeUI、SystemBars等,但我们这次只讲解SystemBars“服务”的启动。

在startServicesIfNeeded()中,我们知道先初始化服“服务”,然后调用“服务”的start()方法

3. SystemBars“服务”的启动

启动的就是SystemBars.java

       所在路径: src\com\android\systemui\statusbar\SystemBars.java
       重点看start()方法
public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
    ......
    //start()方法是再启动中调用的额方法
    @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        //这里会启动ServiceMonitor,并调用其的start(),重点看注释“如果没有远程服务,就会回调onNoService()方法”
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        mServiceMonitor.start();  // will call onNoService if no remote service is found
    }

    @Override
    public void onNoService() {
        if (DEBUG) Log.d(TAG, "onNoService");
        createStatusBarFromConfig();  // fallback to using an in-process implementation
    }
    ......
}

第一次启动时,远程服务没有被启动,因此会回调onNoService()方法,然后调用createStatusBarFromConfig()方法,继续

    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        //根据xml中的配置,是一个应用包名路径,这里就是“com.android.systemui.statusbar.phone.PhoneStatusBar”
        //然后根据包名路径并启动
        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;
        //这里调用mStausBar就是“PhoneStatusBar”实例,并调用start()方法
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

R.string.config_statusBarComponent配置的是“com.android.systemui.statusbar.phone.PhoneStatusBar”

然后就会启动PhoneStatusBar.java,重点,这里在启动后又调用了start()方法。

4. PhoneStatusBar.start()

public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        HeadsUpManager.OnHeadsUpChangedListener {

        ......
 
        @Override
        public void start() {
        ......

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

        ......

        addNavigationBar();

        // Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
                mUserInfoController, mBluetoothController);
        mIconPolicy.setCurrentUserSetup(mUserSetup);

        ......
        startKeyguard(); 

        ......
    }
        ......

}

在 PhoneStatusBar.start()中重点如下几个步骤:

1.createAndAddWindows() 初始化View,顶部状态栏,和底部导航栏

2.addNavigationBar()

3.PhoneStatusBarPolicy() 用于初始化以及更新StatusBar上的icons

4.startKeyguard() 启动屏锁

具体的后续在分析。

5.PhoneStatusBar启动流程图

高清大图请看   百度云 链接:https://pan.baidu.com/s/1NIJn2m3521v9fGys_9rDwQ 密码:bws9

本文参考《SystemUI之功能介绍和UI布局实现》和《Android 4.0 ICS SystemUI浅析——SystemUI启动流程》等

发表评论