目录
1. 点亮屏幕的几种方式:
1.1 应用通过PowerManager 的wakeup()接口
1.2 应用创建的窗口带有WindowManager的 FLAG_TURN_SCREEN_ON 的flag
1.3 应用申请wakelock时候,添加 ACQUIRE_CAUSES_WAKEUP 的flag
1.4 通话的时候,通过距离感应器来点亮屏幕
1.5 调用PowerManager.userActivity() 保持亮屏
2.wakeup 亮屏的过程:
2.1 Screen on blocked
2.2 Screen turning on
2.3 PhoneWindowManager.mPowerKeyWakeLock -> interceptKeyBeforeQueueing
2.4 requestGlobalDisplayState->setDisplayState
2.5 requestGlobalDisplayState->setDisplayBrightness->setLight
Power键唤醒也是通过Input事件调用到 PhoneWindowManager 中的按键事件处理函数interceptKeyBeforeQueueing中去调用PowerManager的wakeup接口
PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()->wakeUpFromPowerKey()->wakeUp()
->PowerManager.wakeUp()
本质是调用到PowerManagerService的WakeUp操作:
PowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),"android.server.wm:TURN_ON")
主要的需要关注的方法:WindowState.prepareWindowToDisplayDuringRelayout()
FLAG_TURN_SCREEN_ON log堆栈信息
11-10 12:57:17.267 13957 13992 V WindowManager: at com.android.server.wm.WindowState.prepareWindowToDisplayDuringRelayout(WindowState.java:2405)
11-10 12:57:17.267 13957 13992 V WindowManager: at com.android.server.wm.WindowState.relayoutVisibleWindow(WindowState.java:4520)
11-10 12:57:17.267 13957 13992 V WindowManager: at com.android.server.wm.WindowManagerService.relayoutWindow(WindowManagerService.java:2182)
11-10 12:57:17.267 13957 13992 V WindowManager: at com.android.server.wm.Session.relayout(Session.java:244)
11-10 12:57:17.267 13957 13992 V WindowManager: at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:309)
11-10 12:57:17.267 13957 13992 V WindowManager: at com.android.server.wm.Session.onTransact(Session.java:164)
11-10 12:57:17.267 13957 13992 V WindowManager: at android.os.Binder.execTransact(Binder.java:748)
11-10 12:57:17.268 13957 13992 I PowerManagerService: Waking up from sleep (uid=1000 reason=android.server.wm:TURN_ON)...
PowerManager.acquireWakeLock()->PowerManagerService.acquireWakeLock()->
applyWakeLockFlagsOnAcquireLocked()->wakeUpNoUpdateLocked()-> updatePowerStateLocked()
DisplayPowerController.mProximitySensorListener.onSensorChanged->debounceProximitySensor()
positive =false的时候会给当前时间添加一个250ms 的延迟来重新执行debounceProximitySensor()
debounceProximitySensor()->updatePowerState()
updatePowerState是亮屏过程的会多次重复执行的函数,注意其实通过感应器来熄屏的时候,并不是真正的熄屏,
只是把背光置0,其实本身还是处于亮屏状态.
这个时候如果用PowerManager 相关的接口去判断会发现还是处于亮屏状态。
主要调用流程:
PowerManager.userActivity()->PowerManagerService$BinderService.userActivity()->userActivityInternal()->updatePowerStateLocked()
上面的5种亮屏的情况,这里主要分析一下Power 键亮屏的情况,也就是调用PowerManager 的wakeup()接口的方式,其他的几种方式都是类似的。
上面的5种亮屏的情况,这里主要分析一下Power 键亮屏的情况,也就是调用PowerManager 的wakeup()接口的方式,其他的几种方式都是类似的。
首先整体了解一下wakeup 的大的过程,可以参考下面的一个时序图,但是这个过程是和实际有点差别的,下面时序图的有些过程是异步的,并不是都在同一个线程内执行,画在一起是为了先有个整体的概念,后面会就几个主要的过程再具体分析。
wakeup 亮屏的时序图:
可以先抓个亮屏的systemtrace 来看一下,从下面的截图可以看到亮屏的流程大致在304ms。
通过SystemTracek发现亮屏有以下几个主要流程:
Screen on blocked/Screen turning on /PhoneWindowManager.mPowerKeyWakeLock /interceptKeyBeforeQueueing
setDisplayState/requestGlobalDisplayState/setDisplayBrightness/setLight
下面会分析各段的主要流程
从log 可以发现这个过程从 DisplayPowerController 的 setScreenState()->blockScreenOn() 到 unblockScreenOn().
Log:
12-09 11:39:24.781 1713 1749 I DisplayPowerController: Blocking screen on until initial contents have been drawn.
12-09 11:39:24.940 1713 1749 I DisplayPowerController: Unblocked screen on after 158 ms
这2个log 对应的是 DisplayPowerController 的 blockScreenOn() 和 unblockScreenOn()的执行.
DisplayPowerController.java
private boolean setScreenState(int state, boolean reportOnly) {
final boolean isOff = (state == Display.STATE_OFF);
//.....
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;
}
unblockScreenOn 就是计算 锁屏或者锁屏上面其他窗口的绘制时间的.
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);
}
}
其中 mWindowManagerPolicy.screenTurningOn() 会通过一系列的调用调用到 SystemUI 的KeyguardServiced.onScreenTurningOn().
其中 MSG_KEYGUARD_DRAWN_TIMEOUT 是5000ms,也就是SystenUI 如果处理任务超过了5S就会触发超时机制,
直接调用 finishKeyguardDrawn() 来通知 WindowManagerService 来继续完成窗口的绘制.
@Override
public void screenTurningOn(final ScreenOnListener screenOnListener) {
//...
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();
}
}
KeyguardService.java
@Override // Binder interface
public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");
checkPermission();
mKeyguardViewMediator.onScreenTurningOn(callback);
mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_ON);
Trace.endSection();
}
其中主要是 KeyguardViewMediator 和 KeyguardLifecyclesDispatcher 都是使用Handler 发现message 来处理.
KeyguardViewMediator 最终通过 handleNotifyScreenTurningOn()
KeyguardLifecyclesDispatcher具体任务是通过ScreenLifecycle的实现类来完成.
private void handleNotifyScreenTurningOn(IKeyguardDrawnCallback callback) {
Trace.beginSection("KeyguardViewMediator#handleNotifyScreenTurningOn");
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyScreenTurningOn");
mStatusBarKeyguardViewManager.onScreenTurningOn();
if (callback != null) {
if (mWakeAndUnlocking) {
mDrawnCallback = callback;
} else {
notifyDrawn(callback);
}
}
}
Trace.endSection();
}
其中 mStatusBarKeyguardViewManager.onScreenTurningOn() 是个空方法,没有具体的操作
private void notifyDrawn(final IKeyguardDrawnCallback callback) {
Trace.beginSection("KeyguardViewMediator#notifyDrawn");
try {
callback.onDrawn();
} catch (RemoteException e) {
Slog.w(TAG, "Exception calling onDrawn():", e);
}
Trace.endSection();
}
notifyDrawn() 的参数 IKeyguardDrawnCallback callback 很重要,它是 PhoneWindowManager 内部的实现了 DrawnListener 接口的实体类对象 mKeyguardDrawnCallback
final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
@Override
public void onDrawn() {
if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
}
};
MSG_KEYGUARD_DRAWN_COMPLETE 会通过Handler 消息机制调用 PhoneWindowManager 的 finishKeyguardDrawn(),
finishKeyguardDrawn() 前面已经提到过,就是等待 WMS 继续处理窗口绘制相关的工作.
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();
}
}
如果有需要绘制的窗口那么mWaitingForDrawn 的size肯定大于0,就会处理 checkDrawnWindowsLocked().
checkDrawnWindowsLocked()最终就是调用PhoneWindowManager的finishWindowsDrawn().
同时 WindowManagerService 处理绘制相关的任务也有一个超时机制,用来确保1000ms 后窗口绘制还没有完成的时候也可以继续执行正常的流程.
超时机制的主要流程是:通过Handler的WAITING_FOR_DRAWN_TIMEOUT 消息来控制的,这个时间是1000ms.
当窗口都绘制完成或者超过1S之后就会执行Handler的ALL_WINDOWS_DRAWN 消息,这个消息会继续回调 PhoneWindowManager 的 Runnable mWindowManagerDrawCallback.run()
而这个Runnable 的主要工作就是继续执行 Handler 的 MSG_WINDOW_MANAGER_DRAWN_COMPLETE 消息来 执行 PhoneWindowManager 的 finishWindowsDrawn().
finishWindowsDrawn() 下一步任务是调用 finishScreenTurningOn()
WMS 的 checkDrawnWindowsLocked 到 PhoneWindowManager 的finishScreenTurningOn 的流程:
checkDrawnWindowsLocked()->ALL_WINDOWS_DRAWN->PhoneWindowManager.mWindowManagerDrawCallback.run()
->finishScreenTurningOn()
private void finishScreenTurningOn() {
//..
if (listener != null) {
listener.onScreenOn();
}
//...
}
这个ScreenOnListener listener 就是通过 DisplayPowerController 的内部类 ScreenOnUnblocker mPendingScreenOnUnblocker.
后续就是通过 mPendingScreenOnUnblocker.onScreenOn() 发送 MSG_SCREEN_ON_UNBLOCKED 消息完成 unblockScreenOn()
总结一下:
Screen on blocked 的主要过程就是通过DisplayPowerController.java PhoneWindowManager.java WindowManagerService.java 和SystemUI 来完成 screenTurningOn 流程.也就是锁屏和其他窗口的绘制流程.
想要这个过程具体是卡在那里耗时,就打开 WindowManagerService 的 DEBUG_SCREEN_ON 开关,可以通过 checkDrawnWindowsLocked() 的log看到这段时间主要是绘制那个窗口需要绘制.
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);
}
}
SystemTrace 里面的 Screen turning on 这段和前面的 Screen on blocked 的 screenTurningOn 不是一样的.
前者比后者包含的过程更多,时间也更久.
Log:
12-09 11:39:24.776 1713 1823 I PowerManagerService: Waking up from sleep (uid=1000 reason=android.policy:POWER)...
//12-09 11:39:24.781 1713 1749 I DisplayPowerController: Blocking screen on until initial contents have been drawn.
//12-09 11:39:24.940 1713 1749 I DisplayPowerController: Unblocked screen on after 158 ms
12-09 11:39:25.024 1713 1749 W PowerManagerService: Screen on took 266 ms
通过log可以发现个过程明显比 Screen on blocked 的158ms 要长的多,而且首尾的2个log表明她们不是在同一个线程里面执行的.
这里首尾2个log 对应的就是 PowerManagerService.wakeUpNoUpdateLocked()到logScreenOn(),而且要执行时间超过200ms 才会打印log.
logScreenOn()主要调用流程:
DisplayPowerController.updatePowerState()->sendOnStateChangedWithWakelock()->
DisplayPowerController$Runnable:mOnStateChangedRunnable run()->
PowerManagerService$DisplayManagerInternal.DisplayPowerCallbacks:onStateChanged()->
PowerManagerService.updatePowerStateLocked()->finishWakefulnessChangeIfNeededLocked()->
PowerManagerService.logScreenOn()
其中有2个地方需要注意:
2.2.1 DisplayPowerController.updatePowerState()中的ready && mustNotify 这2个变量的满足为true 的时候才能继续执行下一步的sendOnStateChangedWithWakelock()
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();
}
// Notify the power manager when ready.
if (ready && mustNotify) {
// Send state change.
synchronized (mLock) {
if (!mPendingRequestChangedLocked) {
mDisplayReadyLocked = true;
if (DEBUG) {
Slog.d(TAG, "Display ready!");
}
}
}
sendOnStateChangedWithWakelock();
}
//...
}
2.2.2 PowerManagerService.updatePowerStateLocked() 中的有个for 循环,其中的updateWakefulnessLocked(dirtyPhase1)为false 的时候才能执行break 跳出for 循环,继续执行finishWakefulnessChangeIfNeededLocked() 和logScreenOn()
private void 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: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 4: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 6: 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);
}
}
SystemTrace 里面对应的这段这个比较简单.
起点就是 PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()-> mPowerKeyWakeLock.acquire().
终点就是: PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyUp()->
finishPowerKeyPress()->PowerManager$WakeLock.release()
SystemTrace 里面对应的 requestGlobalDisplayState 这段其实是 DisplayManagerService.requestGlobalDisplayStateInternal()
SystemTrace 里面对应的 setDisplayState 这段其实是 LocalDisplayAdapter$LocalDisplayDevice$1.setDisplayState()
requestGlobalDisplayStateInternal:
通过 SystemTrace 或者log 可以发现 requestGlobalDisplayStateInternal() 是有多次执行的.
主要流程是:
DisplayPowerState$PhotonicModulator.run() -> DisplayManagerService$LocalService$1.requestDisplayState()
->DisplayManagerService.requestGlobalDisplayStateInternal()
setDisplayState:
主要流程:
DisplayManagerService.requestGlobalDisplayStateInternal()->applyGlobalDisplayStateLocked()->updateDisplayStateLocked()
->LocalDisplayAdapter$LocalDisplayDevice$1.setDisplayState()
LocalDisplayAdapter.setDisplayBrightness()->LightsService.setBrightness()->setLightLocked()->setLight_native()
通过 SystemTrace 可以看到第2次执行requestGlobalDisplayState 后的 setDisplayBrightness和setLight时间主要耗时是setLight_native耗时,
也就是底层lcd 处理上层传递的亮度参数很耗时.