版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/50216563

(一):写在前面

最近由于工作需要,需要了解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()函数:

@Overridepublic 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 bartry {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 upif (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 broadcastsIntentFilter 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 statusmService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);mService.setIconVisibility("tty", false);// Cdma Roaming Indicator, ERImService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);mService.setIconVisibility("cdma_eri", false);// bluetooth statusBluetoothAdapter 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 clockmService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);mService.setIconVisibility("alarm_clock", false);// Sync statemService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);mService.setIconVisibility("sync_active", false);// "sync_failing" is obsolete: b/1297963// volumemService.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. CTS(11)---android自动化测试CTS源码分析之一

    android自动化测试CTS源码分析之一 1, 概述 CTS(Compatibility Test Suite)全名兼容性测试,主要目的就是让Android设备开发商能够开发出兼容性更好的andro ...

  2. android agps,Android应用开发Android GPS ——AGPS源码分析及配置

    本文将带你了解Android应用开发Android GPS --AGPS源码分析及配置,希望本文对大家学Android有所帮助. " Android Framework GPS --AGPS ...

  3. android gps源码分析,Android编程之Android GPS ——AGPS源码分析及配置

    本文主要介绍了Android编程的Android GPS --AGPS源码分析及配置,通过具体的分析以及源码,向大家展示了这些,希望对大家学习Android编程有所帮助. 1:冷启动指令: locat ...

  4. Android 7.0 源码分析项目一期竣工啦

    从 Android 入行开始,因为工作需求和解决疑难bug的原因陆陆续续的看过一些源码,但都不成系统,从2016年年底开始,在Github上建了一个Android Open Source Projec ...

  5. Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)

    1.先熟悉handler方式实现主线程和子线程互相通信方式,子线程和子线程的通信方式 如果不熟悉或者忘记了,请参考我的这篇博客     Android之用Handler实现主线程和子线程互相通信以及子 ...

  6. Android之AsyncTask源码分析(第五篇:execute方法只能执行一次的原因)

    (注意:本文基于API 28的源码分析,API 29上或其他平台的源码略有不同) 前言 当你调用AsyncTask对象的execute()方法时,突然发生崩溃--内心充满不解:java.lang.Il ...

  7. Android——RIL 机制源码分析

    Android 电话系统框架介绍 在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP.AP与BP之间有两种通信方式: 1. ...

  8. Android屏幕刷新——源码分析

    Android屏幕刷新原理--源码分析 文章目录 Android屏幕刷新原理--源码分析 概述 VSync信号 三级缓冲 源码分析 消息队列的同步屏障 参考资料 概述 Android系统每16ms(一 ...

  9. Android -- 消息处理机制源码分析(Looper,Handler,Message)

    android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...

最新文章

  1. iOS UITableViewCell重用问题
  2. QListWidget 小练习
  3. QQ web api
  4. Spartan-6的SelectIO资源
  5. Java导出基础 用POI导出Excel
  6. Spring Boot中mapper包所放位置的配置
  7. SSD源码解读之ssd_pascal.py
  8. 自制计算器(C语言的简单实现)(可多次使用)
  9. iOS 15 越狱情报
  10. 计算广告学(Computational Advertising)学习资料
  11. 解决Windows10关闭UAC后,开机启动项不生效的问题
  12. 读书笔记--家庭教育1
  13. 极光短信在程序中(JAVA)的使用
  14. 2022年湖南省临床执业医师考试二单元随机真题
  15. 面试题——登录、支付功能测试点总结
  16. MySQL数据库常见报错案例与错误代码说明
  17. 发布你自己的轮子 - PyPI打包上传实践
  18. Java语言的出现背景、主要特点、发展历程以及Java技术的应用
  19. 机器人机械臂运动学——运动学正向解算
  20. Firefox Profilemaker 基于Web的浏览器配置编辑器

热门文章

  1. react组件放在数组中_为什么要在函数组件中使用React.memo?
  2. linux6.3支持gcc版本,Linux编程中GCC对C++标准支持和如何选择GCC版本使用
  3. java调试生命周期,一种基于JAVA的智能合约生命周期的管理方法与流程
  4. c#进行三角形周长面积计算公式_小学数学,期末复习,量的计算单位及进率归类,常用计算公式表...
  5. mysql1067默认参数错误_MySQL 1067错误解决方法集合
  6. 《系统集成项目管理工程师》必背100个知识点-88系统集成项目收尾管理工作
  7. CentOS6中安装、配置、启动GitLab以及遇到的那些坑
  8. GitLab-怎样使用GitLab托管项目
  9. 安装Requests
  10. 单高斯分布模型GSM,高斯混合模型GMM