Android亮屏流程之窗口绘制

一、亮屏流程

点亮屏幕会调用PowerManagerService关键方法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);
         }
     }

其中调用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中对mPendingScreenOnUnblocker赋值,并记录时间用于打印log,

    private void blockScreenOn() {
        if (mPendingScreenOnUnblocker == null) {
            //asyncTrace可以不在一个方法里
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
            //创建ScreenOnUnblocker对象等待窗口绘制玩回调
            mPendingScreenOnUnblocker = new ScreenOnUnblocker();
            mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
            Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
        }
    }

接下来看mWindowManagerPolicy.screenTurningOn,这里开始绘制锁屏和其他窗口,分别调用PhoneWindowManager 的finishKeyguardDrawn->mWindowManagerInternal.waitForAllWindowsDrawn->mWindowManagerDrawCallback.run->finishWindowsDrawn->finishScreenTurningOn,在这里回调blockScreenOn中创建的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;
           }
       }
   }

收到窗口绘制完成回调后将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);
        }
    }

然后再次调用updatePowerState ,此时mPendingScreenOnUnblocker == null,因此调用mWindowManagerPolicy.screenTurnedOn通知PhoneWindowManager 屏幕已点亮

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后面有调用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)真正的点亮屏幕

二、绘制锁屏和窗口

上面DisplayPowerController.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;
   }

/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();
              }
          }
      }
      //绘制结束后回调
    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();
      }

绘制结束后调用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();
              }
          }

所以绘制锁屏和其他可见窗口的时间会影响亮屏速度,继续往下看

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 设置窗口绘制状态,将需要绘制的窗口放入mWaitingForDrawn,
  2. mWindowPlacerLocked.requestTraversal 绘制窗口
    WindowSurfacePlacer的requestTraversal方法只是向AnimationThread 线程post了一个mPerformSurfacePlacement Runnable,mAnimationHandler收到这个消息后,performSurfacePlacement()方法就会执行,接着调用 performSurfacePlacementLoop->RootWindowContainer.performSurfacePlacement,
    AnimationThread 继承 HandlerThread 一个带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中执行,因此如果有耗时动画,会影响performSurfacePlacement方法执行,进而影响commitFinishDrawingLocked调用,commitFinishDrawingLocked调用后才会点亮屏幕,因此如果出现亮屏慢的问题,也可以监控AnimationThread中的Looper,看看改线程正在执行什么消息

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之间是对surface进行操作,如setSize,setLayer,setPosition等都不是及时生效的,而是要等到业务关闭之后才统一通知SurfaceFlinger,可以避免属性过快带来的画面不稳定
               ">>> 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");
       }

       ... ...

       //开始动画发送choreography.postCallback
       mService.scheduleAnimationLocked();
       mService.mWindowPlacerLocked.destroyPendingSurfaces();

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

applySurfaceChangesTransaction中计算窗口大小及完成窗口动画

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;
       //最多循环6次,计算窗口大小
       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.
           //计算窗口重点在这里
           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赋值,判断是否需要下一次计算
           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;
       //调用 winAnimator.computeShownFrameLocked(); 计算动画变换矩阵 包括转屏,平移等动画
       forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
       ... ...

       return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
   }

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

     // First perform layout of any root windows (not attached to another window).
     //mPerformLayout中调用mPolicy.layoutWindowLw()得到窗口布局的8个区域,而后WindowState.computeFrameLw()得到四个区域,根据这四个区域再加上
     //LayoutParames和ViewRootImpl中的requestHeight,requestWidth得到最终的窗口大小保存到mFrame中
     forAllWindows(mPerformLayout, true /* traverseTopToBottom */);

     ... ...
 }
  1. 窗口绘制状态更新
  private final Consumer 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.
          // 窗口绘制完成,更新状态
          final boolean committed = winAnimator.commitFinishDrawingLocked();
          ... ...       
          final TaskStack stack = w.getStack();
          if ((!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening())
                  || (stack != null && stack.isAnimatingBounds())) {
              //计算AppWindowAnimator,ScreenRotationAnimation,WindowStateAnimatior加一起的变换矩阵
              winAnimator.computeShownFrameLocked();
          }
          winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
      }
      ... ...
  };

