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
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启动流程》等