#Android之SystemUI加载流程和NavigationBar的分析
本篇只分析SystemUI的加载过程和SystemUI的其中的一个模块StatusBar的小模块NavigationBar,以Android6.0代码进行分析
##AndroidManifest.xml
<application
android:name=".SystemUIApplication"
android:persistent="true"
android:allowClearUserData="false"
android:allowBackup="false"
android:hardwareAccelerated="true"
android:label="@string/app_label"
android:icon="@drawable/icon"
android:process="com.android.systemui"
android:supportsRtl="true"
android:theme="@style/systemui_theme">
<!-- Keep theme in sync with SystemUIApplication.onCreate().
Setting the theme on the application does not affect views inflated by services.
The application theme is set again from onCreate to take effect for those views. -->
<!-- Broadcast receiver that gets the broadcast at boot time and starts
up everything else.
TODO: Should have an android:permission attribute
-->
<service android:name="SystemUIService"
android:exported="true"
/>
##SystemUIService
跟StatusBar相关的服务为SystemUIService
,我们查看SystemUIService
源码
public class SystemUIService extends Service {
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
//获取Application调用startServicesIfNeeded
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
/*打印堆栈信息*/
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
if (args == null || args.length == 0) {
for (SystemUI ui: services) {
pw.println("dumping service: " + ui.getClass().getName());
ui.dump(fd, pw, args);
}
} else {
String svc = args[0];
for (SystemUI ui: services) {
String name = ui.getClass().getName();
if (name.endsWith(svc)) {
ui.dump(fd, pw, args);
}
}
}
}
}
分析SystemUIService
代码,可以知道SystemUI主要做了两件事
- 获取
Application
对象加载SystemUI相关的类,这个等下分析SystemUIApplication
代码可以知道 dump
打印SystenUISerice
运行过程中相关的堆栈信息
那么SystemUIService
又是哪里开始启动的呢?竟然SystemUIService是个服务,那么启动服务要么就是startService
要么就是bindService进行启动,其启动方式则需要通过Intent来传入类名或者包名,因此在源码中搜索SystemUIService可以对比发现,它在
frameworks\base\services\java\com\android\server\SystemServer.java中进行启动
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);
}
在SystemServer的run方法中startOtherServices来启动SystemUIService服务,至于SystemServer则涉及到Android的启动流程,其大概流程为
int -> ServerManager -> Zygote -> SystemServer
SystemServer中会初始化一些Android的java层的服务,如ActivityManagerService、WindowManagerService等
这里SystemUI的加载过程就到此告一段落了,下面分析StatusBar的加载流程
上面讲到在SystemUIService的onCreate中获取SystemUIApplication对象来初始化SystemUI相关的类,这些类里面就包括了StatusBar相关的类,我们查看SystemUIApplication类
##SystemUIApplication
###onCreate
@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.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++) {
//回调各服务的onBootCompleted函数
mServices[i].onBootCompleted();
}
}
}
}, filter);
}
在SystemUIApplication的onCreate中主要做了
- 设置主题(这个会影响其SystemUI的界面显示效果)
- 注册开机广播,设置标志位
###startServicesIfNeeded
SystemUIService中的onCreate启动了这个方法,我们着重分析这个方法
public void startServicesIfNeeded() {
if (mServicesStarted) {
return;
}
if (!mBootCompleted) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
//获取系统文件中的sys.boot_completed的值
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);
//实例化各个类实例,放入mServices数组中
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();
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
//服务启动标志
mServicesStarted = true;
}
这个方法中,首先判断mServicesStarted
标志为来判断SystemUI相关的服务是否启动,同时根据系统配置文件来检查ActivityManagerService是否finishBooting,然后通过类加载机制来初始化SERVICES数组里面相关的类加入mServices中,然后start
/**
* The classes of the stuff to start.
*/
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,//铃声播放相关
};
/**
* Hold a reference on the stuff we start.
*/
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
从mServices和SERVICES的定义可以发现SERVICES是一组包含全路径的相关的类,这些类包含一些我们常见的TunerService(定制状态栏服务)、
KeyguardViewMediator(锁屏相关)、Recents(近期任务)、VolumeUI(音量条)、SystemBars(状态栏)、StorageNotification(通知栏)、PowerUI(电源相关)、RingtonePlayer(铃声播放相关)类,它们都是继承与SystemUI抽象类,现在只分析StatusBar相关的SystemBars类
##SystemBars
public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
private static final String TAG = "SystemBars";
private static final boolean DEBUG = false;
private static final int WAIT_FOR_BARS_TO_DIE = 500;
// manages the implementation coming from the remote process
private ServiceMonitor mServiceMonitor;
// in-process fallback implementation, per the product config
private BaseStatusBar mStatusBar;
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
//实例化ServiceMonitor
mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
//start
mServiceMonitor.start(); // will call onNoService if no remote service is found
}
/*服务没启动时,ServiceMonitor会回调onNoService*/
@Override
public void onNoService() {
if (DEBUG) Log.d(TAG, "onNoService");
createStatusBarFromConfig(); // fallback to using an in-process implementation
}
/*服务已经启动的回调*/
@Override
public long onServiceStartAttempt() {
if (DEBUG) Log.d(TAG, "onServiceStartAttempt mStatusBar="+mStatusBar);
if (mStatusBar != null) {
// tear down the in-process version, we'll recreate it again if needed
mStatusBar.destroy();
mStatusBar = null;
return WAIT_FOR_BARS_TO_DIE;
}
return 0;
}
/*系统配置改变*/
@Override
protected void onConfigurationChanged(Configuration newConfig) {
if (mStatusBar != null) {
mStatusBar.onConfigurationChanged(newConfig);
}
}
/*打印堆栈*/
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mStatusBar != null) {
mStatusBar.dump(fd, pw, args);
}
}
/*从xml文件中获取PhoneStatusBar全路径,通过类加载器实例化类,调用其start*/
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
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;
mStatusBar.start();
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
private RuntimeException andLog(String msg, Throwable t) {
Log.w(TAG, msg, t);
throw new RuntimeException(msg, t);
}
}
我们先从start方法开始分析
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
mServiceMonitor.start(); // will call onNoService if no remote service is found
}
这里实例化ServiceMonitor类start,继续分析ServiceMonitor
###ServiceMonitor
...
public ServiceMonitor(String ownerTag, boolean debug,
Context context, String settingKey, Callbacks callbacks) {
mTag = ownerTag + ".ServiceMonitor";
mDebug = debug;
mContext = context;
mSettingKey = settingKey; // Settings.Secure.BAR_SERVICE_COMPONENT
mCallbacks = callbacks;
}
public void start() {
// listen for setting changes
/*Settings.Secure.BAR_SERVICE_COMPONENT改变时回调*/
ContentResolver cr = mContext.getContentResolver();
cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);
// listen for package/component changes
//应用安装,改变,卸载会触发mBroadcastReceiver广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
...
ServiceMOnitor是一个监听Settings.Secure.BAR_SERVICE_COMPONENT是否改变的类,在start中通过监听系统系统时应用的变化来启动服务
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String pkg = intent.getData().getSchemeSpecificPart();
if (mServiceName != null && mServiceName.getPackageName().equals(pkg)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_PACKAGE_INTENT, intent));
}
}
};
应用装载时,通过Handler发送MSG_PACKAGE_INTENT消息事件,我们查看Handler消息回调
// internal handler + messages used to serialize access to internal state
public static final int MSG_START_SERVICE = 1; //启动服务,并非真正启动,会根据ServiceName进行判断
public static final int MSG_CONTINUE_START_SERVICE = 2; //启动服务
public static final int MSG_STOP_SERVICE = 3;//停止服务消息
public static final int MSG_PACKAGE_INTENT = 4;//包安装事件消息
public static final int MSG_CHECK_BOUND = 5;//包改变或者卸载时,重新启动服务消息
public static final int MSG_SERVICE_DISCONNECTED = 6;//服务断开消息
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_START_SERVICE:
startService();
break;
case MSG_CONTINUE_START_SERVICE:
continueStartService();
break;
case MSG_STOP_SERVICE:
stopService();
break;
case MSG_PACKAGE_INTENT:
packageIntent((Intent)msg.obj);
break;
case MSG_CHECK_BOUND:
checkBound();
break;
case MSG_SERVICE_DISCONNECTED:
serviceDisconnected((ComponentName)msg.obj);
break;
}
}
};
private void packageIntent(Intent intent) {
if (mDebug) Log.d(mTag, "packageIntent intent=" + intent
+ " extras=" + bundleToString(intent.getExtras())