常见的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中的转屏流程

我们知道Android中支持横屏和竖屏,用户可以选择锁定(rotation lock)也可以选择让传感器来自动转屏。而转屏时为了使用户体验更流畅,会对屏幕截屏,然后使用截屏的图来做转屏动画,直到转屏动...

Android中的转屏流程

http://blog.csdn.net/jinzhuojun/article/details/50085491 我们知道Android中支持横屏和竖屏,用户可以选择锁定(rotat...

[Android]浮层视频效果,在另外一个Window使用SurfaceView无法正常显示的问题排查与解决

视频浮层下使用SurfaceView遇到的问题和解决方案

Skia深入分析1——skia上下文

前言:         断断续续跟Android的skia库打了两年交道,如今交接掉了,便写写关于skia的一些知识,也算了结一段职业生涯。 找了找网上关于skia的文章,基本上都过时了,讲得也不怎么...

学习Mechanics of Datafile Restore Operations的注意点

学习Mechanics of Datafile Restore Operations的注意点When you issue a RESTORE command, RMAN directs a serve...

Android 自定义ImageView支持缩放,拖拽,方便复用

今天刚发了一篇关于ImageView的缩放和拖拽的博客,然后我想了下,将他自定义下,方便我们来复用这个imageView,效果我就不多说了,http://blog.csdn.net/xiaanming...

Android6.0 按键流程(二)KeyboardInputMapper扫描码转成键盘码

在上一篇博客中,我们详细分析了InputReader中读取设备事件,到processEventsLocked函数处理事件(包括设备事件,设备添加、删除等),再到ProcessEventsForDevi...

我的Android进阶之旅------>android Matrix图片随意的放大缩小,拖动

step1:新建一个项目DragAndZoom,并准备一张照片放在res/drawable-hdpi目录下,如下图所示:         step2: 设置应用的UI界面,在main.xml中设置:...

Android图片缩放总结及比较

在Android中对大图片进行缩放真的很不尽如人意,不知道是不是我的方法不对。下面我列出3种对图片缩放的方法,并给出相应速度。请高人指教。 第一种是BitmapFactory和BitmapFac...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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