手机常亮屏不自动灭屏

一. 基础知识介绍

  1. WakeLock(休眠锁)

WakeLock用于保持设备的唤醒状态,有些情况下,即时用户不操作App,我们也需要保持屏幕处于唤醒状态,以保证用户体验,比如视频类APP和计步类APP,视频类APP需要屏幕一直保持常量,计步类APP要求熄屏后程序依然保持运行状态。

  1. WakeLock的多种类型:

PARTIAL_WAKE_LOCK:保持CPU正常运转,但屏幕和键盘灯都可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU正常运转,允许屏幕点亮但可能屏幕被置灰,键盘灯可能是关闭的。
SCREEN_BRIGHT_WAKE_LOCK:保持CPU正常运转,允许屏幕高亮显示,键盘灯可能是关闭的。
FULL_WAKE_LOCK:保持CPU正常运转,保持屏幕高亮显示,键盘灯也保持亮度。
ACQUIRE_CAUSES_WAKEUP:强制屏幕和键盘灯亮起,这种锁针对一些必须通知用户的操作。
ON_AFTER_RELEASE:当WakeLock被释放后,继续保持屏幕和键盘灯亮起一段时间。

二. 遇到不灭屏的解决方法

  1. 方法一

使用adb shell dumpsys >dumpsys.txt

或者在bugreport.zip

或者使用命令: adb shell dumpsys power > power_dump.txt

搜索关键字:Wake Locks: 查看对应的持有对象。

实例分析:

1. 案例一

复现场景:

settingssettings->display->screen timeout-设置15秒,15秒后手机不灭屏.(低概率)

(1) 查看dump power的信息:

Wake Locks: size=1 FULL_WAKE_LOCK 'TinnoFactory' ACQUIRE_CAUSES_WAKEUP ACQ=-55m1s400ms (uid=1000 pid=16340)

(2) 发现有持有'TinnoFactory' TAG的 wake lock (FULL_WAKE_LOCK)导致不能灭屏。

(3) 查看代码:

private static final String TAG = "TinnoFactory";

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Log.i(TAG, "<TinnoFactoryActivity> onCreate");

PowerManager pm =(PowerManager) getSystemService(POWER_SERVICE);

wakeLock= pm.newWakeLock(PowerManager.FULL_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);

wakeLock.acquire();

@Override

public void onDestroy() {

Log.d(TAG, "<TinnoFactoryActivity> onDestroy");

// Log.i(TAG, "onDestroy, reset previousMobileDataState");

// setMobileDataState(mPreviousMobileDataState);

// Log.i(TAG, "setMobileData, getMobileDataState = " + getMobileDataState());

if (wakeLock != null) {wakeLock.release();}

super.onDestroy();

}

(4) 这个应用退出来就可以恢复。

2. 案例二

复现场景:

将timeout 时间设置为15秒。在打电话界面停留超过15秒,手机不灭屏。

(1) 查看dump power的信息:

SCREEN_BRIGHT_WAKE_LOCK 'WindowManager ' ON_AFTER_RELEASE ACQ=-1m56s271ms (uid=1000 pid=1344 ws=WorkSource{10172})

(2) 发现有持有'WindowManager ' TAG,是来自uid: 10172, 通过日志发现10172是dialer应用。

(3) 分析'WindowManager' TAG,怎么持有wake lock。

使用倒序的方法找:

  1. TAG 定义:

TAG_WM 定义:

frameworks/base/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java

public class WindowManagerDebugConfig {

...

static final String TAG_WM = "WindowManager";

..

  1. 调用newWakeLock SCREEN_BRIGHT_WAKE_LOCK的地方:

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

private WindowManagerService(Context context, InputManagerService inputManager,

boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,

ActivityTaskManagerService atm, DisplayWindowSettingsProvider

displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,

Supplier<Surface> surfaceFactory,

Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {

...

mHoldingScreenWakeLock = mPowerManager.newWakeLock(

PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);

...

}

3)谁在使用mHoldingScreenWakeLock.

只要newHoldScreen不为null,若调用setHoldScreenLocked,则就会调用acquire函数.

void setHoldScreenLocked(final Session newHoldScreen) {

final boolean hold = newHoldScreen != null;

...

if (hold != state) {

if (hold) {

mHoldingScreenWakeLock.acquire();

mPolicy.keepScreenOnStartedLw();

}

..

  1. 接下来寻找是调用setHoldScreenLocked 函数

发现只有一处,是在RootWindowContainer.java 中。

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

// "Something has changed! Let's make it correct now."

// TODO: Super long method that should be broken down...

void performSurfacePlacementNoTrace() {

...

mWmService.setHoldScreenLocked(mHoldScreen);

..

  1. 查看是谁给mHoldScreen赋值。

也是只有一处,当设置flag是FLAG_KEEP_SCREEN_ON。

android/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

/**

* @param w WindowState this method is applied to.

* @param obscured True if there is a window on top of this obscuring the display.

* @param syswin System window?

* @return True when the display contains content to show the user. When false, the display

* manager may choose to mirror or blank the display.

*/

boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {

if (w.mHasSurface && canBeSeen) {

if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {

mHoldScreen = w.mSession;

mHoldScreenWindow = w;

}

(4) 在dialer 中查看是谁使用了FLAG_KEEP_SCREEN_ON 。

果真有有相应的代码,进行debug调试既可.

vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/InCallPresenter.java

private void applyScreenTimeout() {

if (screenTimeoutEnabled) {

window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

} else {

window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

}

}

相关推荐
weixin_403810136 小时前
AI智能体写安卓自动化脚本教程:Cursor/Trae+CLI 实战,自然语言生成代码
android·人工智能·自动化·跨境电商·安卓自动化脚本·多账户运营
呆呆小孩8 小时前
零基础学 MySQL(上):从建库建表到增删改查,一篇搭好 SQL 基础
android·sql·mysql
catchadmin8 小时前
NativePHP v4 让 Blade 构建原生 iOS 与 Android 界面
android·ios·ai·php
FfHUCisI10 小时前
Golang 数据库连接池深度调优
android·数据库·golang
古法安卓12 小时前
Android-epoll原理详解
android·java·android studio
字节暗面14 小时前
四款 APP 加固强度测评:让 AI 拆了四个包,结果有点出乎意料
android·逆向工程·加固
网安蟹佬霸15 小时前
蓝队防御实战:SIEM与SOAR构建安全运营中心(万字详解+实战配置)
android·安全·web安全·网络安全·网安
敢敢のwings16 小时前
世界模型与FlashWorld:从“在梦中学习“到秒级3D场景生成
android·学习·3d
Dovis(誓平步青云)17 小时前
牛奶不能减成负数:冰箱库存的筛选、去重与不可变更新
android·java·开发语言
Awna17 小时前
MySQL 存储空间与索引运维实战:从空间排查到在线扩容
android·运维·mysql