此篇文章针对android5.1 systemUI源码进行分析
下面我们进行分析,
1.1 frameworks/base/packages/SystemUI/AndroidManifest.xml
我们先来看下这个文件下的内容:
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”>
………………………………………
android:exported=”true”
/>
android:process=”:screenshot”
android:exported=”false” />
android:exported=”true” />
android:permission=”android.permission.BIND_WALLPAPER”
android:exported=”true” />
………………………………………
………………………………………
………………………………………
我们可以看到,AndroidManifest.xml注册了很多的service 和 广播,那么是怎么启动的服务呢?
我们继续看下这个所注册的三个服务,
SystemUIService /
.screenshot.TakeScreenshotService /
.LoadAverageService/.ImageWallpaper
这三个服务是怎么启动的呢,我们仔细来看下这句注释:
“Broadcast receiver that gets the broadcast at boot time and starts up everything else.”
看里这个注释,我们就应该知道,首先启动的应该是SystemUIService这个服务。
那么SystemUIService这个服务是怎么启动的呢,启动服务我们知道多数的通用方法是
startService(intent)和bindService(intent)
那么我们就在SystemUI下全局搜索“SystemUIService”,可以看下结果
frameworks/base/services/java/com/android/server/SystemServer.java: “com.android.systemui.SystemUIService”));
我们打开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);
}
原来是 intent.setComponent()启动了SystemUIService这个服务。
1.2 frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
下面我们来分析一下SystemUIService.java:
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
在oSystemUIService中的onCreate只调用了
((SystemUIApplication) getApplication()).startServicesIfNeeded();
这么一个语句,下面我们来看看startServicesIfNeeded()这里面有啥东西
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();
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
mServicesStarted = true;
}
}
在这里我们看到mServices启动了不止一个服务,那么这些都是那些服务呢,
我们看这个语句
mServices[i] = (SystemUI)cl.newInstance();
这里的语句付给了mServices[i].start()一个对象,
我们往上去找,可以看到这Class cl = SERVICES[i];
cl是SERVICES[i]这个数组中的一个值,在java的定义中,我们可以看到这个SERVICES的初始化
private final Class[] SERVICES = new Class[] {
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recent.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
};
SERVICES中添加要start的所有服务选项,这里,我们重点关注一下
com.android.systemui.statusbar.SystemBars.class,
这是我们进行下一步分析的重要线索。
1.3 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
我们看下SystemBars.java这个文件中的start()中到底写了些什么东西,
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
}
这里,启动了另外一个服务mServiceMonitor,除了启动这个服务外什么都没有做,那我们继续往下面去看看
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
在这个文件里面,对star()方法的调用
public void start() {
…………………
mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
在这个函数里,这个sendEmptyMessage语句是一个非常关键的调用,这个调用也是启动了一个服务,我们去看下这个mHandler都干了些啥事,
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;
}
}
};
在这里我们看到
case MSG_START_SERVICE:
startService();
break;
这里才是真正的启动了一个服务,mCallbacks.onNoService();
private void startService() {
mServiceName = getComponentNameFromSetting();
if (mDebug) Log.d(mTag, “startService mServiceName=” + mServiceName);
if (mServiceName == null) {
mBound = false;
mCallbacks.onNoService();
} else {
long delay = mCallbacks.onServiceStartAttempt();
mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);
}
}
我们来看下if (mServiceName == null) 这个判断的结果是怎么来的,
private ComponentName getComponentNameFromSetting() {
String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
mSettingKey, UserHandle.USER_CURRENT);
return cn == null ? null : ComponentName.unflattenFromString(cn);
}
由以上的代码我们可知,cn返回的是null值,在startService()中就调用了 mCallbacks.onNoService();
我们来看下frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
onNoService()的调用,
public void onNoService() {
if (DEBUG) Log.d(TAG, “onNoService”);
createStatusBarFromConfig();
}
private void createStatusBarFromConfig() {
…………………………………..
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
mStatusBar.start();
…………………………………..
}
在createStatusBarFromConfig()中终于有了实际的行动来进行关于status的一下相关操作了,一直到这里,其实前面所做的都是一些服务的调用,并没有对screen进行任何的view类级别的操作,其实上面的流程,只是在系统框架先进行的一些服务注册,及逻辑方面的一些准备。
1.4 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
下面我们来着重分析下BaseStatusBar.start().
public void start() {
…………………….
createAndAddWindows();
…………………….
}
在BaseStatusBar.start()中,这个语句是重点中的重点,是对整个status的布局,我们进到这个函数中去看个究竟
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
public void createAndAddWindows() {
addStatusBarWindow();
}
在createAndAddWindows中也只是调用了这么一个函数,没有其他的东西了,我们接着看
addStatusBarWindow();
其实在addStatusBarWindow所做的东西也不多,就是两步
makeStatusBarView()和mStatusBarWindowManager.add();
但是这两步确实非常重要的两部。
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
我们先来看看akeStatusBarView()这个里面是什么情况
protected PhoneStatusBarView makeStatusBarView() {
…………………………
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,R.layout.super_status_bar, null);
…………………………..
}
我们在super_status_bar.xml中这个文件可以看到
<-com.android.systemui.statusbar.phone.StatusBarWindowView
//xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:fitsSystemWindows=”true”>
…………………………..
<-com.android.systemui.statusbar.ScrimView android:id=”@+id/scrim_behind” <