commitFinishDrawingLocked方法中调用WindowState.performShowLocked更新窗口绘制状态 为HAS_DRAWN

绘制之后检查窗口状态checkDrawnWindowsLocked,已经画完的窗口,从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内还没有移除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. 触发绘制动画
    frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
   void scheduleAnimationLocked() {
       mAnimator.scheduleAnimation();
   }

向Choreographer 发起绘制动画请求
frameworks/base/services/core/java/com/android/server/wm/

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

Callback mAnimationFrameCallback在AnimationThread线程执行,AnimationThread是一个HandlerThread,所有窗口动画在该线程中执行
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中创建Choreographer对象,所以实在AnimationThread所在的线程执行动画
       AnimationThread.getHandler().runWithScissors(
               () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);

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

窗口动画分为:

  • AppWindowAnimator
    Activity进入退出动画

  • ScreenRotationAnimation
    窗口旋转动画

  • WindowStateAnimator
    普通窗口动画

    1. 负责合成 AppWindowAnimator,ScreenRotationAnimation,WindowStateAnimatior的变换矩阵
    2. 保存了窗口Surface属性
  • DimAnimation

WindowAnimator单例,用于管理所有窗口动画

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切换动画,AppWindowAnimator中专门执行Activity动画
                    dc.stepAppWindowsAnimation(mCurrentTime);
                    DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
                    //2. 屏幕旋转动画
                    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更新普通窗口动画
                    dc.updateWindowsForAnimator(this);
                    //4. 壁纸动画
                    dc.updateWallpaperForAnimator(this);
                    //5. 将变换矩阵设置在Surface上
                    dc.prepareWindowSurfaces();
                }
                ... ...
                //是否申请绘制下一桢动画
                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");
            }
            //继续绘制
            if (!mAnimating && mLastAnimating) {
                mWindowPlacerLocked.requestTraversal();
                mService.mTaskSnapshotController.setPersisterPaused(false);
                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
            }

             ... ...
        }
    }

animate方法主要调用了AppWindowAnimator,ScreenRotationAnimation,WindowStateAnimator的stepAnimationLocked方法,stepAnimationLocked将状态迁移到由时间戳currentTime所指定的一桢上。
下面以WindowStateAnimator的stepAnimationLocked方法为例

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

  //计算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) {
       ... ...
       //计算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等属性,从而实现窗口动画的渲染
           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);

           ... ...
   }

至此完成了一帧窗口动画的绘制

总结

  1. 屏幕点亮首先调用PowerManagerService.updatePowerStateLocked方法,DisplayPowerController通过调用blockScreenOn和unblockScreenOn方法等待锁屏和其他窗口绘制
  2. 首先绘制锁屏,锁屏绘制完后调用WMS.waitForAllWindowsDrawn绘制其他可见窗口,一般是statusBar和Wallpaper窗口,同时发送1s timeout消息WAITING_FOR_DRAWN_TIMEOUT,如果1s内绘制完成则remove这个消息,如果没有绘制完则执行WAITING_FOR_DRAWN_TIMEOUT消息,不再等待直接唤醒屏幕。
  3. 窗口绘制的最主要方法是RootWindowContainer.performSurfacePlacement,该方法在AnimationThread中执行,窗口动画也是在这个线程执行。在这个方法中首先计算窗口大小,准备窗口动画,然后更新窗口绘制状态,调用commitFinishDrawingLocked更新窗口绘制状态为HAS_DRAWN
  4. 窗口绘制准备就绪,回调ScreenOnUnblocker.onScreenOn方法,通知PowerManagerService点亮屏幕。在performSurfacePlacement最后向Chrographer发起执行窗口动画请求。

你可能感兴趣的:(Android亮屏流程之窗口绘制)