您的位置:首页 > 其它

常见的WindowManager问题分析

2016-06-01 15:47 405 查看
1.UI hang and adb is still alive when running LGE compliant monkey test with DUT for 771 Minutes
WindowManagerService主要修改点是在performLayoutAndPlacesurfaceLockedInner(主要用于系统UI刷新)这个方法
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ec566bc..0cc29f6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -10195,7 +10195,12 @@
// Don't remove this window until rotation has completed.
continue;
}
-            win.reportResized();
+            if (!win.reportResized()) {
+                mInnerFields.mOrientationChangeComplete = true;
+                if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
+                    "win: " + win + " Resize have exception, set orientationChangeComplete to "
+                    + mInnerFields.mOrientationChangeComplete);
+            }
mResizingWindows.remove(i);
}

diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c2548de..5dd05c5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1484,7 +1484,7 @@
}
}

-    void reportResized() {
+    boolean reportResized() {
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
@@ -1540,8 +1540,21 @@
mStableInsetsChanged = false;
mOutsetsChanged = false;
mWinAnimator.mSurfaceResized = false;
+            return true;
} catch (RemoteException e) {
mOrientationChanging = false;
+            if (DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) {
+                Slog.i(TAG, "Fail to resize window " + this + ": " + e);
+            }
+            mOverscanInsetsChanged = false;
+            mContentInsetsChanged = false;
+            mVisibleInsetsChanged = false;
+            mStableInsetsChanged = false;
+            mWinAnimator.mSurfaceResized = false;
+            mLastOverscanInsets.set(mOverscanInsets);
+            mLastContentInsets.set(mContentInsets);
+            mLastVisibleInsets.set(mVisibleInsets);
+            mLastStableInsets.set(mStableInsets);
mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
// We are assuming the hosting process is dead or in a zombie state.
@@ -1549,6 +1562,7 @@
+ ", removing this window.");
mService.mPendingRemove.add(this);
mService.requestTraversalLocked();
+            return false;
}
}


死循环在哪里?

1、Window退出调用WindowManagerService的removeWindowLocked

2、removeWindowLocked会执行退场动画,并调用performLayoutAndPlaceSurfacesLocked进行一次计算和状态处理,并将动画进行调度处理,放入下一个VSYNC的处理列表中,因为动画还没有被执行处理所以mInnerFields.mOrientationChangeComplete不为true,因此mWindowsFreezingScreen也不会被置为false,屏幕和输入不会被解冻和恢复。

3、ActivityManagerService接收到app
died的通知之后resume下一个app,下一个app与当前结束的这个app的orientation不一样,触发冻结屏幕和输入。

4、VSYNC到来,执行动画的相关操作,因为屏幕已经被冻结,所以正在退出的Window不能执行动画操作而直接返回,导致finishExit不能被执行,最终Window不会被正常删除。执行copyAnimToLayoutParamsLocked将mInnerFields.mOrientationChangeComplete置为true,然后调用requestTraversalLocked发送执行下一次performLayoutAndPlaceSurfacesLocked的消息到消息队列中。

5、performLayoutAndPlaceSurfacesLocked执行,调用updateResizingWindows。因为退出的Window没有被finishExit,并且执行reportResized更新窗口大小和内容状态的过程中由于Window已经退出,所以调用mClient.resized执行IPC(跨进程调用)时发生RemoteException,导致关键状态值没有被置位清空,所以执行updateResizingWindows的过程中会因为Window的状态一直满足条件而调用makeWindowFreezingScreenIfNeededLocked,因为此时窗口已经被冻结,所以会将mInnerFields.mOrientationChangeComplete一直置为false,因此不会将mWindowsFreezingScreen置为false和调用stopFreezingDisplayLocked解冻屏幕和恢复输入。接着会调用scheduleAnimationLocked将下一次动画调度到VSYNC的列表中。

6、下一次VSYNC到来,重复第四步和第五步构成不能解冻屏幕和恢复输入的死循环

2.Update window surface while live wallpaper is changed.

Other than surface resized or surface moved, setSurfaceBoundariesLocked inWindowStateAnimator.java may encounter another scenario that the live wallpaperis changed. In all of scenarios, updateSurfaceWindowCrop(...) should be calledseparately to avoid float
window flickering when it's dragged off screen.

void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
...
if ((w.mAttrs.flags & LayoutParams.FLAG_FULLSCREEN) != 0
+              || w.mAttrs.type == LayoutParams.TYPE_WALLPAPER) {
updateSurfaceWindowCrop(recoveringMemory);
}
}


问题:窗口边缘切换的时候出现闪烁

思路:

When the window move to the edge of screen, first call setWindowCrop,

 if the position of window is changed, second call setPosition. setWindowCrop will let surfaceflinger dispaly the window,

 but the lefttop position is the last postion, this will lead the rightbottom position reduced,

 and the reduced rect is dispaly the second layer's window,

 so the window flicking. setPosition let surfaceflinger dispaly the window second, and this time is right rect.

路径:

        services/core/java/com/android/server/wm/WindowStateAnimator.java

        

     

void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
final WindowState w = mWin;

int width;
int height;
if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
// for a scaled surface, we always want the requested
// size.
width  = w.mRequestedWidth;
height = w.mRequestedHeight;
} else {
width = w.mCompatFrame.width();
height = w.mCompatFrame.height();
}

// Something is wrong and SurfaceFlinger will not like this,
// try to revert to sane values
if (width < 1) {
width = 1;
}
if (height < 1) {
height = 1;
}

float left = w.mShownFrame.left;
float top = w.mShownFrame.top;

// Adjust for surface insets.
final LayoutParams attrs = w.getAttrs();
width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
left -= attrs.surfaceInsets.left;
top -= attrs.surfaceInsets.top;

final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
if (surfaceMoved) {
mSurfaceX = left;
mSurfaceY = top;

try {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"POS " + left + ", " + top, null);
mSurfaceControl.setPosition(left, top);
+      updateSurfaceWindowCrop(recoveringMemory);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + w
+ " pos=(" + left + "," + top + ")", e);
if (!recoveringMemory) {
mService.reclaimSomeSurfaceMemoryLocked(this, "position", true);
}
}
}

final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
if (surfaceResized) {
mSurfaceW = width;
mSurfaceH = height;
mSurfaceResized = true;

try {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"SIZE " + width + "x" + height, null);
mSurfaceControl.setSize(width, height);
+    updateSurfaceWindowCrop(recoveringMemory);
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
final TaskStack stack = w.getStack();
if (stack != null) {
stack.startDimmingIfNeeded(this);
}
}
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
// entire system.
Slog.e(TAG, "Error resizing surface of " + w
+ " size=(" + width + "x" + height + ")", e);
if (!recoveringMemory) {
mService.reclaimSomeSurfaceMemoryLocked(this, "size", true);
}
}
}
-         updateSurfaceWindowCrop(recoveringMemory);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: