android 窗口焦点丢失,窗口焦点丢失问题分析

这篇博客深入解析了系统日志中关于Keyguard窗口管理的异常行为,重点讲述了低电量警告、锁网和壁纸窗口层级对焦点切换的影响。通过分析WindowManagerService中的代码,揭示了系统窗口堆栈调整的逻辑,以及如何通过修改代码避免焦点错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从slog中的systemlog可以看出如下信息:

01-01 08:29:03.732   633   936 I WindowManager: Relayout invis Window{42244420 u0 Keyguard}: mExiting=false

01-01 08:29:03.732   633  1011 D PowerManagerService: releaseWakeLockInternal: lock=1109498264 [NlpWakeLock], flags=0x0 pkg name:com.google.android.gms

01-01 08:29:03.732   633  1011 D PowerManagerService: updateSuspendBlockerLocked goto release:PowerManagerService.WakeLocks: ref count=1

01-01 08:29:03.732   633  1011 D PowerManagerService: Releasing suspend blocker "PowerManagerService.WakeLocks".

01-01 08:29:03.732   633   936 I WindowManager: Releasing surface in: Window{42244420 u0 Keyguard EXITING}

01-01 08:29:03.732   633   936 D WindowManager: Input focus has changed to null

01-01 08:29:03.752   633   644 D PowerManagerService: acquireWakeLockInternal: lock=1109498264, flags=0x1, tag="NlpWakeLock", ws=null, uid=10025, pid=968 pkg name:com.google.android.gms

01-01 08:29:03.752   633   644 D PowerManagerService: updateSuspendBlockerLocked goto acquire:PowerManagerService.WakeLocks: ref count=0

01-01 08:29:03.752   633   644 D PowerManagerService: Acquiring suspend blocker "PowerManagerService.WakeLocks".

01-01 08:29:03.762   633   648 I WindowManager: Focus moving from Window{42244420 u0 Keyguard EXITING} to null

01-01 08:29:03.762   633   648 I WindowManager: Losing focus: Window{42244420 u0 Keyguard EXITING}

01-01 08:29:03.792   633   648 D WindowManager: Input focus has changed to Window{42242428 u0 com.android.phone}

01-01 08:29:03.832   633   786 D PowerManagerService: acquireWakeLockInternal: lock=1110600800, flags=0x1, tag="UlrDispatchingService", ws=null, uid=10025, pid=968 pkg name:com.google.android.gms

可以使用针对一些系统窗口进行测试验证,

常见的系统窗口:

长按关机键出现的对话框

statusbar下拉框

低电警告

锁网

anr提示框

。。。

具体:

WindowManager.java中

public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;

。。。

public static final int LAST_SYSTEM_WINDOW      = 2999;

这之间的窗口类型全是系统窗口

原因已查明:

两个不同层级的系统级dialog开出顺序加上keyguard的特殊性导致了窗口focus错误

1.窗口堆栈初始状态:

...

keyguard

wallpaper

launcher

...

2.开出低电量后,由于低电警告层级>wallpaper,所以变化为:修改后与3一样

...

keyguard

low_battery

wallpaper

launcher

...

3.由于墙纸窗口的特殊性,总是显示在需要显示墙纸窗口(这里是keyguard)的下面,所以调整为:

...

keyguard

wallpaper

low_battery

launcher

...

4.开出锁网后,由于锁网窗口层级>wallpaper,所以 变化为:

...

keyguard

sim_lock

wallpaper

low_battery

launcher

...​

修改后:

keyguard

wallpaper

low_battery

sim_lock

launcher

5.墙纸窗口的特殊性,总是显示在需要显示墙纸窗口(这里是keyguard)的下面,所以调整为:

...

keyguard

wallpaper

sim_lock

low_battery

launcher

...​

虽然锁网层级

修改方案有两种:

1.锁网比低电后开出才有此问题,可以在锁网开出的时候发广播关闭低电警告(建议采用此规避方案,但是由于其他dialog也会出现该问题,故未采用该方案)

2.wms添加系统窗口修改,堆栈中碰到wallpaper窗口,直接pass,继续寻找,此方案修改方法如下:

diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService

index 6099cfa..eebe4b4 100755

--- a/services/java/com/android/server/wm/WindowManagerService.java

+++ b/services/java/com/android/server/wm/WindowManagerService.java

@@ -1075,6 +1075,9 @@ public class WindowManagerService extends IWindowManager.Stub

int i;

for (i = windows.size() - 1; i >= 0; i--) {

if (windows.get(i).mBaseLayer <= myLayer) {

+                if (windows.get(i).mIsWallpaper) {

+                    continue;

+                }

break;

}

}

谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值