Android亮屏流程之窗口繪制

一、亮屏流程

點(diǎn)亮屏幕會(huì)調(diào)用PowerManagerService關(guān)鍵方法updatePowerStateLocked
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

     protected void updatePowerStateLocked() {
         if (!mSystemReady || mDirty == 0) {
             return;
         }
         if (!Thread.holdsLock(mLock)) {
             Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
         try {
             // Phase 0: Basic state updates.
             updateIsPoweredLocked(mDirty);
             updateStayOnLocked(mDirty);
             updateScreenBrightnessBoostLocked(mDirty);
 
             // Phase 1: Update wakefulness.
             // Loop because the wake lock and user activity computations are influenced
             // by changes in wakefulness.
             final long now = SystemClock.uptimeMillis();
             int dirtyPhase2 = 0;
             for (;;) {
                 int dirtyPhase1 = mDirty;
                 dirtyPhase2 |= dirtyPhase1;
                 mDirty = 0;
 
                 updateWakeLockSummaryLocked(dirtyPhase1);
                 updateUserActivitySummaryLocked(now, dirtyPhase1);
                 if (!updateWakefulnessLocked(dirtyPhase1)) {
                     break;
                 }
             }
 
             // Phase 2: Update display power state.
             boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
 
             // Phase 3: Update dream state (depends on display ready signal).
             updateDreamLocked(dirtyPhase2, displayBecameReady);
 
             // Phase 4: Send notifications, if needed.
             finishWakefulnessChangeIfNeededLocked();
 
             // Phase 5: Update suspend blocker.
             // Because we might release the last suspend blocker here, we need to make sure
             // we finished everything else first!
             updateSuspendBlockerLocked();
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
     }

其中調(diào)用updateDisplayPowerStateLocked->DisplayPowerController.requestPowerState->sendUpdatePowerStateLocked->updatePowerState->animateScreenStateChange->setScreenState->blockScreenOn()

frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

   private boolean setScreenState(int state, boolean reportOnly) {
       ... ...
       if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
           setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
           if (mPowerState.getColorFadeLevel() == 0.0f) {
               blockScreenOn();
           } else {
               unblockScreenOn();
           }
           mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
       }

       // Return true if the screen isn't blocked.
       return mPendingScreenOnUnblocker == null;
   }

blockScreenOn中對(duì)mPendingScreenOnUnblocker賦值,并記錄時(shí)間用于打印log,

    private void blockScreenOn() {
        if (mPendingScreenOnUnblocker == null) {
            //asyncTrace可以不在一個(gè)方法里
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
            //創(chuàng)建ScreenOnUnblocker對(duì)象等待窗口繪制玩回調(diào)
            mPendingScreenOnUnblocker = new ScreenOnUnblocker();
            mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
            Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
        }
    }

接下來看mWindowManagerPolicy.screenTurningOn,這里開始繪制鎖屏和其他窗口仪吧,分別調(diào)用PhoneWindowManager 的finishKeyguardDrawn->mWindowManagerInternal.waitForAllWindowsDrawn->mWindowManagerDrawCallback.run->finishWindowsDrawn->finishScreenTurningOn薛闪,在這里回調(diào)blockScreenOn中創(chuàng)建的mPendingScreenOnUnblocker.onScreenOn方法

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    @Override
    public void screenTurningOn(final ScreenOnListener screenOnListener) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");

        updateScreenOffSleepToken(false);
        synchronized (mLock) {
            mScreenOnEarly = true;
            mScreenOnFully = false;
            mKeyguardDrawComplete = false;
            mWindowManagerDrawComplete = false;
            mScreenOnListener = screenOnListener;

            if (mKeyguardDelegate != null) {
                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
                        getKeyguardDrawnTimeout());
                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
            } else {
                if (DEBUG_WAKEUP) Slog.d(TAG,
                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
                finishKeyguardDrawn();
            }
        }
    }

frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

   private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
       @Override
       public void onScreenOn() {
           Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
           msg.setAsynchronous(true);
           mHandler.sendMessage(msg);
       }
   }
   private final class DisplayControllerHandler extends Handler {
       public DisplayControllerHandler(Looper looper) {
           super(looper, null, true /*async*/);
       }

       @Override
       public void handleMessage(Message msg) {
               ... ...

               case MSG_SCREEN_ON_UNBLOCKED:
                   if (mPendingScreenOnUnblocker == msg.obj) {
                       unblockScreenOn();
                       updatePowerState();
                   }
                   break;
           }
       }
   }

收到窗口繪制完成回調(diào)后將mPendingScreenOnUnblocker賦空

    private void unblockScreenOn() {
        if (mPendingScreenOnUnblocker != null) {
            mPendingScreenOnUnblocker = null;
            long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
            Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
            Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
        }
    }

然后再次調(diào)用updatePowerState 坏快,此時(shí)mPendingScreenOnUnblocker == null,因此調(diào)用mWindowManagerPolicy.screenTurnedOn通知PhoneWindowManager 屏幕已點(diǎn)亮

private void updatePowerState() {
    ... ...
        // Determine whether the display is ready for use in the newly requested state.
        // Note that we do not wait for the brightness ramp animation to complete before
        // reporting the display is ready because we only need to ensure the screen is in the
        // right power state even as it continues to converge on the desired brightness.
        final boolean ready = mPendingScreenOnUnblocker == null &&
                (!mColorFadeEnabled ||
                        (!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
                && mPowerState.waitUntilClean(mCleanListener);
        final boolean finished = ready
                && !mScreenBrightnessRampAnimator.isAnimating();
            // Notify policy about screen turned on.
        if (ready && state != Display.STATE_OFF
                && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
            setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
            mWindowManagerPolicy.screenTurnedOn();
        }
}

    private void setReportedScreenState(int state) {
        Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
        mReportedScreenStateToPolicy = state;
    }

updatePowerState后面有調(diào)用setScreenState

   private boolean setScreenState(int state, boolean reportOnly) {
       final boolean isOff = (state == Display.STATE_OFF);
       if (mPowerState.getScreenState() != state) {

           ... ...

           if (!reportOnly) {
               mPowerState.setScreenState(state);
               // Tell battery stats about the transition.
               try {
                   mBatteryStats.noteScreenState(state);
               } catch (RemoteException ex) {
                   // same process
               }
           }
       }
   }

DisplayPowerState.setScreenState->scheduleScreenUpdate 最終通知底層(LocalDisplayAdapter,SurfaceControl,HWComposer)真正的點(diǎn)亮屏幕

二黍瞧、繪制鎖屏和窗口

上面DisplayPowerController.setScreenState方法中首先blockScreenOn,然后開始繪制窗口原杂,等待回調(diào)

frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

   private boolean setScreenState(int state, boolean reportOnly) {
       ... ...
       if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
           setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
           if (mPowerState.getColorFadeLevel() == 0.0f) {
               blockScreenOn();
           } else {
               unblockScreenOn();
           }
           mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
       }

       // Return true if the screen isn't blocked.
       return mPendingScreenOnUnblocker == null;
   }

/MP02/AMSS/LINUX/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

      // Called on the DisplayManager's DisplayPowerController thread.
      @Override
      public void screenTurningOn(final ScreenOnListener screenOnListener) {
          if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
  
          updateScreenOffSleepToken(false);
          synchronized (mLock) {
              mScreenOnEarly = true;
              mScreenOnFully = false;
              mKeyguardDrawComplete = false;
              mWindowManagerDrawComplete = false;
              mScreenOnListener = screenOnListener;
  
              if (mKeyguardDelegate != null) {
                  mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                  mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
                          getKeyguardDrawnTimeout());
                  mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
              } else {
                  if (DEBUG_WAKEUP) Slog.d(TAG,
                          "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
                  finishKeyguardDrawn();
              }
          }
      }
      //繪制結(jié)束后回調(diào)
    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
          @Override
          public void onDrawn() {
              if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
              mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
          }
      };

開始繪制鎖屏

