Android PowerManager 进入屏保、睡眠的过程梳理

灭屏screen_off和睡眠sleep都有对应的配置时间,如果Settings开了接口也都是可以配置的。默认情况下要看SettingsProvider里面对应的default的值,当然特定的产品要考虑到overlay的情况。

比如在这里def_screen_off_timeout则是60s,而def_sleep_timeout是-1则表示关闭了睡眠功能。换句话说,机器不用过1分钟系统会进入屏保,不会睡眠,屏幕或者hdmi是一直都有信号输出的。

SettigsProvider defaults.xml

    <integer name="def_screen_off_timeout">60000</integer>
    <integer name="def_sleep_timeout">-1</integer>

overlay的情况

这里面默认的睡眠时间是20s,屏保时间是10s,也就是说没事做10s进屏保,再过10s进睡眠。


    <integer name="def_sleep_timeout">20000</integer>

    <integer name="def_screen_off_timeout">10000</integer>

 参考日志

08-22 05:09:51.244  3067  3092 I PowerManagerService: Nap time (uid 1000)...
08-22 05:09:51.245  3067  3092 I DreamManagerService: Entering dreamland.
08-22 05:09:51.245  3067  3092 I PowerManagerService: Dreaming...

08-22 05:10:01.243  3067  3092 I PowerManagerService: Going to sleep due to screen timeout (uid 1000)...
08-22 05:10:01.244  3067  3092 I DreamManagerService: Gently waking up from dream.
08-22 05:10:01.245  3067  3092 I PowerManagerService: Sleeping (uid 1000)...
08-22 05:10:01.247  2892  2954 E         : getRealActiveConfig to config(0).
08-22 05:10:01.248  3067  3088 I DreamManagerService: Performing gentle wake from dream.

在每次更新系统power状态的时候,都要基于当前的user activity计算再次唤醒或者睡眠的时间。关键函数updateUserActivitySummaryLocked,主要是计算出下次超时时间nextTimeout和用户状态mUserActivitySummary,当满足nextTimeout到下次更新状态的时候会基于这个用户状态来进行相应的动作,是dim、dream、还是sleep。注意,这个状态的计算是逐层变深的,后面的计算如果满足条件会覆盖掉前面的计算。另一方面,整个系统进入休眠的顺序也一定是dim、dream、doze、sleep。

    /**
     * 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.
     *
     * This function must have no other side-effects.
     */
    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
                    || mWakefulness == WAKEFULNESS_DREAMING
                    || mWakefulness == WAKEFULNESS_DOZING) {
                final long sleepTimeout = getSleepTimeoutLocked();
                final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
                final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
                final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
                final long nextProfileTimeout = getNextProfileTimeoutLocked(now);

                mUserActivitySummary = 0;
                if (mLastUserActivityTime >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTime
                            + screenOffTimeout - screenDimDuration;
                    if (now < nextTimeout) {
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        nextTimeout = mLastUserActivityTime + screenOffTimeout;
                        if (now < nextTimeout) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }
                if (mUserActivitySummary == 0
                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                    if (now < nextTimeout) {
                        if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
                                || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                            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;
                    }
                }

                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;
                        }
                    }
                    mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                    nextTimeout = -1;
                }

                if (nextProfileTimeout > 0) {
                    nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
                }

                if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                    scheduleUserInactivityTimeout(nextTimeout);
                }
            } else {
                mUserActivitySummary = 0;
            }

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
                        + PowerManagerInternal.wakefulnessToString(mWakefulness)
                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
                        + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
            }
        }
    }

summary

    // Summarizes the user activity state.
    private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
    private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
    private static final int USER_ACTIVITY_SCREEN_DREAM = 1 << 2;

获得系统睡眠超时时间,要从设定值和最小灭屏值选一个大的出来,最小灭屏值一般是10s,也就是说睡眠时间不能比最小的灭屏值还小。

    private long getSleepTimeoutLocked() {
        final long timeout = mSleepTimeoutSetting;
        if (timeout <= 0) {
            return -1;
        }
        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
    }

在初始化updateSettingsLocked里面,从SettingsProvider读数据,如果没有设定过就是默认值。

        mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
                Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
                UserHandle.USER_CURRENT);
        mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver,
                Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT,
                UserHandle.USER_CURRENT);

后去系统灭屏超时时间,这个主要是选一个睡眠超时和系统灭屏时间的较小值。比如前面的是灭屏是10s,睡眠是20s,那就是10s,反之还是10s。前面的两个if里面的条件一般不满足。

    private long getScreenOffTimeoutLocked(long sleepTimeout) {
        long timeout = mScreenOffTimeoutSetting;
        if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
            timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
        }
        if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
            timeout = Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
        }
        if (sleepTimeout >= 0) {
            timeout = Math.min(timeout, sleepTimeout);
        }
        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
    }

最小灭屏值是在framework/base里面config.xml里面设定的

 <integer name="config_minimumScreenOffTimeout">10000</integer>

参考日志

mWakefulness从Dreaming到Dozing到Asleep,mUserActivitySummary从USER_ACTIVITY_SCREEN_DREAM到啥都没。

