(一):写在前面

近期因为工作须要,须要了解CM11中的有关于StatusBar相关的内容。总的来说,刚開始阅读其源代码的时候,是有点困难,只是通过构建相关代码的脑图和流程图,几天下来。我已经对其源代码有了一个大体的了解。只是其内部细节还有非常多不是非常明确,可是这对于我的工作来说就已经足够了。

在android系统中,有关于系统状态栏有关的代码位于/framework/base/packages/SystemUI/中,非常明显,该SystemUI是一个app源代码。当系统进行编译的时候,就会生成SystemUI.apk。

所以我们对待它就像是对待普通app程序一样。

好了。如今開始我们的代码分析。

(二):StatusBar流程分析

对于android系统来说,SystemUI的启动是有位于packages以下的android系统launcher启动器启动的,启动方式事实上是通过java的反射机制实现的。其启动SystemUI的SystemUIService。该SystemUIService是Service的一个子类,同一时候,在该类中通过反射机制同一时候启动6个和系统UI相关的类,这个我们后面再分析。

这6个和系统UI相关的类都继承自SystemUI类,在SystemUIService中实例化这6个类的时候同一时候启动该类相应的start()方法来启动服务。而他们的start()函数中主要是启动相关ServiceMonitor的start方法,在该ServiceMonitor中主要是启动相关的包的服务。即调用startService()函数。

在启动服务的时候,就会实例化StatusBar,而且调用其onStart()函数。这个就是StatusBar的启动流程,这样说的话可能理解起来比較繁琐,以下的这张图就是系统状态栏的启动过程的流程图:

(三):SystemUIService源代码分析

以下我们来分析一下SystemUIService的源代码。

该SystemUIService类继承自Service类。说明该类是一个服务类,在该类中都是干了什么工作呢?我们先找到Service类中的onCreate()方法:

public void onCreate() {
HashMap<Class<? >, Object> components = new HashMap<Class<?>, Object>();
final int N = SERVICES.length;
for (int i=0; i<N; i++) {
Class<? > cl = SERVICES[i];
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 = components;
Log.d(TAG, "running: " + mServices[i]); mServices[i].start();
}
}

从这里能够看出,通过一个for循环将数组SERVICES中保存的类实例化,即调用newInstance()函数。实例化完毕之后。对其对象中的属性进行赋值,最后再调用相应的start()函数。

以下我们来看一下SERVICES数组中的保存的6个类:

 private final Class<?>[] SERVICES = new Class[] {
com.android.systemui.recent.Recents.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,
com.android.systemui.settings.SettingsUI.class,
};

当然,在这个类里面也存有其它相关的函数。包含配置发生改变的函数,销毁函数等,以下我们来看一下该类的脑图:

因为在这里启动了6个相关的类。可是我们在这篇文章中,我们先分析SystemBars.class类。

(四):SystemBars源代码分析

在上面的流程图中,我们知道,启动的6个类都是继承自SystemUI类,我们先来看一下SystemUI类:

SystemUI类是一个抽象类。在该类中定义了一些方法,当中包含启动方法,配置发生改变的函数。销毁函数等。

以下我们先来看一下该类的代码:

 public Context mContext;
public Map<Class<?>, Object> mComponents; public abstract void start(); protected void onConfigurationChanged(Configuration newConfig) {
} public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
} @SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> interfaceType) {
return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
} public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
if (mComponents != null) {
mComponents.put(interfaceType, component);
}
}

在这个类中,比較有意思的就是Map对象,该对象就是保存相关类的组件。以下我们来看一下脑图:

以下我们来看SystemBars的源代码。在这里我们主要查看的是其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类的对象来说,其start()函数,终于都要调用位于SystemBars类中的createStatusBarFromConfig()函数,在该函数中。主要是调用BaseStatusBar对象的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());
}

以下我们来看一下SystemBars类的脑图:

(五):ServiceMonitor源代码分析

在ServiceMonitor类中主要是使用Handler中的信息类来进行包服务管理。当中有启动服务,继续服务,暂停服务,停止服务等函数,在这里辗转反側终于还是回归到SystemBars中的StatusBars的启动:

(六):终于流程分析

上面我们提到了,终于还是要启动StatusBar,而这里启动的StatusBar并非其真正的StatusBar,而是他的子类,也就是位于com/android/systemui/statusbar/phone/PhoneStatusBar.java,以下我们来看一下他的start()函数:

@Override
public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
updateDisplaySize(); ThemeConfig currentTheme = mContext.getResources().getConfiguration().themeConfig;
if (currentTheme != null) {
mCurrentTheme = (ThemeConfig)currentTheme.clone();
} else {
mCurrentTheme = ThemeConfig.getSystemTheme();
} mLocationController = new LocationController(mContext);
mBatteryController = new BatteryController(mContext);
mDockBatteryController = new DockBatteryController(mContext);
mBluetoothController = new BluetoothController(mContext); super.start(); // calls createAndAddWindows() addNavigationBar(); SettingsObserver observer = new SettingsObserver(mHandler);
observer.observe(); // Developer options - Force Navigation bar
try {
boolean needsNav = mWindowManagerService.needsNavigationBar();
if (!needsNav) {
mDevForceNavbarObserver = new DevForceNavbarObserver(mHandler);
mDevForceNavbarObserver.observe();
}
} catch (RemoteException ex) {
// no window manager? good luck with that
} // Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext); mHeadsUpObserver.onChange(true); // set up
if (ENABLE_HEADS_UP) {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.HEADS_UP_NOTIFICATION), true,
mHeadsUpObserver, mCurrentUserId);
}
}

