相关文章推荐
玩足球的白开水  ·  PowerManagerService分析( ...·  10 小时前    · 
至今单身的保温杯  ·  Android 休眠(一) ...·  10 小时前    · 
刚毅的硬币  ·  Day 31 - 使用 Amazon ...·  4 天前    · 
憨厚的枇杷  ·  Getting error ...·  3 月前    · 
爱逃课的葡萄酒  ·  AWK ...·  1 年前    · 
求醉的大白菜  ·  SQLServer 分页Offset ...·  1 年前    · 
力能扛鼎的筷子  ·  MTK/Android GPS ...·  1 年前    · 

https://blog.csdn.net/Gaugamela/article/details/52838654 Android7.0 PowerManagerService(3) 核心函数updatePowerStateLocked的主要流程

https://mp.weixin.qq.com/s/P3IvBrYt7afEa4XyEd3BQg PowerManagerService分析(二)

https://blog.csdn.net/u011311586/article/details/51034313 (原创)android6.0系统 PowerManager深入分析

Platform: RK3288
OS: Android 7.1.2
Kernel: 4.4.143

一.frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

1.在updatePowerStateLocked()方法中,设置了一个死循环,并且上述分析的两个方法都在死循环中执行,
为何设计一个死循环与它循环内部的实现有关系。updateWakefulnessLocked(),这个方法是退出循环的关键。
如果这个方法返回false,则循环结束,如果返回true,则进行下一次循环

    private void updatePowerStateLocked() {
        if (!mSystemReady || 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);
            // 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;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;
                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
            // Phase 2: Update display power state.
            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
            // Phase 3: Update dream state (depends on display ready signal).
            updateDreamLocked(dirtyPhase2, displayBecameReady);
            // Phase 4: Send notifications, if needed.
            finishWakefulnessChangeIfNeededLocked();
            // Phase 5: Update suspend blocker.
            // Because we might release the last suspend blocker here, we need to make sure
            // we finished everything else first!
            updateSuspendBlockerLocked();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);

2.进入休眠,实现休眠的方法  

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) {
           //当前屏幕保持唤醒&&设备将要退出唤醒状态(睡眠or屏保)
           if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
               Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
               final long time = SystemClock.uptimeMillis();
               //是否在休眠时启用屏保
               if (shouldNapAtBedTimeLocked()) {
                  //进入屏保,返回true
                  changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
                  } else {
                     //进入睡眠,返回true
                     changed = goToSleepNoUpdateLocked(time,
                     PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, 
                     Process.SYSTEM_UID);
    return changed;

3.updateUserActivitySummaryLocked主要根据用户最后的活动来决定当前屏幕的状态。
举个栗子,休眠的时,先变暗一下(USER_ACTIVITY_SCREEN_DIM 暗屏),再休眠

在该函数中用mUserActivitySummary变量存储当前屏幕的状态。
一共有3中基本状态:
* USER_ACTIVITY_SCREEN_BRIGHT 点亮屏幕
* USER_ACTIVITY_SCREEN_DIM 屏幕变暗
* USER_ACTIVITY_SCREEN_DREAM 屏保状态
从代码可以看出,屏幕变化和userActivity活动有关,它根据最后的userActivity活动的时间决定点亮屏幕、调暗屏幕或熄灭屏幕

* Updates the value of mUserActivitySummary to summarize the user requested * state of the system such as whether the screen should be bright or dim. * Note that user activity is ignored when the system is asleep. private void updateUserActivitySummaryLocked(long now, int dirty) { 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 || mWakefulness == WAKEFULNESS_DREAMING || mWakefulness == WAKEFULNESS_DOZING) { //获取进入休眠状态的时间sleepTimeout //getSleepTimeoutLocked中会判断休眠时间和屏幕熄灭时间的关系 //如果休眠时间sleepTimeout小于屏幕熄灭时间screenOfftime, //则休眠时间被调整为屏幕熄灭时间,因为屏幕亮屏状态下,终端不能进入休眠 final int sleepTimeout = getSleepTimeoutLocked(); //获取屏幕熄灭的时间 final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout); //获取屏幕变暗的时间 final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); //当Window Manager判定用户inactive时,将此标志置为true final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager; //类似于之前的mWakeLockSummary,将当前的用户事件,转化为PMS可以处理的屏幕状态 mUserActivitySummary = 0; //在唤醒的状态下,发生过用户事件 if (mLastUserActivityTime >= mLastWakeTime) { //重新计算出屏幕需要变暗的时间 nextTimeout = mLastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < nextTimeout) { //如果没有到达需要变暗的时间,那么当前屏幕的状态为USER_ACTIVITY_SCREEN_BRIGHT(亮屏) mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { //到达变暗的时间,则计算出屏幕熄灭的时间 nextTimeout = mLastUserActivityTime + screenOffTimeout; if (now < nextTimeout) { //还没到熄灭的时间,则当前屏幕的状态为USER_ACTIVITY_SCREEN_DIM(暗屏) mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; //注意mUserActivitySummary为0才会进入下面的分支 //即上面改变mUserActivitySummary的条件不满足时,才会进入这个分支(例如:唤醒状态下,没发生过改变屏幕状态的UserActivity) if (mUserActivitySummary == 0 //mLastUserActivityTimeNoChangeLights表示用户最后的活动不会改变屏幕当前的状态 && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) { //计算下次屏幕熄灭的时间 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) { //走到这个分支,应该是屏幕已经熄灭,但还未到达休眠状态,先进入dream态 mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; } else { //直接进入dream态,后文的updateWakefulnessLocked将判断是否休眠 mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; nextTimeout = -1; //如果屏幕未进入dream态,但Window Manager判定用户inactive,则进入下面分支 if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) { //如果屏幕未熄灭 if ((mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) { // Device is being kept awake by recent user activity if (nextTimeout >= now && mOverriddenTimeout == -1) { // Save when the next timeout would have occurred mOverriddenTimeout = nextTimeout; //Window Manager的权限很大,如果它判断用户inactive,直接进入dream态 mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; nextTimeout = -1; //根据nextTimeOut延迟发送信息,信息被处理后,将重新调用updatePowerStateLocked,于是再次进入到该方法 //通过不断进入该方法,不断评估是否根据用户动作亮、熄屏等 if (mUserActivitySummary != 0 && nextTimeout >= 0) { Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, nextTimeout); } else { mUserActivitySummary = 0; ..........

4.isItBedTimeYetLocked()方法,该方法判断当前设备是否将要进入睡眠状态,
返回值为对isBeKeptAwakeLocke()方法返回值取反,由mStayOn(是否屏幕常亮)、wakelockSummary、
userActivitySummary、mProximityPositive等决定,只要满足其中之一为ture,则说明无法进入睡眠,
也就说,要满足进入睡眠,相关属性值都为false。

   private boolean isItBedTimeYetLocked() {
        return mBootCompleted && !isBeingKeptAwakeLocked();
private boolean isBeingKeptAwakeLocked() {return mStayOn//屏幕是否保持常亮
    || mProximityPositive//接近传感器接近屏幕时为true
    //处于awake状态
    || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
    //屏幕处于亮屏或者dim状态
    || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
            | USER_ACTIVITY_SCREEN_DIM)) != 0            
    || mScreenBrightnessBoostInProgress;//处于亮度增强中}  

 5.updateWakeLockSummaryLocked函数根据PMS当前持有的所有WakeLock,得到当前终端整体的信息,保存到mWakeLockSummary变量中 

* Updates the value of mWakeLockSummary to summarize the state of all active wake locks. * Note that most wake-locks are ignored when the system is asleep. private void updateWakeLockSummaryLocked(int dirty) { //PMS持有的WakeLock发生变化,或者唤醒状态发生变化时,才重新进行更新mWakeLockSummary //例如:调用PMS的acquireWakeLock时,就会将dirty的DIRTY_WAKE_LOCKS位置1 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); //这里只关注WakeLock的level //下面的代码其实就是实现每个level WakeLock对应的注释信息 switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { case PowerManager.PARTIAL_WAKE_LOCK: //在分析PMS acquireWakeLock的流程时,已经提到过 //在doze模式下,不在白名单内的非系统应用申请PARTIAL_WAKE_LOCK时,将被disabled if (!wakeLock.mDisabled) { // We only respect this if the wake lock is not disabled. 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; case PowerManager.DRAW_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_DRAW; break; // Cancel wake locks that make no sense based on the current state. //从下面的代码可以看出,PMS中的mWakefulness变量记录了终端当前的状态 //下面就是移除在特定状态下,没有意义的WakeLock if (mWakefulness != WAKEFULNESS_DOZING) { //如果不是Dozing状态,移除相应的wakeLock标志位 mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW); if (mWakefulness == WAKEFULNESS_ASLEEP || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) { //如果当前为Asleep或者有Doze的wakeLock锁的时候,应该移除掉屏幕亮度相关的wakeLock锁 mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM | WAKE_LOCK_BUTTON_BRIGHT); if (mWakefulness == WAKEFULNESS_ASLEEP) { //休眠时,sensor不再需要监听终端是否靠近物体,以触发亮灭屏 mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF; // Infer implied wake locks where necessary based on the current state. //根据当前的状态,及PMS持有的WakeLock,推断出隐含的持锁需求 //例如:当PMS持有亮屏锁WAKE_LOCK_SCREEN_BRIGHT时,若当前终端为唤醒态 //那么CPU显然也需要处于唤醒态 if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) { if (mWakefulness == WAKEFULNESS_AWAKE) { mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE; } else if (mWakefulness == WAKEFULNESS_DREAMING) { mWakeLockSummary |= WAKE_LOCK_CPU; if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) { mWakeLockSummary |= WAKE_LOCK_CPU; ...................

二.RK3288 Android 7.1 HDMI 休眠

diff --git a/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java b/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
index d38a942..93ff2a1 100755
--- a/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@@ -93,6 +93,8 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
 //FOR CEC
 import android.hardware.hdmi.*;
 import android.os.ServiceManager;
+import java.io.File;
+import java.util.Scanner;
@@ -1628,6 +1630,25 @@ public final class PowerManagerService extends SystemService
+	private static boolean isHdmiSwitchSet() {
+		File switchFile = new File("/sys/devices/virtual/switch/hdmi/state");
+		if (!switchFile.exists()) {
+			switchFile = new File("/sys/class/switch/hdmi/state");
+		try {
+			Scanner switchFileScanner = new Scanner(switchFile);
+			int switchValue = switchFileScanner.nextInt();
+			switchFileScanner.close();
+			return switchValue > 0;
+		} catch (Exception e) {
+			return false;
      * Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
      * Note that most wake-locks are ignored when the system is asleep.
@@ -1642,7 +1663,13 @@ public final class PowerManagerService extends SystemService
             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) {
+				int  xhmFlags;
+				if(isHdmiSwitchSet()) {
+				   xhmFlags = 1; 
+				}else { 			
+			       xhmFlags = wakeLock.mFlags;
+				}
+                switch (xhmFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                     case PowerManager.PARTIAL_WAKE_LOCK:
                         if (!wakeLock.mDisabled) {
                             // We only respect this if the wake lock is not disabled.