MP02/AMSS/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

      public void onScreenTurnedOn() {
          Trace.beginSection("KeyguardViewMediator#onScreenTurnedOn");
          notifyScreenTurnedOn();
          mUpdateMonitor.dispatchScreenTurnedOn();
          Trace.endSection();
      }
      
      private void handleNotifyScreenTurnedOn() {
          Trace.beginSection("KeyguardViewMediator#handleNotifyScreenTurnedOn");
          if (LatencyTracker.isEnabled(mContext)) {
              LatencyTracker.getInstance(mContext).onActionEnd(LatencyTracker.ACTION_TURN_ON_SCREEN);
          }
          synchronized (this) {
              if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOn");
              mStatusBarKeyguardViewManager.onScreenTurnedOn();
          }
          Trace.endSection();
      }

繪制結(jié)束后調(diào)用finishKeyguardDrawn

/MP02/AMSS/LINUX/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

      private void finishKeyguardDrawn() {
          synchronized (mLock) {
              if (!mScreenOnEarly || mKeyguardDrawComplete) {
                  return; // We are not awake yet or we have already informed of this event.
              }
  
              mKeyguardDrawComplete = true;
              if (mKeyguardDelegate != null) {
                  mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
              }
              mWindowManagerDrawComplete = false;
          }
  
          // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
          // as well as enabling the orientation change logic/sensor.
          mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
                  WAITING_FOR_DRAWN_TIMEOUT);
      }

開始繪制其他可見窗口
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

          @Override
          public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
              boolean allWindowsDrawn = false;
              synchronized (mWindowMap) {
                  mWaitingForDrawnCallback = callback;
                  getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
                  mWindowPlacerLocked.requestTraversal();
                  mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
                  if (mWaitingForDrawn.isEmpty()) {
                      allWindowsDrawn = true;
                  } else {
                      mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
                      checkDrawnWindowsLocked();
                  }
              }
              if (allWindowsDrawn) {
                  callback.run();
              }
          }

所以繪制鎖屏和其他可見窗口的時(shí)間會(huì)影響亮屏速度印颤,繼續(xù)往下看

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

      void waitForAllWindowsDrawn() {
          final WindowManagerPolicy policy = mService.mPolicy;
          forAllWindows(w -> {
              final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
              if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
                  w.mWinAnimator.mDrawState = DRAW_PENDING;
                  // Force add to mResizingWindows.
                  w.mLastContentInsets.set(-1, -1, -1, -1);
                  mService.mWaitingForDrawn.add(w);
              }
          }, true /* traverseTopToBottom */);
      }
  1. waitForAllWindowsDrawn 設(shè)置窗口繪制狀態(tài),將需要繪制的窗口放入mWaitingForDrawn穿肄,
  2. mWindowPlacerLocked.requestTraversal 繪制窗口
    WindowSurfacePlacer的requestTraversal方法只是向AnimationThread 線程post了一個(gè)mPerformSurfacePlacement Runnable年局,mAnimationHandler收到這個(gè)消息后,performSurfacePlacement()方法就會(huì)執(zhí)行,接著調(diào)用 performSurfacePlacementLoop->RootWindowContainer.performSurfacePlacement,
    AnimationThread 繼承 HandlerThread 一個(gè)帶Looper 的Thread

frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java

     void requestTraversal() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
             mService.mAnimationHandler.post(mPerformSurfacePlacement);
         }
     }
     public WindowSurfacePlacer(WindowManagerService service) {
         mService = service;
         mWallpaperControllerLocked = mService.mRoot.mWallpaperController;
         mPerformSurfacePlacement = () -> {
             synchronized (mService.mWindowMap) {
                 performSurfacePlacement();
             }
         };
     }

所以performSurfacePlacement 也是在AnimationThread中執(zhí)行咸产,因此如果有耗時(shí)動(dòng)畫矢否,會(huì)影響performSurfacePlacement方法執(zhí)行,進(jìn)而影響commitFinishDrawingLocked調(diào)用脑溢,commitFinishDrawingLocked調(diào)用后才會(huì)點(diǎn)亮屏幕僵朗,因此如果出現(xiàn)亮屏慢的問題,也可以監(jiān)控AnimationThread中的Looper,看看改線程正在執(zhí)行什么消息

