Performed 6 layouts in a row. Skipping

調用流程如下:
 /frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
performSurfacePlacement -> performSurfacePlacementLoop -> isLayoutNeeded -> requestTraversal -> mAnimationHandler.post(runnable) -> 持wms鎖 -> performSurfacePlacement() ->

如果一個window連續layout的次數超過6,打印log :WindowManager: Performed 6 layouts in a row. Skipping

/////////////
WindowSurfacePlacer{
         mPerformSurfacePlacement = () -> {
             synchronized (mService.mWindowMap) {
                  performSurfacePlacement();
             }
          };
}

--->performSurfacePlacement-->
{

         int loopCount = 6;
          do {
              mTraversalScheduled = false;
              performSurfacePlacementLoop();
              mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
              loopCount--;
          } while (mTraversalScheduled && loopCount > 0);

}
--->performSurfacePlacementLoop-->
{
mService.mRoot.performSurfacePlacement(recoveringMemory);//處理relayout的核心方法
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
1.           if (mService.mRoot.isLayoutNeeded()) {
                  if (++mLayoutRepeatCount < 6) {
2.                      requestTraversal();
                  } else {
                      Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
                      mLayoutRepeatCount = 0;
                  }
              } else {
                  mLayoutRepeatCount = 0;
              }

 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}

1.--->RootWindowContainer-->isLayoutNeeded{
         final int numDisplays = mChildren.size();
          for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
              final DisplayContent displayContent = mChildren.get(displayNdx);
3.              if (displayContent.isLayoutNeeded()) {
                  return true;
              }
          }
          return false;
      }
}
///
2-->requestTraversal
    void requestTraversal() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mService.mAnimationHandler.post(mPerformSurfacePlacement);
        }
    }
    private final Runnable mPerformSurfacePlacement;

    public WindowSurfacePlacer(WindowManagerService service) {
        mService = service;
        mPerformSurfacePlacement = () -> {
            synchronized (mService.mGlobalLock) {
                performSurfacePlacement();///循環操作
            }
        };
    }
///
3--->DisplayContent.isLayoutNeeded.mLayoutNeeded

DisplayContent.setLayoutNeeded{
 mLayoutNeeded = true;
}
/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
performSurfacePlacement-->performSurfacePlacementNoTrace{
.....
581          if (mWmService.mFocusMayChange) {
582              mWmService.mFocusMayChange = false;
583              mWmService.updateFocusedWindowLocked(
584                      UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
585          }
....
....
605          if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
606                  ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
607          Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
//openTransaction和closeTransaction之間是對surface進行操作,建立和SurfaceFlinger通信,
//如setSize,setLayer,setPosition等都不是及時生效的,而是要等到業務關閉之後才統一通知
//SurfaceFlinger,可以避免屬性過快帶來的畫面不穩定
608          mWmService.openSurfaceTransaction();
609          try {
//計算窗口大小及完成窗口動畫
610              applySurfaceChangesTransaction(recoveringMemory);
611          } catch (RuntimeException e) {
612              Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
613          } finally {
614              mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
615              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
616              if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
617                      "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
618          }
619          mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();

....
654          handleResizingWindows();


}
RootWindowContainer.applySurfaceChangesTransaction--->
  private void applySurfaceChangesTransaction(boolean recoveringMemory) {

....
//遍歷mChildren
830          final int count = mChildren.size();
831          for (int j = 0; j < count; ++j) {
832              final DisplayContent dc = mChildren.get(j);
833              dc.applySurfaceChangesTransaction(recoveringMemory);
834          }
835  
836          // Give the display manager a chance to adjust properties like display rotation if it needs
837          // to.
838          mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
839          SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
....

  }
////
/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

3715      // TODO: Super crazy long method that should be broken down...
3716      void applySurfaceChangesTransaction(boolean recoveringMemory) {

3721          int repeats = 0;
3722          do {
3723              repeats++;
3724              if (repeats > 6) {
3725                  Slog.w(TAG, "Animation repeat aborted after too many iterations");
3726                  clearLayoutNeeded();
3727                  break;
3728              }

3730              if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
3731                      pendingLayoutChanges);
....
....
///
3733              if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
3734                  mWallpaperController.adjustWallpaperWindows();
3735              }
3736  
3737              if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
3738                  if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
3739                  if (updateOrientationFromAppTokens()) {
3740                      setLayoutNeeded();
3741                      sendNewConfiguration();
3742                  }
3743              }
3744  
3745              if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
3746                  setLayoutNeeded();
3747              }
3749              // FIRST LOOP: Perform a layout, if needed.
3750              if (repeats < LAYOUT_REPEAT_THRESHOLD) {
3751                  performLayout(repeats == 1, false /* updateInputWindows */);
3752              } else {
3753                  Slog.w(TAG, "Layout repeat skipped after too many iterations");
3754              }
3755  
3756              // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
3757              pendingLayoutChanges = 0;
//pendingLayoutChanges賦值,判斷是否需要下一次計算
3759              Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
3760              try {
3761                  mDisplayPolicy.beginPostLayoutPolicyLw();
3762                  forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
3763                  pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
3764              } finally {
3765                  Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3766              }
///
....

3767              if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
3768                      "after finishPostLayoutPolicyLw", pendingLayoutChanges);
3769                  mInsetsStateController.onPostLayout();
3770          } while (pendingLayoutChanges != 0);
.....
.....
          Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
          try {
//調用 winAnimator.computeShownFrameLocked(); 計算動畫變換矩陣 包括轉屏,平移等動畫
             forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
          } finally {
              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
          }
......
}
基於pendingLayoutChanges 這個值是否跳出循環,關注pendingLayoutChanges的賦值
////frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java    
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
        final boolean obscuredChanged = w.mObscured !=
                mTmpApplySurfaceChangesTransactionState.obscured;
        final RootWindowContainer root = mWmService.mRoot;
....

        // Moved from updateWindowsAndWallpaperLocked().
        if (w.mHasSurface) {
        ///commitFinishDrawingLocked中設置window轉檯爲READY_TO_SHOW,
        //其方法中的方法中調用WindowState.performShowLocked更新窗口繪製狀態 爲HAS_DRAWN
            // Take care of the window being ready to display.
            final boolean committed = winAnimator.commitFinishDrawingLocked();
.......

        }
....
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章