一、亮屏流程
点亮屏幕会调用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 */);
}
- waitForAllWindowsDrawn 设置窗口绘制状态,将需要绘制的窗口放入mWaitingForDrawn,
- 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;
}
- 窗口大小计算
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 */);
... ...
}
- 窗口绘制状态更新
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.
// 窗口绘制完成,更新状态
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;
}
- 触发绘制动画
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
普通窗口动画- 负责合成 AppWindowAnimator,ScreenRotationAnimation,WindowStateAnimatior的变换矩阵
- 保存了窗口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);
... ...
}
至此完成了一帧窗口动画的绘制
总结
- 屏幕点亮首先调用PowerManagerService.updatePowerStateLocked方法,DisplayPowerController通过调用blockScreenOn和unblockScreenOn方法等待锁屏和其他窗口绘制
- 首先绘制锁屏,锁屏绘制完后调用WMS.waitForAllWindowsDrawn绘制其他可见窗口,一般是statusBar和Wallpaper窗口,同时发送1s timeout消息WAITING_FOR_DRAWN_TIMEOUT,如果1s内绘制完成则remove这个消息,如果没有绘制完则执行WAITING_FOR_DRAWN_TIMEOUT消息,不再等待直接唤醒屏幕。
- 窗口绘制的最主要方法是RootWindowContainer.performSurfacePlacement,该方法在AnimationThread中执行,窗口动画也是在这个线程执行。在这个方法中首先计算窗口大小,准备窗口动画,然后更新窗口绘制状态,调用commitFinishDrawingLocked更新窗口绘制状态为HAS_DRAWN
- 窗口绘制准备就绪,回调ScreenOnUnblocker.onScreenOn方法,通知PowerManagerService点亮屏幕。在performSurfacePlacement最后向Chrographer发起执行窗口动画请求。
网友评论