关闭

常见的WindowManager问题分析

1284人阅读 评论(0) 收藏 举报
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退出调用WindowManagerServiceremoveWindowLocked

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

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

4、VSYNC到来,执行动画的相关操作,因为屏幕已经被冻结,所以正在退出Window不能执行动画操作直接返回,导致finishExit不能被执行,最终Window不会正常删除。执行copyAnimToLayoutParamsLockedmInnerFields.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);
    }


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:26594次
    • 积分:520
    • 等级:
    • 排名:千里之外
    • 原创:26篇
    • 转载:7篇
    • 译文:0篇
    • 评论:2条
    最新评论