08-22 06:22:02.828  3064  5660 D PowerManagerService: updateUserActivitySummaryLocked: mWakefulness=Dreaming, mUserActivitySummary=0x4, nextTimeout=146181 (in 264 ms)
08-22 06:22:02.828  3064  5660 D PowerManagerService: updateDisplayPowerStateLocked: mDisplayReady=true, policy=3, mWakefulness=2, mWakeLockSummary=0x3, mUserActivitySummary=0x4, mBootCompleted=true, screenBrightnessOverride=-1, useAutoBrightness=false, mScreenBrightnessBoostInProgress=false, mIsVrModeEnabled= false, sQuiescent=false

08-22 06:22:03.093  3064  3089 D PowerManagerService: handleUserActivityTimeout
08-22 06:22:03.093  3064  3089 D PowerManagerService: updateUserActivitySummaryLocked: mWakefulness=Dreaming, mUserActivitySummary=0x0, nextTimeout=146181 (1 ms ago)
08-22 06:22:03.093  3064  3089 D PowerManagerService: updateDisplayPowerStateLocked: mDisplayReady=true, policy=3, mWakefulness=2, mWakeLockSummary=0x3, mUserActivitySummary=0x0, mBootCompleted=true, screenBrightnessOverride=-1, useAutoBrightness=false, mScreenBrightnessBoostInProgress=false, mIsVrModeEnabled= false, sQuiescent=false
08-22 06:22:03.093  3064  3089 D PowerManagerService: goToSleepNoUpdateLocked: eventTime=146182, reason=2, flags=0, uid=1000
08-22 06:22:03.093  3064  3089 I PowerManagerService: Going to sleep due to screen timeout (uid 1000)...


08-22 06:22:03.094  3064  3089 D PowerManagerService: updateWakeLockSummaryLocked: mWakefulness=Dozing, mWakeLockSummary=0x3
08-22 06:22:03.094  3064  3089 D PowerManagerService: updateUserActivitySummaryLocked: mWakefulness=Dozing, mUserActivitySummary=0x0, nextTimeout=146181 (2 ms ago)
08-22 06:22:03.094  3064  3089 D PowerManagerService: updateDisplayPowerStateLocked: mDisplayReady=true, policy=3, mWakefulness=3, mWakeLockSummary=0x3, mUserActivitySummary=0x0, mBootCompleted=true, screenBrightnessOverride=-1, useAutoBrightness=false, mScreenBrightnessBoostInProgress=false, mIsVrModeEnabled= false, sQuiescent=false

08-22 06:22:03.094  3064  3089 I DreamManagerService: Gently waking up from dream.
08-22 06:22:03.095  3064  3089 D PowerManagerService: reallyGoToSleepNoUpdateLocked: eventTime=146184, uid=1000
08-22 06:22:03.095  3064  3089 I PowerManagerService: Sleeping (uid 1000)...
08-22 06:22:03.095  3064  3089 D PowerManagerService: updateWakeLockSummaryLocked: mWakefulness=Asleep, mWakeLockSummary=0x1
08-22 06:22:03.095  3064  3089 D PowerManagerService: updateUserActivitySummaryLocked: mWakefulness=Asleep, mUserActivitySummary=0x0, nextTimeout=0 (146185 ms ago)
08-22 06:22:03.096  3064  3089 D PowerManagerService: updateDisplayPowerStateLocked: mDisplayReady=false, policy=0, mWakefulness=0, mWakeLockSummary=0x1, mUserActivitySummary=0x0, mBootCompleted=true, screenBrightnessOverride=-1, useAutoBrightness=false, mScreenBrightnessBoostInProgress=false, mIsVrModeEnabled= false, sQuiescent=false
08-22 06:22:03.096  3064  3085 I DreamManagerService: Performing gentle wake from dream.

 

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android睡眠机制是指当 Android 设备进入空闲状态(例如长时间没有操作屏幕或者按键)时,系统会自动关闭一些硬件设备(如屏幕、CPU 等)以节省电力。这个状态也称为深度睡眠状态(Deep Sleep)。 在 Android 中,睡眠机制分为两种模式:系统睡眠和设备睡眠。 1. 系统睡眠 系统睡眠是指 Android 系统进入睡眠状态,此时系统会关闭屏幕和键盘背光灯、降低 CPU 频率等。但是,系统仍然会继续运行某些服务和进程,例如接收来电和短信等。 2. 设备睡眠 设备睡眠是指 Android 设备进入睡眠状态,此时系统会关闭所有硬件设备,包括 CPU、屏幕等。这种状态下,设备不会响应任何操作,直到唤醒它。 在 Android 中,设备睡眠模式又分为以下几种: - PARTIAL_WAKE_LOCK:保持 CPU 运转,屏幕和键盘背光灯关闭。 - SCREEN_DIM_WAKE_LOCK:保持 CPU 运转,屏幕变暗,键盘背光灯关闭。 - SCREEN_BRIGHT_WAKE_LOCK:保持 CPU 运转,屏幕亮度保持不变,键盘背光灯关闭。 - FULL_WAKE_LOCK:保持 CPU 运转,屏幕和键盘背光灯都亮。 开发者可以使用 PowerManager 类来控制设备睡眠模式。例如,通过 acquire 方法获取一个 WakeLock 对象,保持设备处于唤醒状态。使用完后,通过 release 方法释放 WakeLock 对象。 示例代码: ```java PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakeLockTag"); wakeLock.acquire(); // do something wakeLock.release(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值