android/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

   //"Something has changed!  Let's make it correct now."
   // TODO: Super crazy long method that should be broken down...
   void performSurfacePlacement(boolean recoveringMemory) {
       if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
               + Debug.getCallers(3));
       ... ...
       //建立和SurfaceFlinger通信 ,openTransaction和closeTransaction之間是對(duì)surface進(jìn)行操作验庙,如setSize顶吮,setLayer,setPosition等都不是及時(shí)生效的粪薛,而是要等到業(yè)務(wù)關(guān)閉之后才統(tǒng)一通知SurfaceFlinger悴了,可以避免屬性過快帶來的畫面不穩(wěn)定
               ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
       mService.openSurfaceTransaction();
       try {
           applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
       } catch (RuntimeException e) {
           Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
       } finally {
           mService.closeSurfaceTransaction();
           if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                   "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
       }

       ... ...

       //開始動(dòng)畫發(fā)送choreography.postCallback
       mService.scheduleAnimationLocked();
       mService.mWindowPlacerLocked.destroyPendingSurfaces();

       if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
               "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
   }

applySurfaceChangesTransaction中計(jì)算窗口大小及完成窗口動(dòng)畫

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

   boolean applySurfaceChangesTransaction(boolean recoveringMemory) {

       final int dw = mDisplayInfo.logicalWidth;
       final int dh = mDisplayInfo.logicalHeight;
       final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;

       mTmpUpdateAllDrawn.clear();

       int repeats = 0;
       //最多循環(huán)6次,計(jì)算窗口大小
       do {
           repeats++;
           if (repeats > 6) {
               Slog.w(TAG, "Animation repeat aborted after too many iterations");
               clearLayoutNeeded();
               break;
           }
           ... ...

           if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
               setLayoutNeeded();
           }

           // FIRST LOOP: Perform a layout, if needed.
           //計(jì)算窗口重點(diǎn)在這里
           if (repeats < LAYOUT_REPEAT_THRESHOLD) {
               performLayout(repeats == 1, false /* updateInputWindows */);
           } else {
               Slog.w(TAG, "Layout repeat skipped after too many iterations");
           }

           // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
           pendingLayoutChanges = 0;
           //pendingLayoutChanges賦值违寿,判斷是否需要下一次計(jì)算
           if (isDefaultDisplay) {
               mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
               forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
               pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
               if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
                       "after finishPostLayoutPolicyLw", pendingLayoutChanges);
           }
       } while (pendingLayoutChanges != 0);

       mTmpApplySurfaceChangesTransactionState.reset();
       resetDimming();

       mTmpRecoveringMemory = recoveringMemory;
       //調(diào)用 winAnimator.computeShownFrameLocked(); 計(jì)算動(dòng)畫變換矩陣 包括轉(zhuǎn)屏湃交,平移等動(dòng)畫
       forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
       ... ...

       return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
   }

  1. 窗口大小計(jì)算
  void performLayout(boolean initial, boolean updateInputWindows) {
     ... ...

     // First perform layout of any root windows (not attached to another window).
     //mPerformLayout中調(diào)用mPolicy.layoutWindowLw()得到窗口布局的8個(gè)區(qū)域,而后WindowState.computeFrameLw()得到四個(gè)區(qū)域陨界,根據(jù)這四個(gè)區(qū)域再加上
     //LayoutParames和ViewRootImpl中的requestHeight巡揍,requestWidth得到最終的窗口大小保存到mFrame中
     forAllWindows(mPerformLayout, true /* traverseTopToBottom */);

     ... ...
 }
  1. 窗口繪制狀態(tài)更新
  private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
      ... ...

      final WindowStateAnimator winAnimator = w.mWinAnimator;

      //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
      w.mContentChanged = false;

      // Moved from updateWindowsAndWallpaperLocked().
      if (w.mHasSurface) {
          // Take care of the window being ready to display.
          // 窗口繪制完成,更新狀態(tài)
          final boolean committed = winAnimator.commitFinishDrawingLocked();
          ... ...       
          final TaskStack stack = w.getStack();
          if ((!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening())
                  || (stack != null && stack.isAnimatingBounds())) {
              //計(jì)算AppWindowAnimator菌瘪,ScreenRotationAnimation腮敌,WindowStateAnimatior加一起的變換矩陣
              winAnimator.computeShownFrameLocked();
          }
          winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
      }
      ... ...
  };

