常见的WindowManager问题分析

原创 2016年06月01日 15:47:59
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);
    }


版权声明:本文为博主原创文章,未经博主允许不得转载。

android binder解析

android binder解析   2013-04-20 09:27:48|  分类: android |  标签:binder  ipc  surfaceflinger  anr   |...
  • iefswang
  • iefswang
  • 2014年08月20日 16:40
  • 1900

Android6.0 WMS(十一) WMS窗口动画生成及播放

上一篇我们我们分析到有VSync信号过来,最后会调用WindowAnimator的animateLocked函数来生成和播放动画,这篇我们我们主要从这个函数开始分析。 animateLocked函数...
  • kc58236582
  • kc58236582
  • 2017年01月12日 15:13
  • 1273

Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(二)WMS的relayoutWindow

既上一篇博客,这篇我们分析WMS的relayoutWindow函数。 relayoutWindow 我们先看下relayoutWindow函数 public int relayoutWindo...
  • kc58236582
  • kc58236582
  • 2016年12月21日 16:41
  • 2889

Android 深入了解Surface

Activity是如何显示的   最初的想法就是,Activity获得一块显存,然后在上面绘图,最后交给设备去显示.这个道理是没错,但是Android的 SurfaceFlinger是在Syst...
  • qjbagu
  • qjbagu
  • 2012年04月05日 11:37
  • 487

android Surface 那点事儿

首先我们要说一下Surface是什么?关于Surface的描述是这样的“Handle onto a raw buffer that is being managed by the screen com...
  • zhiyuan263287
  • zhiyuan263287
  • 2014年02月17日 15:30
  • 1879

Android 7.0 start home activity and send boot completed broadcast

Boot completed broadcast sending flow. In frameworks/base/services/core/java/com/android/server/wm/...
  • petib_wangwei
  • petib_wangwei
  • 2017年04月21日 15:58
  • 1254

Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析

在Android系统中,Activity组件在启动之后,并且在它的窗口显示出来之前,可以显示一个启动窗口。这个启动窗口可以看作是Activity组件的预览窗口,是由WindowManagerServi...
  • Luoshengyang
  • Luoshengyang
  • 2013年02月18日 00:56
  • 48769

常见的WindowManager问题分析

1.UI hang and adb is still alive when running LGE compliant monkey test with DUT for 771 Minutes Win...
  • DaHeMaDeGeGe
  • DaHeMaDeGeGe
  • 2016年06月01日 15:47
  • 1932

Android 7.1 GUI系统-窗口管理WMS-Surface管理(四)

Surface的管理 Surface是窗口能真正显示到物理屏幕上的基础,由surfaceflinger管理,可以通过WindowStateAnimator.java中的变量mDrawState来查看...
  • lin20044140410
  • lin20044140410
  • 2017年12月13日 23:27
  • 759

C++常见问题与分析

1.求下面函数的返回值(微软) int func(x) { int countx = 0; while(x) { countx ++; x = x&(x-1); } return c...
  • wjeson
  • wjeson
  • 2013年12月03日 13:39
  • 1371
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:常见的WindowManager问题分析
举报原因:
原因补充:

(最多只允许输入30个字)