在这个代码中。我们看到代码中,有一个类PhoneStatusBarPolicy类,该类就是向状态栏中加入图标的管理类。以下我们来看一下该类的构造方法:

    public PhoneStatusBarPolicy(Context context) {
mContext = context;
mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); // listen for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_ALARM_CHANGED);
filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); int numPhones = MSimTelephonyManager.getDefault().getPhoneCount();
mSimState = new IccCardConstants.State[numPhones];
for (int i=0; i < numPhones; i++) {
mSimState[i] = IccCardConstants.State.READY;
} // TTY status
mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null);
mService.setIconVisibility("tty", false); // Cdma Roaming Indicator, ERI
mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
mService.setIconVisibility("cdma_eri", false); // bluetooth status
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
int bluetoothIcon = R.drawable.stat_sys_data_bluetooth;
if (adapter != null) {
mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected;
}
}
mService.setIcon("bluetooth", bluetoothIcon, 0, null);
mService.setIconVisibility("bluetooth", mBluetoothEnabled); // Alarm clock
mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
mService.setIconVisibility("alarm_clock", false); // Sync state
mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);
mService.setIconVisibility("sync_active", false);
// "sync_failing" is obsolete: b/1297963 // volume
mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
mService.setIconVisibility("volume", false);
updateVolume();
}

而这里主要是加入监听广播,而且加入其它相关图标。

还有有些图标是在布局文件里加入的,当中于StatusBar相关的布局文件是在以下几个文件里的:

  • SystemUI/res/layout/status_bar.xml
  • SystemUI/res/layout/super_status_bar.xml

以及其内部include的相关文件。

好了,至此,有关与android系统状态栏相关的代码已经了解的差点儿相同了,通过这个,我们能够向状态栏中加入图标或者是删除图标。这个是比較简单了。

好了。有关与状态栏的代码我们就分析到此。后面我们再来分析QuickSettings的相关的代码。

android(cm11)状态栏源代码分析(一)的更多相关文章

  1. 子墨庖丁Android的ActionBar源代码分析 (一)实例化

    假设你从事过Androidclient开发,相信你对ActionBar这套框架并不陌生,或者说你并不了解它,可是你应该时不时的要跟它打交道.抛开ActionBar的实现不说,ActionBar实际上是 ...

  2. Android应用Activity、Dialog、PopWindow、Toast窗体加入机制及源代码分析

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重劳动成果] 1 背景 之所以写这一篇博客的原因是由于之前有写过一篇<Android应用setCont ...

  3. Android 中View的绘制机制源代码分析 三

    到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...

  4. Android系统进程Zygote启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6768304 在Android系统中,所有的应用 ...

  5. Android系统默认Home应用程序(Launcher)的启动过程源代码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个 Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home ...

  6. Android应用程序安装过程源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6766010 Android系统在启动的过程中, ...

  7. Android应用程序进程启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...

  8. Android应用程序绑定服务(bindService)的过程源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6745181 Android应用程序组件Serv ...

  9. Android应用程序内部启动Activity过程(startActivity)的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6703247 上文介绍了Android应用程序的 ...

随机推荐

  1. 【译】从现有的容器里创建新的Docker镜像

    如果你修改了一个容器的内容,你可以使用docker commit命令将现有的容器状态保存为一个镜像. 下面的例子展示了如何修改一个基于oraclelinux:6.6的容器使得其能够运行Apache H ...

  2. Zookeeper ZooDefs.Ids

    OPEN_ACL_UNSAFE  : 完全开放的ACL,任何连接的客户端都可以操作该属性znode CREATOR_ALL_ACL : 只有创建者才有ACL权限 READ_ACL_UNSAFE:只能读 ...

  3. chrome+postman测试rest请求

    1.在chrome安装postman 2.在chrome打开postman 浏览器输入:chrome://apps/ 选择你的postman 3.在你看到的postman中 normal中可以看到参数 ...

  4. hihoCoder 1467 2-SAT·hihoCoder音乐节(2-SAT模版)

    #1467 : 2-SAT·hihoCoder音乐节 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 hihoCoder音乐节由hihoCoder赞助商大力主办,邀请了众 ...

  5. springboot开启定时任务 添加定时任务 推送

    最近在自学Java的springboot框架,要用到定时推送消息.参考了网上的教程,自己调试,终于调好了.下面将网上的教程归纳下,总结复习下.  springboot开启定时任务  在SpringBo ...

  6. vue2搭建简易spa

    使用vue-cli来配置webpack,webpack是一个打包工具,使程序模块化 全局安装vue-cli: npm install -g vue-cli 安装好后,使用vue-cli脚手架配置web ...

  7. iOS笔记-(缓存机制的理解与实现)

    (1)运行中的现象: 在iOS开发中,会遇到:同一NSURL被多次请求,会造成用户的流量浪费,程序的响应速度不够快.比如说,从服务器上请求一张图片,请求100次,下载的结果都是一样的. (2)解决方法 ...

  8. poj 1743 Musical Theme 后缀自动机/后缀数组/后缀树

    题目大意 直接用了hzwer的题意 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题."主题&qu ...

  9. [LeetCode] Binary Search Tree Iterator 深度搜索

    Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...

  10. Windows下C++多线程同步与互斥简单运用(转)

    1.  互斥量,Mutex #include <Windows.h> #include <iostream> using namespace std; DWORD WINAPI ...