commitFinishDrawingLocked方法中調(diào)用WindowState.performShowLocked更新窗口繪制狀態(tài) 為HAS_DRAWN

繪制之后檢查窗口狀態(tài)checkDrawnWindowsLocked,已經(jīng)畫完的窗口,從mWaitingForDrawn中移除俏扩,如果mWaitingForDrawn為空糜工,則移除WAITING_FOR_DRAWN_TIMEOUT消息。

android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

      void checkDrawnWindowsLocked() {
          if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
              return;
          }
          for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
              WindowState win = mWaitingForDrawn.get(j);
              if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
                      ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
                      " mHasSurface=" + win.mHasSurface +
                      " drawState=" + win.mWinAnimator.mDrawState);
              if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
                  // Window has been removed or hidden; no draw will now happen, so stop waiting.
                  if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
                  mWaitingForDrawn.remove(win);
              } else if (win.hasDrawnLw()) {
                  // Window is now drawn (and shown).
                  if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
                  mWaitingForDrawn.remove(win);
              }
          }
          if (mWaitingForDrawn.isEmpty()) {
              if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
              mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
              mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
          }
      }

如果1s內(nèi)還沒有移除WAITING_FOR_DRAWN_TIMEOUT消息录淡,則打印timeout log捌木,不再等待窗口繪制,直接亮屏
android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

          case WAITING_FOR_DRAWN_TIMEOUT: {
              Runnable callback = null;
              synchronized (mWindowMap) {
                  Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
                  mWaitingForDrawn.clear();
                  callback = mWaitingForDrawnCallback;
                  mWaitingForDrawnCallback = null;
              }
              if (callback != null) {
                  callback.run();
              }
              break;
          }
  1. 觸發(fā)繪制動(dòng)畫
    frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
   void scheduleAnimationLocked() {
       mAnimator.scheduleAnimation();
   }

向Choreographer 發(fā)起繪制動(dòng)畫請(qǐng)求
frameworks/base/services/core/java/com/android/server/wm/

   void scheduleAnimation() {
       if (!mAnimationFrameCallbackScheduled) {
           mAnimationFrameCallbackScheduled = true;
           mChoreographer.postFrameCallback(mAnimationFrameCallback);
       }
   }

Callback mAnimationFrameCallback在AnimationThread線程執(zhí)行嫉戚,AnimationThread是一個(gè)HandlerThread,所有窗口動(dòng)畫在該線程中執(zhí)行
android/frameworks/base/services/core/java/com/android/server/wm/WindowAnimator.java

   WindowAnimator(final WindowManagerService service) {
       mService = service;
       mContext = service.mContext;
       mPolicy = service.mPolicy;
       mWindowPlacerLocked = service.mWindowPlacerLocked;
       //在AnimationThread中創(chuàng)建Choreographer對(duì)象刨裆,所以實(shí)在AnimationThread所在的線程執(zhí)行動(dòng)畫
       AnimationThread.getHandler().runWithScissors(
               () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);

        mAnimationFrameCallback = frameTimeNs -> {
            synchronized (mService.mWindowMap) {
                mAnimationFrameCallbackScheduled = false;
            }
            animate(frameTimeNs);
        };
    }

窗口動(dòng)畫分為:

  • AppWindowAnimator
    Activity進(jìn)入退出動(dòng)畫

  • ScreenRotationAnimation
    窗口旋轉(zhuǎn)動(dòng)畫

  • WindowStateAnimator
    普通窗口動(dòng)畫

    1. 負(fù)責(zé)合成 AppWindowAnimator,ScreenRotationAnimation彬檀,WindowStateAnimatior的變換矩陣
    2. 保存了窗口Surface屬性
  • DimAnimation

