安卓屏保调试2

9 阅读4分钟

安卓屏保调试2 - Wesley's Blog

上一年为了研究屏保过程投屏,写了一篇文章:安卓屏保调试 - Wesley's Blog

今年为了做屏保广告又跟屏保打上交道了。

起初发现一台机器 dream 时间到了之后怎么也出不了屏保,直接把 dumpsys power 结果喂给 gpt,一下子就解决了,记录一下。

dumpsys power | grep -i mStayOnWhilePluggedInSetting 这个结果显示 3,改成 0 就可以了。

stay_on_while_plugged_in

/**
         * Whether we keep the device on while the device is plugged in.
         * Supported values are:
         * <ul>
         * <li>{@code 0} to never stay on while plugged in</li>
         * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
         * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
         * <li>{@link BatteryManager#BATTERY_PLUGGED_WIRELESS} to stay on for wireless charger</li>
         * <li>{@link BatteryManager#BATTERY_PLUGGED_DOCK} to stay on for dock charger</li>
         * </ul>
         * These values can be OR-ed together.
         */
@Readable
public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";

基础单值(对应特定的供电方式)

  • 0:关闭状态(默认值)。无论连接什么电源,设备都会遵循常规的休眠和屏保倒计时。
  • 1:交流电 (AC)。只有在使用电源适配器(插在墙上)充电时,屏幕才保持常亮。对应底层常量 BatteryManager.BATTERY_PLUGGED_AC
  • 2:USB。只有在连接到电脑或其他 USB 端口充电时,屏幕才保持常亮。对应底层常量 BatteryManager.BATTERY_PLUGGED_USB
  • 4:无线充电 (Wireless)。只有在使用无线充电器时,屏幕才保持常亮。对应底层常量 BatteryManager.BATTERY_PLUGGED_WIRELESS
  • 8:底座 (Dock)。插在专用底座上时保持常亮。对应底层常量 BatteryManager.BATTERY_PLUGGED_DOCK

由于采用了位掩码设计,可以将上述基础值相加(按位或操作 |),以同时支持多种情况:

  • 3 (1 + 2):只要插着交流电或 USB,就不休眠。(最常见的组合值)
  • 7 (1 + 2 + 4):只要连着交流电、USB 或 无线充电中的任意一种,就不休眠。(通常被开发者用来表示“只要通电就不休眠”)

对于 Android TV 来说,由于它没有电池,通常被系统视为始终处于“AC 供电”状态。所以只要这个值包含了 1(比如设成了 1, 37),TV 就永远不会进入 Dream 屏保了。 我碰到的就是这种情况。

另外一些情况

如果上面的值设置为 0 了,还是不行的话,可以继续排查:

dumpsys power | grep -E "mWakefulness|Wake Locks|SCREEN_BRIGHT|FULL_WAKE|WindowManager"

看Wake Locks size是不是 0:

YYT:/ #
YYT:/ # dumpsys power | grep -E "mWakefulness|Wake Locks|SCREEN_BRIGHT|FULL_WAKE|WindowManager"
  mWakefulness=Awake
  mWakefulnessChanging=false
  mScreenBrightnessOverrideFromWindowManager=NaN
  mUserActivityTimeoutOverrideFromWindowManager=-1
  mUserInactiveOverrideFromWindowManager=false
Wake Locks: size=0
  03-25 14:38:33.335 - 1000 - ACQ WindowManager/displayId:0 (screen-bright,on-after-release)
  03-25 14:38:35.528 - 1000 - REL WindowManager/displayId:0

UndimDetectorWakeLock

在Android T版本中,系统新增了SCREEN_BRIGHT_WAKE_LOCK(UndimDetectorWakeLock)机制。当设备处于低亮度(dim)状态时,用户两次打断屏幕熄灭操作就会触发系统保持屏幕常亮10分钟。

比如:

  • mKeepScreenOnEnabled = true
  • mKeepScreenOnForMillis = 10min
  • mUndimsRequired = 2
  • mMaxDurationBetweenUndimsMillis = 5min

那就等于:

  1. 屏幕先变暗一次。
  2. 把它点亮,记第 1 次 undim。
  3. 如果 5 分钟内又发生了第 2 次 undim,系统就判断“用户明显还在用”,于是额外保持亮屏 10 分钟
  4. 如果第 2 次发生在 5 分钟之后,那前面的计数作废,重新从 1 次开始算。

这时候 screen_off_timeout 就会变得不准确了,以 UndimDetectorWakeLock 计时为准。

调试命令

查看屏保是否启用:

settings get secure screensaver_enabled

查看进入的屏保的时间:

settings get system screen_off_timeout

查看进入休眠的时间:

settings get secure sleep_timeout

sleep_timeout 通常应比 screen_off_timeout 更长,不然设备会直接休眠而不是进屏保。

dumpsys dreams

YYT:/ # dumpsys dreams
DREAM MANAGER (dumpsys dreams)
​
mCurrentDream=null
mForceAmbientDisplayEnabled=false
mDreamsOnlyEnabledForDockUser=false
mDreamsEnabledSetting=true
mDreamsActivatedOnDockByDefault=true
mDreamsActivatedOnChargeByDefault=true
mIsDocked=false
mIsCharging=true
mWhenToDream=3
mKeepDreamingWhenUnpluggingDefault=false
getDozeComponent()=null
​
Dreamland:
  mCurrentDream: null
  mSentStartBroadcast=false
YYT:/ # settings list secure | grep screensaver
screensaver_activate_on_dock=1
screensaver_activate_on_sleep=1
screensaver_components=com.media/com.media.ScreensaverService
screensaver_default_component=com.google.android.apps.tv.dreamx/.service.Backdrop
screensaver_enabled=1
YYT:/ #
YYT:/ #
YYT:/ # settings list system | grep screen
dim_screen=1
lockscreen_sounds_enabled=1
screen_brightness=102
screen_brightness_mode=0
screen_off_timeout=30000

参考

Android14 用户两次打断息屏操作后,屏幕将会在10分钟内无法熄灭并持续点亮(关闭Android13新增的dim功能) - 掘金

使屏幕保持开启状态 | Background work | Android Developers