PMS更新各个状态,最终都会调用updatePowerStateLocked函数,下面我们来分析下

    private void updatePowerStateLocked() {if (!mSystemReady || mDirty == 0) {//mDirty=0代表没有变化,或者系统没有准备好,直接退出return;}if (!Thread.holdsLock(mLock)) {Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");}Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");try {// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);//更新电源状态updateStayOnLocked(mDirty);updateScreenBrightnessBoostLocked(mDirty);

updateIsPoweredLocked函数,先是要dirty有DIRTY_BATTERY_STATE标志位。我们在下面分析下,什么时候会有这个标志位

    private void updateIsPoweredLocked(int dirty) {if ((dirty & DIRTY_BATTERY_STATE) != 0) {final boolean wasPowered = mIsPowered;final int oldPlugType = mPlugType;final boolean oldLevelLow = mBatteryLevelLow;mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);//这些都是从BatteryService获取mPlugType = mBatteryManagerInternal.getPlugType();mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();if (DEBUG_SPEW) {Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered+ ", mIsPowered=" + mIsPowered+ ", oldPlugType=" + oldPlugType+ ", mPlugType=" + mPlugType+ ", mBatteryLevel=" + mBatteryLevel);}if (wasPowered != mIsPowered || oldPlugType != mPlugType) {//是否充电或者充电类型改变了mDirty |= DIRTY_IS_POWERED;//mDirty置位// Update wireless dock detection state.final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(//无线充电相关mIsPowered, mPlugType, mBatteryLevel);// Treat plugging and unplugging the devices as a user activity.// Users find it disconcerting when they plug or unplug the device// and it shuts off right away.// Some devices also wake the device when plugged or unplugged because// they don't have a charging LED.final long now = SystemClock.uptimeMillis();if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,dockedOnWirelessCharger)) {//是否需要唤醒设备wakeUpNoUpdateLocked(now, Process.SYSTEM_UID);}userActivityNoUpdateLocked(//触发userActivitynow, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);// Tell the notifier whether wireless charging has started so that// it can provide feedback to the user.if (dockedOnWirelessCharger) {//无线充电相关mNotifier.onWirelessChargingStarted();}}if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {if (DEBUG_SPEW) {Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");}mAutoLowPowerModeSnoozing = false;}updateLowPowerModeLocked();//更新低功耗模式}}}

首先systemReady函数最终会把mDirty置位为DIRTY_BATTERY_STATE,还有收BatterySevice发出来的广播,最总也会置这个标志位。

    private final class BatteryReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {synchronized (mLock) {handleBatteryStateChangedLocked();}}}
    private void handleBatteryStateChangedLocked() {mDirty |= DIRTY_BATTERY_STATE;updatePowerStateLocked();}

再来看看电池状态发生什么变化要唤醒设备:

    private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {// Don't wake when powered unless configured to do so.if (!mWakeUpWhenPluggedOrUnpluggedConfig) {//如果资源中没有配置这项,直接退出不唤醒设备return false;}// Don't wake when undocked from wireless charger.// See WirelessChargerDetector for justification.if (wasPowered && !mIsPowered&& oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {//这是一个 拔出的工作,然后之前的无线充电return false;}// Don't wake when docked on wireless charger unless we are certain of it.// See WirelessChargerDetector for justification.if (!wasPowered && mIsPowered&& mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS//插入动作,现在是无线充电&& !dockedOnWirelessCharger) {return false;}// If already dreaming and becoming powered, then don't wake.if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {//正在充电,但是mWakefulness 是做梦状态return false;}// Don't wake while theater mode is enabled.if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {return false;}// Otherwise wake up!return true;//其他就唤醒设备}

继续分析updatePowerStateLocked函数,分析updateStayOnLocked函数。一般这个函数mStatyon为fasle,除非在资源中设置哪种充电状态下可以长亮。

    private void updateStayOnLocked(int dirty) {if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {//当dirty是电池状态和设置的状态改变时final boolean wasStayOn = mStayOn;if (mStayOnWhilePluggedInSetting != 0//这个值从资源中读取,一般设置的话代表哪种充电时可以常亮&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {//看有没有设mMaximumScreenOffTimeoutFromDeviceAdmin屏幕最大亮屏时间,没设默认最大。那么这个函数返回是falsemStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);} else {mStayOn = false;}if (mStayOn != wasStayOn) {mDirty |= DIRTY_STAY_ON;}}}

继续分析updatePowerStateLocked函数的updateScreenBrightnessBoostLocked函数,这个函数是更新屏幕是否保持最亮状态

    private void updateScreenBrightnessBoostLocked(int dirty) {if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {//这个状态实在boostScreenBrightnessInternal函数中设置最亮时置位,当然下面发送消息MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT也会将这个标志位置位if (mScreenBrightnessBoostInProgress) {//当前正在最亮屏幕这个状态final long now = SystemClock.uptimeMillis();mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);if (mLastScreenBrightnessBoostTime > mLastSleepTime) {final long boostTimeout = mLastScreenBrightnessBoostTime +SCREEN_BRIGHTNESS_BOOST_TIMEOUT;if (boostTimeout > now) {//看当前时间是否小于最亮屏幕结束的时间Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, boostTimeout);//发送一个延迟的消息,到最亮屏幕结束的时候接受到消息,将标志位置为DIRTY_SCREEN_BRIGHTNESS_BOOST后,重新再回到这个函数return;}}mScreenBrightnessBoostInProgress = false;//回到这个函数时,直接将这个屏幕最亮状态的标志位改成falseuserActivityNoUpdateLocked(now,//触发一个userActivityPowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);}}}

下面看看MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT消息的处理函数。

                case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:handleScreenBrightnessBoostTimeout();break;
    private void handleScreenBrightnessBoostTimeout() { // runs on handler threadsynchronized (mLock) {if (DEBUG_SPEW) {Slog.d(TAG, "handleScreenBrightnessBoostTimeout");}mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;updatePowerStateLocked();}}

接下来看updatePowerStateLocked函数的另一个阶段:

            // Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = SystemClock.uptimeMillis();int dirtyPhase2 = 0;for (;;) {int dirtyPhase1 = mDirty;//这个循环中每次新的mDirty全部给dirtyPhase1,并且在这个循环中使用这个dirtydirtyPhase2 |= dirtyPhase1;//dirtyPhase2 会把之前所有的mDirty状态全部或上,然后用这个状态继续下面的函数mDirty = 0;//mDirty会在这里清零updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}

先看下updateWakeLockSummaryLocked函数,更新wakelock的函数

    private void updateWakeLockSummaryLocked(int dirty) {if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {mWakeLockSummary = 0;final int numWakeLocks = mWakeLocks.size();for (int i = 0; i < numWakeLocks; i++) {final WakeLock wakeLock = mWakeLocks.get(i);switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {//先根据wakelock的flag,mWakeLockSummary或上各种状态case PowerManager.PARTIAL_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_CPU;break;case PowerManager.FULL_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;break;case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;break;case PowerManager.SCREEN_DIM_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;break;case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK://距离传感器相关mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;break;case PowerManager.DOZE_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_DOZE;break;}}// Cancel wake locks that make no sense based on the current state.if (mWakefulness != WAKEFULNESS_DOZING) {//下面根据各种状态,将上面或上的mWakeLockSummary,有的减去mWakeLockSummary &= ~WAKE_LOCK_DOZE;}if (mWakefulness == WAKEFULNESS_ASLEEP|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM| WAKE_LOCK_BUTTON_BRIGHT);if (mWakefulness == WAKEFULNESS_ASLEEP) {mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;}}// Infer implied wake locks where necessary based on the current state.if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {//只要有屏幕锁,cpu锁必须持有if (mWakefulness == WAKEFULNESS_AWAKE) {mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;} else if (mWakefulness == WAKEFULNESS_DREAMING) {mWakeLockSummary |= WAKE_LOCK_CPU;}}if (DEBUG_SPEW) {Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="+ PowerManagerInternal.wakefulnessToString(mWakefulness)+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));}}}

下面分析下updateUserActivitySummaryLocked函数

 private void updateUserActivitySummaryLocked(long now, int dirty) {// Update the status of the user activity timeout timer.if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);long nextTimeout = 0;if (mWakefulness == WAKEFULNESS_AWAKE//状态为awake,dreaming,dozing,否则mUserActivitySummary为0|| mWakefulness == WAKEFULNESS_DREAMING|| mWakefulness == WAKEFULNESS_DOZING) {final int sleepTimeout = getSleepTimeoutLocked();//睡眠timeoutfinal int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);//灭屏的timeoutfinal int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);//屏幕由亮变暗的timeoutmUserActivitySummary = 0;if (mLastUserActivityTime >= mLastWakeTime) {//userActivity的time大于上次唤醒时间nextTimeout = mLastUserActivityTime//这个时间代表是比较亮的一个时间的结束点+ screenOffTimeout - screenDimDuration;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;//mUserActivitySummary赋值} else {nextTimeout = mLastUserActivityTime + screenOffTimeout;//这个时间代表屏幕暗的一个时间结束点if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;}}}if (mUserActivitySummary == 0&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {//这个time是userActivity一个特殊的flag才会设置nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;if (now < nextTimeout) {if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;}}}if (mUserActivitySummary == 0) {if (sleepTimeout >= 0) {final long anyUserActivity = Math.max(mLastUserActivityTime,mLastUserActivityTimeNoChangeLights);if (anyUserActivity >= mLastWakeTime) {nextTimeout = anyUserActivity + sleepTimeout;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;}}} else {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;nextTimeout = -1;//该值为-1,下面就不会发送消息了}}if (mUserActivitySummary != 0 && nextTimeout >= 0) {Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, nextTimeout);//到下个时间timeout结束的时候发送消息,重新进入这个函数}} else {mUserActivitySummary = 0;}

MSG_USER_ACTIVITY_TIMEOUT的消息处理

        @Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_USER_ACTIVITY_TIMEOUT:handleUserActivityTimeout();break;
    private void handleUserActivityTimeout() { // runs on handler threadsynchronized (mLock) {if (DEBUG_SPEW) {Slog.d(TAG, "handleUserActivityTimeout");}mDirty |= DIRTY_USER_ACTIVITY;updatePowerStateLocked();}}

继续分析函数updateWakefulnessLocked

    private boolean updateWakefulnessLocked(int dirty) {boolean changed = false;if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE| DIRTY_DOCK_STATE)) != 0) {if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {//当mWakefulness不是awake的时候,直接返回false,也就是上面的循环退出if (DEBUG_SPEW) {Slog.d(TAG, "updateWakefulnessLocked: Bed time...");}final long time = SystemClock.uptimeMillis();if (shouldNapAtBedTimeLocked()) {changed = napNoUpdateLocked(time, Process.SYSTEM_UID);} else {changed = goToSleepNoUpdateLocked(time,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);}}}return changed;}

再来看看isItBedTimeYetLocked函数

    private boolean isItBedTimeYetLocked() {return mBootCompleted && !isBeingKeptAwakeLocked();}

isBeingKeptAwakeLocked函数,如果isBeingKeptAwakeLocked返回true代表处于亮屏状态,isItBedTimeYetLocked返回false,上面的for死循环退出

    private boolean isBeingKeptAwakeLocked() {return mStayOn|| mProximityPositive//距离传感器有关|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT| USER_ACTIVITY_SCREEN_DIM)) != 0|| mScreenBrightnessBoostInProgress;//屏幕处于最亮状态}

如果isBeingKeptAwakeLocked返回false,并且mBootCompleted 为true开机完成了。那么updateWakefulnessLocked函数进入判断条件
那再来看看shouldNapAtBedTimeLocked函数,就是看有没有做梦这个设置,如果没有直接到goToSleepNoUpdateLocked函数,到了goToSleepNoUpdateLocked函数后将mWakefulness 设为WAKEFULNESS_DOZING显示返回true还要继续循环,下次到updateWakefulnessLocked这个函数,不是awake类型的,也返回false,直接退出死循环了。到napNoUpdateLocked函数也是一样的先是将mWakefulness置为WAKEFULNESS_DREAMING,返回true,继续循环,下次不是awake类型就返回false,退出循环了。

    private boolean shouldNapAtBedTimeLocked() {return mDreamsActivateOnSleepSetting|| (mDreamsActivateOnDockSetting&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);}

下面分析就是updateDisplayPowerStateLocked函数要和Display交互。放在下一篇博客分析。



and5.1PowerManagerService深入分析(三)updatePowerStateLocked函数相关推荐

  1. and5.1PowerManagerService深入分析(四)PMS与Display模块

    and5.1PowerManagerService深入分析(四)PMS与Display模块 转自:http://blog.csdn.net/kc58236582/article/details/480 ...

  2. 12.MySql关于获取当前时间的三个函数

    这三个函数都是获取当前时间的,获取的详细格式如下图所示,可以根据需要来选用. 转载于:https://www.cnblogs.com/Nick-Hu/p/7566805.html

  3. ACMNO.37 C语言-数字交换 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换。写三个函数; ①输入10个数;②进行处理;③输出10个数。

    题目描述 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换. 写三个函数: ①输入10个数:②进行处理:③输出10个数. 输入 10个整数 输出 整理后的十个数,每个数后跟 ...

  4. Math.ceil(),Math.floor()与Math.round()三个函数的定义。

    为什么80%的码农都做不了架构师?>>>    JavaScript: The Definitive Guide, 4th Edition中对Math.ceil(),Math.flo ...

  5. php怎么输出3个函数和,PHP利用var_dump,var_export,print_r三个函数的区别示例

    感兴趣的小伙伴,下面一起跟随512笔记的小玲来看看吧!下面的示例看看这三个函数的具体的区别,其中var_dump和var_export比较少用,但他们两者又很相似.所以可以看看: 代码如下: /* 5 ...

  6. [前端技术]如何加深对JavaScipt中的Math.ceil() 、Math.floor() 、Math.round() 三个函数的理解...

    首先还是看看<The Definitive Guide, 4th Edition>书中对三个函数的的定义. Math.ceil(x): round a number up Argument ...

  7. python多线程的作用_Python多线程中三个函数的强大功能简介

    在Python多线程中有三个比较简单的函数,在实际的相关操作中你对这一实际操作是否了解?是否对其感兴趣?如果你想对Python多线程的开发与多线程程序及相关实际操作方案有所了解的话,你就可以点击以下的 ...

  8. excel三次样条函数_日常系列2:二次和三次函数样条、数据的插值

    本讲导读 本讲适合在讲授或学习完高中数学的基本初等函数章节.三角函数章节和导数章节后,作为数学建模材料,在日常教学中讲授或学习.本讲内容包括但不限于: 一次函数.二次函数.三次函数的统计和物理意义及三 ...

  9. iOS之深入分析GCD的函数与队列以及多种组合使用

    一.GCD 简介 ① 什么是 GCD ? GCD 是 Apple 开发的一个多核编程的较新的解决方法: GCD 全称:Grand Central Dispatch,是纯 C 语言,提供非常多强大的函数 ...

最新文章

  1. SD-WAN是怎样简化企业网络和节省资金的?
  2. datanode无法启动问题
  3. 如何重命名磁盘盘符名?
  4. css:构建响应式网站
  5. sqli-labs less11 POST注入-字符型
  6. Spring声明式事务示例
  7. fir滤波器算法c语言程序,FIR滤波器设计C语言程序
  8. 《软件需求分析(第二版)》第 12 章——需求确认 重点部分总结
  9. eda技术试卷_《EDA技术》试题及答案
  10. ERROR manager.SqlManager: Error reading from database: java.sql.SQLException: Streaming result set
  11. 路由器snmp配置_S7503E V7 snmpv3典型组网配置案例(与IMC联动)
  12. 运行Eclipse出现:a java runtime environment(JRE) or java development kit(JDK) must be....
  13. 基于nagios网络监控平台的实现--具体事例
  14. dwr框架java解析excel_dwr poi java 将excel 导出到客户端
  15. AtmosphericCorrection大气校正_landsat8
  16. 【C++】 【判定质数】 【分解质因数】【筛质数(编制质数表)】
  17. linux安卓管理软件,基于Android的文件管理系统源代码
  18. vue中利用高德地图选取经纬度
  19. 回文素数(10亿)—— unfinished
  20. [VCS]后仿真中的几个基本概念

热门文章

  1. Silverstack Lab for Mac(媒体资源数据管理工具)激活版
  2. 推荐一个可以在电脑上玩所有下载渠道手游的安卓模拟器
  3. 用户头像上传(自用)
  4. Python批量提取Excel文件中文本框组件里的文本
  5. 【案例1】图书馆管理系统毕业论文
  6. 王者归来,低代码的逆袭之路
  7. python程序设计论文_浅谈初中Python程序设计教学的实践与体会
  8. win7java浏览器崩溃_浏览器崩溃怎么办,教你win7系统浏览器崩溃的应对办法
  9. Python 实现 PDF转图片 图片转PDF
  10. luooj最强阵容加强版