WindowAnimator單例帆啃,用于管理所有窗口動(dòng)畫

android/frameworks/base/services/core/java/com/android/server/wm/WindowAnimator.java

  private void animate(long frameTimeNs) {
    ... ... 

        synchronized (mService.mWindowMap) {
            mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
            mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
            mAnimating = false;
            mAppWindowAnimating = false;
            if (DEBUG_WINDOW_TRACE) {
                Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
            }

            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
            mService.openSurfaceTransaction();
            try {
                final AccessibilityController accessibilityController =
                        mService.mAccessibilityController;
                final int numDisplays = mDisplayContentsAnimators.size();
                for (int i = 0; i < numDisplays; i++) {
                    final int displayId = mDisplayContentsAnimators.keyAt(i);
                    final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
                    //1. Activity切換動(dòng)畫,AppWindowAnimator中專門執(zhí)行Activity動(dòng)畫
                    dc.stepAppWindowsAnimation(mCurrentTime);
                    DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
                    //2. 屏幕旋轉(zhuǎn)動(dòng)畫
                    final ScreenRotationAnimation screenRotationAnimation =
                            displayAnimator.mScreenRotationAnimation;
                    if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
                        if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
                            setAnimating(true);
                        } else {
                            mBulkUpdateParams |= SET_UPDATE_ROTATION;
                            screenRotationAnimation.kill();
                            displayAnimator.mScreenRotationAnimation = null;

                            //TODO (multidisplay): Accessibility supported only for the default
                            // display.
                            if (accessibilityController != null && dc.isDefaultDisplay) {
                                // We just finished rotation animation which means we did not
                                // announce the rotation and waited for it to end, announce now.
                                accessibilityController.onRotationChangedLocked(
                                        mService.getDefaultDisplayContentLocked());
                            }
                        }
                    }

                    // Update animations of all applications, including those
                    // associated with exiting/removed apps
                    ++mAnimTransactionSequence;
                    //3.  WindowStateAnimator.stepAnimationLocked更新普通窗口動(dòng)畫
                    dc.updateWindowsForAnimator(this);
                    //4. 壁紙動(dòng)畫
                    dc.updateWallpaperForAnimator(this);
                    //5. 將變換矩陣設(shè)置在Surface上
                    dc.prepareWindowSurfaces();
                }
                ... ...
                //是否申請(qǐng)繪制下一楨動(dòng)畫
                if (mService.mDragState != null) {
                    mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
                }
                ... ...
            } catch (RuntimeException e) {
                Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
            } finally {
                mService.closeSurfaceTransaction();
                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate");
            }
            //繼續(xù)繪制
            if (!mAnimating && mLastAnimating) {
                mWindowPlacerLocked.requestTraversal();
                mService.mTaskSnapshotController.setPersisterPaused(false);
                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
            }

             ... ...
        }
    }

animate方法主要調(diào)用了AppWindowAnimator,ScreenRotationAnimation窍帝,WindowStateAnimator的stepAnimationLocked方法努潘,stepAnimationLocked將狀態(tài)遷移到由時(shí)間戳currentTime所指定的一楨上。
下面以WindowStateAnimator的stepAnimationLocked方法為例

