窗口焦点丢失问题分析

从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
...​
虽然锁网层级<低电警告层级,但是堆栈中位置确到了低电之上,WMS寻找focus窗口的时候是按堆栈顺序查找,也就造成了最终focus在了锁网上,但低电警告显示在锁网之上


修改方案有两种:
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;
             }
         }


谢谢!

 

你可能感兴趣的:(android模块分析)