安卓屏保调试2

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

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

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

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

stay_on_while_plugged_in

java 复制代码
/**
         * 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:

shell 复制代码
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

shell 复制代码
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
shell 复制代码
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

相关推荐
StackNoOverflow9 分钟前
MySQL Explain 返回列详解:从入门到实战,附 SQL 与避坑大全
android
CYRUS_STUDIO9 小时前
Frida 检测与对抗实战:进程、maps、线程、符号全特征清除
android·逆向
csj5010 小时前
安卓基础之《(28)—Service组件》
android
lhbian12 小时前
PHP、C++和C语言对比:哪个更适合你?
android·数据库·spring boot·mysql·kafka
catoop13 小时前
Android 最佳实践、分层架构与全流程解析(2025)
android
ZHANG13HAO13 小时前
Android 13 特权应用(Android Studio 开发)调用 AOSP 隐藏 API 完整教程
android·ide·android studio
田梓燊14 小时前
leetcode 142
android·java·leetcode
angerdream14 小时前
Android手把手编写儿童手机远程监控App之JAVA基础
android
菠萝地亚狂想曲14 小时前
Zephyr_01, environment
android·java·javascript
sTone8737515 小时前
跨端框架通信机制全解析:从 URL Schema 到 JSI 到 Platform Channel
android·前端