android/frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java

  //計(jì)算mTransformation
  private boolean stepAnimation(long currentTime) {
       if ((mAnimation == null) || !mLocalAnimating) {
           return false;
       }
       currentTime = getAnimationFrameTime(mAnimation, currentTime);
       mTransformation.clear();
       final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
       if (mAnimationStartDelayed && mAnimationIsEntrance) {
           mTransformation.setAlpha(0f);
       }
       if (false && DEBUG_ANIM) Slog.v(TAG, "Stepped animation in " + this + ": more=" + more
               + ", xform=" + mTransformation);
       return more;
   }

   // This must be called while inside a transaction.  Returns true if
   // there is more animation to run.
   boolean stepAnimationLocked(long currentTime) {
       // Save the animation state as it was before this step so WindowManagerService can tell if
       // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet().
       mWasAnimating = mAnimating;
       final DisplayContent displayContent = mWin.getDisplayContent();
       if (mWin.mToken.okToAnimate()) {
           // We will run animations as long as the display isn't frozen.

           if (mWin.isDrawnLw() && mAnimation != null) {
               mHasTransformation = true;
               mHasLocalTransformation = true;
               if (!mLocalAnimating) {
                   if (DEBUG_ANIM) Slog.v(
                       TAG, "Starting animation in " + this +
                       " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
                       " wh=" + mWin.mFrame.height() +
                       " dx=" + mAnimDx + " dy=" + mAnimDy +
                       " scale=" + mService.getWindowAnimationScaleLocked());
                   final DisplayInfo displayInfo = displayContent.getDisplayInfo();
                   if (mAnimateMove) {
                       mAnimateMove = false;
                       mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
                               mAnimDx, mAnimDy);
                   } else {
                       mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
                               displayInfo.appWidth, displayInfo.appHeight);
                   }
                   mAnimDx = displayInfo.appWidth;
                   mAnimDy = displayInfo.appHeight;
                   mAnimation.setStartTime(mAnimationStartTime != -1
                           ? mAnimationStartTime
                           : currentTime);
                   mLocalAnimating = true;
                   mAnimating = true;
               }
               if ((mAnimation != null) && mLocalAnimating) {
                   mLastAnimationTime = currentTime;
                   if (stepAnimation(currentTime)) {
                       return true;
                   }
               }

           }
           ... ...

       return false;
   }

來到animate方法的第五步開始在Surface上繪制

frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java

 void prepareSurfaceLocked(final boolean recoveringMemory) {
       ... ...
       //計(jì)算AppWindowAnimatior,ScreenRotaionAnimator,WindowStateAnimatior 的變換矩陣 Transformation
       computeShownFrameLocked();

       setSurfaceBoundariesLocked(recoveringMemory);

       if (mIsWallpaper && !mWin.mWallpaperVisible) {
           // Wallpaper is no longer visible and there is no wp target => hide it.
           hide("prepareSurfaceLocked");
       } else if (w.isParentWindowHidden() || !w.isOnScreen()) {
           hide("prepareSurfaceLocked");
           mWallpaperControllerLocked.hideWallpapers(w);

           // If we are waiting for this window to handle an orientation change. If this window is
           // really hidden (gone for layout), there is no point in still waiting for it.
           // Note that this does introduce a potential glitch if the window becomes unhidden
           // before it has drawn for the new orientation.
           if (w.getOrientationChanging() && w.isGoneForLayoutLw()) {
               w.setOrientationChanging(false);
               if (DEBUG_ORIENTATION) Slog.v(TAG,
                       "Orientation change skips hidden " + w);
           }
       } else if (mLastLayer != mAnimLayer
               || mLastAlpha != mShownAlpha
               || mLastDsDx != mDsDx
               || mLastDtDx != mDtDx
               || mLastDsDy != mDsDy
               || mLastDtDy != mDtDy
               || w.mLastHScale != w.mHScale
               || w.mLastVScale != w.mVScale
               || mLastHidden) {
           displayed = true;
           mLastAlpha = mShownAlpha;
           mLastLayer = mAnimLayer;
           mLastDsDx = mDsDx;
           mLastDtDx = mDtDx;
           mLastDsDy = mDsDy;
           mLastDtDy = mDtDy;
           w.mLastHScale = w.mHScale;
           w.mLastVScale = w.mVScale;
           if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
                   "controller=" + mSurfaceController +
                   "alpha=" + mShownAlpha + " layer=" + mAnimLayer
                   + " matrix=[" + mDsDx + "*" + w.mHScale
                   + "," + mDtDx + "*" + w.mVScale
                   + "][" + mDtDy + "*" + w.mHScale
                   + "," + mDsDy + "*" + w.mVScale + "]", false);
            //修改Surface的layer坤学、matrix疯坤、alpha等屬性,從而實(shí)現(xiàn)窗口動(dòng)畫的渲染
           boolean prepared =
               mSurfaceController.prepareToShowInTransaction(mShownAlpha,
                       mDsDx * w.mHScale * mExtraHScale,
                       mDtDx * w.mVScale * mExtraVScale,
                       mDtDy * w.mHScale * mExtraHScale,
                       mDsDy * w.mVScale * mExtraVScale,
                       recoveringMemory);
           mSurfaceController.setLayer(mAnimLayer);

           ... ...
   }

