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);
}