PowerUI

powerUI是SystemUI显示电池相关信息的模块,包括低电量提醒,危急电量关机提醒,高温关机提醒,省电模式等的功能。
在powerUI.java 中主要是两个函数start()和onReveice()

启动流程

SystemUI启动时会加载众多功能模块,其中就包含着PowerUI,会直接调用\

PowerUI.start()

start() 函数是在PowerUI 中最先触发的方法。在方法内进行了一些赋值操作,及注册对电量变化和屏幕开闭状态的广播监听
1)实例化PowerManager,因为是处理和Power相关的业务,必须实例化PowerManager.

2)初始化关屏时间,关屏时间会持续刷新。

3)实例化PowerNotificationWarnings,Power相关的事件会通过Notification方式进行处理。

4)监控电池电量,在电量不足是给出警告和提示。

5)更新电池电量等级。

public void start() {//获取PowerManager  用于获取电池的相关信息mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);//获取自启动以来的毫秒数mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();mWarnings = Dependency.get(WarningsUI.class);//和混合通知相关,相关功能平台默认是关闭的,我们暂时也就不关注了mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);mLastConfiguration.setTo(mContext.getResources().getConfiguration());// 监测低电量阀值的改变ContentObserver obs = new ContentObserver(mHandler) {@Overridepublic void onChange(boolean selfChange) {updateBatteryWarningLevels();}};final ContentResolver resolver = mContext.getContentResolver();resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),false, obs, UserHandle.USER_ALL);// 更新低电量等阀值updateBatteryWarningLevels();// 监听相关广播mReceiver.init();//检查我们是否需要让用户知道手机之前因温度过高而关闭showWarnOnThermalShutdown();// Register an observer to configure mEnableSkinTemperatureWarning and perform the// registration of skin thermal event listener upon Settings change.//注册观察者以配置 mEnableSkinTemperatureWarning 并在设置更改时执行皮肤热事件侦听器的注册。resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),false /*notifyForDescendants*/,new ContentObserver(mHandler) {@Overridepublic void onChange(boolean selfChange) {doSkinThermalEventListenerRegistration();}});// Register an observer to configure mEnableUsbTemperatureAlarm and perform the// registration of usb thermal event listener upon Settings change.//注册观察者以配置 mEnableUsbTemperatureAlarm 并在设置更改时执行 USB 热事件侦听器的注册。resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),false /*notifyForDescendants*/,new ContentObserver(mHandler) {@Overridepublic void onChange(boolean selfChange) {doUsbThermalEventListenerRegistration();}});// 初始化温度阀值initThermalEventListeners();mCommandQueue.addCallback(this);}

电池电量有三个关键值定义如下(frameworks\base\core\res\res\valuesconfig.xml):

<integer name="config_criticalBatteryWarningLevel">5</integer>
<integer name="config_lowBatteryWarningLevel">15</integer>
<integer name="config_lowBatteryCloseWarningBump">5</integer>

低电量警告

updateBatteryWarningLevels

void updateBatteryWarningLevels() {//获取系统配置的危急电量,默认值是5int critLevel = mContext.getResources().getInteger(com.android.internal.R.integer.config_criticalBatteryWarningLevel);// 获取系统配置的低电量值,默认:15int warnLevel = mContext.getResources().getInteger(com.android.internal.R.integer.config_lowBatteryWarningLevel);if (warnLevel < critLevel) {warnLevel = critLevel;}mLowBatteryReminderLevels[0] = warnLevel;mLowBatteryReminderLevels[1] = critLevel;// 获取系统配置的关闭低电量警告状态的电量值,默认:20(15+5)mLowBatteryAlertCloseLevel = mLowBatteryReminderLevels[0]+ mContext.getResources().getInteger(com.android.internal.R.integer.config_lowBatteryCloseWarningBump);}

电池相关广播监听

final class Receiver extends BroadcastReceiver {private boolean mHasReceivedBattery = false;public void init() {// Register for Intent broadcasts for...IntentFilter filter = new IntentFilter();// 省电模式改变filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);// 电池状态改变filter.addAction(Intent.ACTION_BATTERY_CHANGED);// 开关屏filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_SCREEN_ON);// 切换用户filter.addAction(Intent.ACTION_USER_SWITCHED);mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler);// Force get initial values. Relying on Sticky behavior until API for getting info.if (!mHasReceivedBattery) {// Get initial stateIntent intent = mContext.registerReceiver(null,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));if (intent != null) {onReceive(mContext, intent);}}}@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {ThreadUtils.postOnBackgroundThread(() -> {if (mPowerManager.isPowerSaveMode()) {// 开启省电模式则关闭低电量警告mWarnings.dismissLowBatteryWarning();}});} else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {mHasReceivedBattery = true;// 电量final int oldBatteryLevel = mBatteryLevel;mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);final int oldBatteryStatus = mBatteryStatus;mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,BatteryManager.BATTERY_STATUS_UNKNOWN);// 充电final int oldPlugType = mPlugType;mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);final int oldInvalidCharger = mInvalidCharger;mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;final boolean plugged = mPlugType != 0;final boolean oldPlugged = oldPlugType != 0;// 根据当前电量与危急电量、低电量、关闭低电量警告电量比较判断当前所处状态int oldBucket = findBatteryLevelBucket(oldBatteryLevel);int bucket = findBatteryLevelBucket(mBatteryLevel);if (DEBUG) {Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel+ " .. " + mLowBatteryReminderLevels[0]+ " .. " + mLowBatteryReminderLevels[1]);Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);}// 更新电池警告信息mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);if (oldInvalidCharger == 0 && mInvalidCharger != 0) {Slog.d(TAG, "showing invalid charger warning");mWarnings.showInvalidChargerWarning();return;} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {mWarnings.dismissInvalidChargerWarning();} else if (mWarnings.isInvalidChargerWarningShowing()) {// if invalid charger is showing, don't show low batteryif (DEBUG) {Slog.d(TAG, "Bad Charger");}return;}// Show the correct version of low battery warning if neededif (mLastShowWarningTask != null) {mLastShowWarningTask.cancel(true);if (DEBUG) {Slog.d(TAG, "cancelled task");}}mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {// 判断是否要显示低电量警告maybeShowBatteryWarningV2(plugged, bucket);});} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {mScreenOffTime = SystemClock.elapsedRealtime();} else if (Intent.ACTION_SCREEN_ON.equals(action)) {mScreenOffTime = -1;} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {mWarnings.userSwitched();} else {Slog.w(TAG, "unknown intent: " + intent);}}}
protected void maybeShowBatteryWarningV2(boolean plugged, int bucket) {final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();final boolean isPowerSaverMode = mPowerManager.isPowerSaveMode();// Stick current battery state into an immutable container to determine if we should show// a warning.if (DEBUG) {Slog.d(TAG, "evaluating which notification to show");}if (hybridEnabled) {if (DEBUG) {Slog.d(TAG, "using hybrid");}Estimate estimate = refreshEstimateIfNeeded();mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),estimate.getAverageDischargeTime(),mEnhancedEstimates.getSevereWarningThreshold(),mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(),mEnhancedEstimates.getLowWarningEnabled());} else {if (DEBUG) {Slog.d(TAG, "using standard");}mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],mLowBatteryReminderLevels[0]);}mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);if (mCurrentBatteryStateSnapshot.isHybrid()) {maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);} else {maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);}}protected void maybeShowBatteryWarning(BatteryStateSnapshot currentSnapshot,BatteryStateSnapshot lastSnapshot) {final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()|| lastSnapshot.getPlugged();if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {mWarnings.showLowBatteryWarning(playSound);} else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {mWarnings.dismissLowBatteryWarning();} else {mWarnings.updateLowBatteryWarning();}}

在ACTION_SCREEN_OFF、ACTION_SCREEN_ON这两个广播事件处理中只是简单的对 mScreenOffTime 进行了重新赋值,当屏幕关闭时设置为从系统启动到现在的时间,当屏幕开启时设置为 -1。该值用于在其他位置做差值判断如播放低电量声音时是否播放。

      final ContentResolver cr = mContext.getContentResolver();final int silenceAfter = Settings.Global.getInt(cr,Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;if (silenceAfter > 0&& mScreenOffTime > 0&& offTime > silenceAfter) {Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter+ "ms): not waking up the user with low battery sound"); // 屏幕休眠时间太久了,不使用低电量声音唤醒使用者return;}

ACTION_BATTERY_CHANGED 广播

final int oldBatteryLevel = mBatteryLevel;mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);final int oldBatteryStatus = mBatteryStatus;mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,BatteryManager.BATTERY_STATUS_UNKNOWN);final int oldPlugType = mPlugType;mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);final int oldInvalidCharger = mInvalidCharger;mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);final boolean plugged = mPlugType != 0; final boolean oldPlugged = oldPlugType != 0;int oldBucket = findBatteryLevelBucket(oldBatteryLevel); int bucket = findBatteryLevelBucket(mBatteryLevel); // 获取电量等级判断

相关判断如下

 if (DEBUG) { // debug 环境下输出更多的日志信息Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel+ " .. " + mLowBatteryReminderLevels[0]+ " .. " + mLowBatteryReminderLevels[1]);Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);}if (oldBatteryStatus == BatteryManager.BATTERY_STATUS_FULL&& mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {mIfDisChargeHappen = 1; // 如果电池满并且没有再充电状态下 mIfDisChanrgeHappen =1}if (oldInvalidCharger == 0 && mInvalidCharger != 0) { // 判断新旧充电是否可用Slog.d(TAG, "showing invalid charger warning");showInvalidChargerDialog(); // 不可用弹出充电不可用的对话框return;} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {dismissInvalidChargerDialog(); // 充电可用后 让对话框消失} else if (mInvalidChargerDialog != null) {// if invalid charger is showing, don't show low battery// 如果不可用的对话框已经存在就不提示低电量return;}

下面判断是否弹出电量低及充电满和播放声音

 if (!plugged&& ((bucket < oldBucket || oldPlugged) || (mBatteryLevel==1 || oldPlugged))&& mBatteryStatus != BatteryManager.BATTERY_STATUS_CHARGING&& bucket < 0) {showLowBatteryWarning(); // 弹出低电量报警// only play SFX when the dialog comes up or the bucket changesif (bucket != oldBucket || oldPlugged) {playLowBatterySound(); // 播放低电量报警声音}} else if (plugged || (bucket > oldBucket && bucket > 0)) {dismissLowBatteryWarning(); // 让低电量报警消失} else if (mBatteryLevelTextView != null) {showLowBatteryWarning();}if(!plugged) {mOldPluggedFull = 0;dismissFullBatteryWarning(); // 让满电提示消失}if(mBatteryLevel >= 100 && plugged&& mOldPluggedFull == 0 && mIfDisChargeHappen == 1) {mOldPluggedFull = 1 ;showFullBatteryWarning(); // 显示满电提示playLowBatterySound(); //播放声音mIfDisChargeHappen = 0;} else if ( mBatteryLevel < 100 && isChargerConnected(mPlugType)) {if (mUsbPlugged == 1) {playChargerConnectedSound(); // 播放连接充电时的声音}mUsbPlugged ++;}

SystemUI中的PowerUI简析相关推荐

  1. 今晚直播 | 强化学习在比赛和自动机器学习中的应用简析

    「AI Drive」是由 PaperWeekly 和 biendata 共同发起的学术直播间,旨在帮助更多的青年学者宣传其最新科研成果.我们一直认为,单向地输出知识并不是一个最好的方式,而有效地反馈和 ...

  2. 离散数学中Warshall算法简析

    离散数学中Warshall算法简析 最近学了离散数学的图论,突然感觉离散数学的作用十分强大,相信学好离散数学中的算法,编程的魅力也不言而喻.闲话不多说,这篇博客中记录的是Warshall算法的简单解析 ...

  3. pythonimportre_python中re模块简析

    python中re模块简析 发布时间:2020-05-20 20:01:47 来源:51CTO 阅读:383 re的分组功能 python的re模块有一个分组功能.所谓的分组就是去已经匹配到的内容里面 ...

  4. PHP+新浪微博开放平台+新浪云平台(SAE)开发微博应用——PHP SDK中Demo程序简析

    PHP+新浪微博开放平台+新浪云平台(SAE) --新浪微博应用开发的一个解决方案 一.PHP+新浪微博开放平台+新浪云平台(SAE)方案的基础 二.建立微博应用的过程 三.PHP SDK中Demo程 ...

  5. STL中sort算法简析

    STL里sort算法简析 文章目录 STL里sort算法简析 一.引入 二.正解 三.源码 **`sort的源码`**: **`其中,__introsort_loop便是内省式排序:`** 插入排序 ...

  6. ahp层次分析法软件_层次分析法在历史街区研究中的应用简析

    摘要 AHP (Analytic Hierarchy Process)层次分析法通常被运用于解决多目标.多标准.多要素.多层次的非结构化的复杂决策性问题,特别是战略决策性问题,在建筑.规划.风景园林等 ...

  7. Windows Server 2008域中组的简析

    在域中创建合乎具体生产环境的组对象,先要搞清楚各类组作用域和类型,见下图: 组作用域(Group Scope): 本地域(Domain Local):可用于包含具有相似资源访问需求的用户和组,例如所有 ...

  8. 《传送门》游戏中传送机制简析

    相信大家对于传送门应该在电影或者游戏看过很多了,无缝传送门这个机制也不是Value公司第一次在游戏中实现,早已经有很多游戏实现过,比如<影子武士>.<雷神之锤>等等都使用了各种 ...

  9. RocketMQ 在联想大数据中的应用简析

    http://casaveneziausa.com/lenovo-logo/ 众所周知,RocketMQ 作为一款分布式.队列模型的消息中间件,具有以下特点: 严格保证的消息顺序 丰富的消息拉取模式 ...

最新文章

  1. 来,一起手撸一个简版 Redis(附源码)
  2. ThinkPHP3.2.3 字段映射/自动验证/自动完成
  3. 不要把HANA跟BW混为一谈
  4. Vue——定义全局工具类
  5. POJ 3061 -- Subsequence(二分)
  6. 为什么需要函数式编程?
  7. R语言ggplot2画图3
  8. 38 | 测试数据的“银弹”- 统一测试数据平台(下)
  9. odi 12.2.1.1新特性
  10. android studio报错:ClassLoader referenced unknown path: /data/app/xxxx-1/lib/arm64
  11. python黑网站充值_Python黑帽子:Windows系统提权
  12. icode青少年编程比赛网站学生刷题进度爬虫
  13. qt html表格自动增加行,QT中的tablewidget如何插入一行数据
  14. Django项目实践(商城):十七、商品详情页面
  15. 夫妻卖盲盒、年入16亿,揭秘泡泡玛特的暴利生意
  16. 暗影骑士vn7安装linux,宏碁暗影骑士一代(VN7-591G)拆机清灰教程
  17. 即插即用demo系列——文本相似度比较
  18. SQL Server 的几个故障
  19. tf-faster-rcnn在cpu下运行demo、测试和训练自己的数据集
  20. 光纤接入网广域网连接拓扑结构设计

热门文章

  1. 咖啡泡JAVA_【转】咖啡—冲泡方式
  2. word文档导航栏中的同级菜单不对齐
  3. Python画海绵宝宝、小猪佩奇、皮卡丘
  4. 普吉岛最后的黄昏,中文字幕
  5. TZC 高中信息技术(Python)必修题单————题解
  6. 12-类和对象的概念
  7. Vue笔记(8) - 案例
  8. 数据可视化(Echarts、antv)
  9. 【人工智能概论】 变分自编码器(Variational Auto Encoder , VAE)
  10. iOS进度条 自定义圆角 UIProgressView