至此完成了一幀窗口動(dòng)畫的繪制

總結(jié)

  1. 屏幕點(diǎn)亮首先調(diào)用PowerManagerService.updatePowerStateLocked方法深浮,DisplayPowerController通過調(diào)用blockScreenOn和unblockScreenOn方法等待鎖屏和其他窗口繪制
  2. 首先繪制鎖屏压怠,鎖屏繪制完后調(diào)用WMS.waitForAllWindowsDrawn繪制其他可見窗口,一般是statusBar和Wallpaper窗口飞苇,同時(shí)發(fā)送1s timeout消息WAITING_FOR_DRAWN_TIMEOUT,如果1s內(nèi)繪制完成則remove這個(gè)消息菌瘫,如果沒有繪制完則執(zhí)行WAITING_FOR_DRAWN_TIMEOUT消息洋闽,不再等待直接喚醒屏幕。
  3. 窗口繪制的最主要方法是RootWindowContainer.performSurfacePlacement突梦,該方法在AnimationThread中執(zhí)行诫舅,窗口動(dòng)畫也是在這個(gè)線程執(zhí)行。在這個(gè)方法中首先計(jì)算窗口大小,準(zhǔn)備窗口動(dòng)畫宫患,然后更新窗口繪制狀態(tài)刊懈,調(diào)用commitFinishDrawingLocked更新窗口繪制狀態(tài)為HAS_DRAWN
  4. 窗口繪制準(zhǔn)備就緒,回調(diào)ScreenOnUnblocker.onScreenOn方法娃闲,通知PowerManagerService點(diǎn)亮屏幕虚汛。在performSurfacePlacement最后向Chrographer發(fā)起執(zhí)行窗口動(dòng)畫請(qǐng)求。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皇帮,一起剝皮案震驚了整個(gè)濱河市卷哩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌属拾,老刑警劉巖将谊,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異渐白,居然都是意外死亡尊浓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門纯衍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栋齿,“玉大人,你說我怎么就攤上這事襟诸⊥叨拢” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵歌亲,是天一觀的道長菇用。 經(jīng)常有香客問我,道長应结,這世上最難降的妖魔是什么刨疼? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任泉唁,我火速辦了婚禮鹅龄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亭畜。我一直安慰自己扮休,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布拴鸵。 她就那樣靜靜地躺著玷坠,像睡著了一般蜗搔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上八堡,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天樟凄,我揣著相機(jī)與錄音,去河邊找鬼兄渺。 笑死缝龄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挂谍。 我是一名探鬼主播叔壤,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼口叙!你這毒婦竟也來了炼绘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤妄田,失蹤者是張志新(化名)和其女友劉穎俺亮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疟呐,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铅辞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萨醒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斟珊。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖富纸,靈堂內(nèi)的尸體忽然破棺而出囤踩,到底是詐尸還是另有隱情,我是刑警寧澤晓褪,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布堵漱,位于F島的核電站,受9級(jí)特大地震影響涣仿,放射性物質(zhì)發(fā)生泄漏勤庐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一好港、第九天 我趴在偏房一處隱蔽的房頂上張望愉镰。 院中可真熱鬧,春花似錦钧汹、人聲如沸丈探。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碗降。三九已至隘竭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讼渊,已是汗流浹背动看。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爪幻,地道東北人弧圆。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像笔咽,于是被迫代替她去往敵國和親搔预。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容