PMS亮灭屏流程
1、亮屏流程
PMS模块提供了亮屏接口供应用或组件点亮屏幕。
wakeup()
方法
1 2 3 4 5 6 7 8 9 10 11 12 public void wakeUp (long time, @WakeReason int reason, String details) { try { mService.wakeUp(time, reason, details, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
调用PowerManager的wakeup()
方法后,将直接调用PMS.BinderService中的wakeup()
方法。
**Binder:**在Android系统中,Binder用来实现进程之间的通信(IPC)。它是一个工作在Linux层面的驱动,这一驱动运行在内核态。我们在客户端调用Binder最终都是通过系统调用完成的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public void wakeUp (long eventTime, @WakeReason int reason, String details, String opPackageName) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future" ); } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null ); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid); } finally { Binder.restoreCallingIdentity(ident); } }
wakeUpInternal()
方法:
1 2 3 4 5 6 7 8 9 10 private void wakeUpInternal (long eventTime, @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { synchronized (mLock) { if (wakeUpNoUpdateLocked(eventTime, reason, details, uid, opPackageName, opUid)) { updatePowerStateLocked(); } } }
wakeUpNoUpdateLocked()
方法:该方法用以点亮屏幕,亮屏成功返回true并更新全局状态,失败则返回false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private boolean wakeUpNoUpdateLocked (long eventTime, @WakeReason int reason, String details, int reasonUid, String opPackageName, int opUid) { if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE || !mBootCompleted || !mSystemReady || mForceSuspendActive) { return false ; } try { mLastWakeTime = eventTime; mLastWakeReason = reason; setWakefulnessLocked(WAKEFULNESS_AWAKE, reason, eventTime); mNotifier.onWakeUp(reason, details, reasonUid, opPackageName, opUid); userActivityNoUpdateLocked( eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0 , reasonUid); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true ; }
在上述方法中,首先更新最后一次亮屏时间和原因,然后调用setWakefulnessLocked()
方法用于更新设备的wakefulness值,再通过mNotifier将亮屏动作通知给电池状态服务以进行统计,最后更新用户活动时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void setWakefulnessLocked (int wakefulness, int reason, long eventTime) { if (mWakefulness != wakefulness) { mWakefulness = wakefulness; mWakefulnessChanging = true ; mDirty |= DIRTY_WAKEFULNESS; if (mNotifier != null ) { mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime); } mAttentionDetector.onWakefulnessChangeStarted(wakefulness); } }
onWakefulnessChangeStarted()
方法:该方法负责屏幕状态改变后的相关工作,如发送亮灭屏广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public void onWakefulnessChangeStarted (final int wakefulness, int reason, long eventTime) { if (wakefulness == PowerManagerInternal.WAKEFULNESS_HANGUP) { return ; } final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness + ", reason=" + reason + ", interactive=" + interactive); } mHandler.post(new Runnable() { @Override public void run () { mActivityManagerInternal.onWakefulnessChanged(wakefulness); } }); if (mInteractive != interactive) { if (mInteractiveChanging) { handleLateInteractiveChange(); } mInputManagerInternal.setInteractive(interactive); mInputMethodManagerInternal.setInteractive(interactive); try { mBatteryStats.noteInteractive(interactive); } catch (RemoteException ex) { } StatsLog.write(StatsLog.INTERACTIVE_STATE_CHANGED, interactive ? StatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON : StatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF); mInteractive = interactive; mInteractiveChangeReason = reason; mInteractiveChangeStartTime = eventTime; mInteractiveChanging = true ; handleEarlyInteractiveChange(); } }
综上分析,首先判断系统是否可交互,即是否处于Dream或Awake状态,如果是则interactive为true。如果是亮屏场景,则在执行到该方法时,在 setWakeFulnessLocked()
方法中将 wakefulness 设置为了 WAKEFULNESS_AWAKE,所以 interactive 为 true,mInteractive 是 false。因此,会先执行 handleEarlyInteractiveChange()
,之后再执行handleLateInteractiveChange()
方法。
handleEarlyInteractiveChange()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 private void handleEarlyInteractiveChange () { synchronized (mLock) { if (mInteractive) { mHandler.post(new Runnable() { @Override public void run () { final int why = translateOnReason(mInteractiveChangeReason); mPolicy.startedWakingUp(why); } }); mPendingInteractiveState = INTERACTIVE_STATE_AWAKE; mPendingWakeUpBroadcast = true ; updatePendingBroadcastLocked(); } else { final int why = translateOffReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run () { mPolicy.startedGoingToSleep(why); } }); } } }
接下来执行userActivityNoUpdateLocked()
方法,该方法负责更新用户和系统最后交互时间,计算的时间在updateUserActivitySummary()
方法中用于判断何时灭屏。
最后回到wakeUpInternal()
方法,可以看到,当wakeUpNoUpdateLocked()
执行完毕并返回true后,又会执行updatePowerStateLocked()
方法来更新全部的状态,这个方法中会进行亮屏的最关键的操作updateDisplayPowerStateLocked()
,该方法将power中所有的和显示状态、亮度有关的数据封装到DisplayPowerRequest对象中,向DisplayManagerService中发起请求,于是在DisplayPowerController中将开始设置显示状态、亮度等操作,并在这些操作完成后,通知PMS再次请求,并返回true,表示请求处理成功。
2、Notifier类
Notifier类是PMS的帮助类,它里面的一些逻辑不会在PMS线程中执行,而是在system_server主线程中执行,因此,PMS中需要异步与其他组件进行交互的工作就交给了Notifier类。如通知PhoneWindowManager亮灭屏进度、发送亮灭屏广播。
onWakefulnessChangeStarted()
该方法用于亮屏或者灭屏时逻辑的处理,和onWakefulnessChangeFinished()
方法对应,分别负责操作开始和结束的逻辑处理,当wakefulness
改变时进行回调,因此当亮屏、灭屏、进入Doze
模式时都会调用这个方法。相关代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void onWakefulnessChangeStarted (final int wakefulness, int reason, long eventTime) { final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); mHandler.post(new Runnable() { @Override public void run () { mActivityManagerInternal.onWakefulnessChanged(wakefulness); } }); if (mInteractive != interactive) { if (mInteractiveChanging) { handleLateInteractiveChange(); } mInputManagerInternal.setInteractive(interactive); mInputMethodManagerInternal.setInteractive(interactive); try { mBatteryStats.noteInteractive(interactive); } catch (RemoteException ex) { } mInteractive = interactive; mInteractiveChangeReason = reason; mInteractiveChangeStartTime = eventTime; mInteractiveChanging = true ; handleEarlyInteractiveChange(); } }
handleEarlyInteractiveChange()
方法:处理交互状态改变后的早期逻辑,如通知状态栏设备开始亮灭屏,发送亮灭屏广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private void handleEarlyInteractiveChange () { synchronized (mLock) { if (mInteractive) { mHandler.post(new Runnable() { @Override public void run () { final int why = translateOnReason(mInteractiveChangeReason); mPolicy.startedWakingUp(why); } }); mPendingInteractiveState = INTERACTIVE_STATE_AWAKE; mPendingWakeUpBroadcast = true ; updatePendingBroadcastLocked(); } else { final int why = translateOffReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run () { mPolicy.startedGoingToSleep(why); } }); } } }
onWakefulnessChangeFinished()
该方法用以屏幕状态切换完成后,做wakefulness改变完成后的工作。
1 2 3 4 5 6 7 8 public void onWakefulnessChangeFinished () { if (mInteractiveChanging) { mInteractiveChanging = false ; handleLateInteractiveChange(); } }
handleLateInteractiveChange()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private void handleLateInteractiveChange () { synchronized (mLock) { if (mInteractive) { final int why = translateOnReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run () { mPolicy.finishedWakingUp(why); } }); } else { if (mUserActivityPending) { mUserActivityPending = false ; mHandler.removeMessages(MSG_USER_ACTIVITY); } final int why = translateOffReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run () { mPolicy.finishedGoingToSleep(why); } }); mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP; mPendingGoToSleepBroadcast = true ; updatePendingBroadcastLocked(); } } }
在handleLateInteractiveChange()
方法中,如果是亮屏,则调用 PhoneWindowManager 的 finishedWakingUp()
表示亮屏处理成功。如果是灭屏,则调用 PhoneWindowManager 的 finishedGoingToSleep()
。
updatePendingBroadcaseLocked()
该方法用于交互状态改变时发送广播。如亮屏时,在handlerEarlyInteractiveChang()
方法中调用该方法发送广播,灭屏时,在handlerLateInteractiveChang()
中调用该方法发送广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private void updatePendingBroadcastLocked () { if (!mBroadcastInProgress && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast || mPendingInteractiveState != mBroadcastedInteractiveState)) { mBroadcastInProgress = true ; mSuspendBlocker.acquire(); Message msg = mHandler.obtainMessage(MSG_BROADCAST); msg.setAsynchronous(true ); mHandler.sendMessage(msg); } } private int mPendingInteractiveState;private boolean mPendingWakeUpBroadcast;private boolean mPendingGoToSleepBroadcast;private int mBroadcastedInteractiveState;private boolean mBroadcastInProgress;
在进入updatePendingBroadcaseLocked()
方法时,首先会申请一个SuspendBlocker锁,这个锁是通过在PMS中创建Notifier对象时创建传入的,目的是避免在发送广播时系统休眠而导致广播发送失败,该锁在广播发送完成后释放,之后通过mHandler.obtainMessage(MSG_BROADCAST)
调用sendNextBroadcast()
方法发送广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private final class NotifierHandler extends Handler { @Override public void handleMessage (Message msg) { switch (msg.what) { case MSG_BROADCAST: sendNextBroadcast(); break ; } } } private void sendNextBroadcast () { final int powerState; synchronized (mLock) { if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) { mPendingWakeUpBroadcast = false ; mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE; } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) { if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) { mPendingGoToSleepBroadcast = false ; mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP; } else { finishPendingBroadcastLocked(); return ; } } else { if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) { mPendingWakeUpBroadcast = false ; mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE; } else { finishPendingBroadcastLocked(); return ; } } mBroadcastStartTime = SystemClock.uptimeMillis(); powerState = mBroadcastedInteractiveState; } if (powerState == INTERACTIVE_STATE_AWAKE) { sendWakeUpBroadcast(); } else { sendGoToSleepBroadcast(); } }
以亮屏为例,在进入该方法之前时,mPendingWakeUpBroadcast
会设置为true,mPendingInteractiveState
会设置为INTERACTIVE_STATE_AWAKE
,此时mBroadcastedInteractiveState
为INTERACTIVE_STATE_ASLEEP
,当执行到这个方法后,进入else代码块当中,更新mBroadcastedInteractiveState
变量为true,然后将调用sendWakeUpBroadcast()
方法发送亮屏广播:
1 2 3 4 5 6 7 private void sendWakeUpBroadcast () { if (mActivityManagerInternal.isSystemReady()) { mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null , mWakeUpBroadcastDone, mHandler, 0 , null , null ); } else {} }
这里指定了一个mWakeUpBroadcastDone,会在广播发送后,作为最后一个广播接收器,因此会在这里进行广播发送完毕后的工作:
1 2 3 4 5 6 7 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { @Override public void onReceive (Context context, Intent intent) { sendNextBroadcast(); } };
1 2 3 4 private void finishPendingBroadcastLocked () { mBroadcastInProgress = false ; mSuspendBlocker.release(); }
于是亮屏广播就发送完成了。而灭屏广播,则是通过sendGoToSleepBroadcast()
来发送,逻辑类似。
3、灭屏流程
PMS模块同样提供了灭屏接口goToSleep()
,下面分析具体流程。
3.1、Power按键灭屏
当按Power键灭屏时,会在PhoneWindowManager中处理按键事件后调用PMS的goToSleep()
方法进行灭屏处理。
goToSleep()
方法:
1 2 3 4 5 6 7 public void goToSleep (long time, int reason, int flags) { try { mService.goToSleep(time, reason, flags); } catch (RemoteException e) { } }
在PMS中开始向下Binder调用goToSleep()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public void goToSleep (long eventTime, int reason, int flags) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future" ); } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null ); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { goToSleepInternal(eventTime, reason, flags, uid); } finally { Binder.restoreCallingIdentity(ident); } }
在goToSleep()
方法中,检查权限之后,开始调用goToSleepInternal()
方法。
goToSleepInternal()
方法:
1 2 3 4 5 6 7 8 9 private void goToSleepInternal (long eventTime, int reason, int flags, int uid) { synchronized (mLock) { if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) { updatePowerStateLocked(); } } }
在goToSleepInternal()
方法中,先是调用了goToSleepNoUpdateLocked()
方法,并根据方法返回值决定是否调用updatePowerStateLocked()
方法。
goToSleepNoUpdateLocked()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 @SuppressWarnings("deprecation") private boolean goToSleepNoUpdateLocked (long eventTime, int reason, int flags, int uid) { if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || !mBootCompleted || !mSystemReady) { return false ; } try { switch (reason) { case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: Slog.i(TAG, "Going to sleep due to device administration policy " + "(uid " + uid +")..." ); break ; case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")..." ); break ; case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH: Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")..." ); break ; case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON: Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")..." ); break ; case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON: Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")..." ); break ; case PowerManager.GO_TO_SLEEP_REASON_HDMI: Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")..." ); break ; default : Slog.i(TAG, "Going to sleep by application request (uid " + uid +")..." ); reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION; break ; } mLastSleepTime = eventTime; mSandmanSummoned = true ; setWakefulnessLocked(WAKEFULNESS_DOZING, reason); int numWakeLocksCleared = 0 ; final int numWakeLocks = mWakeLocks.size(); for (int i = 0 ; i < numWakeLocks; i++) { final WakeLock wakeLock = mWakeLocks.get(i); switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { case PowerManager.FULL_WAKE_LOCK: case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: case PowerManager.SCREEN_DIM_WAKE_LOCK: numWakeLocksCleared += 1 ; break ; } } if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0 ) { reallyGoToSleepNoUpdateLocked(eventTime, uid); } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true ; }
在goToSleepNoUpdateLocked()
方法中,使用setWakefulnessLocked()
来设置wakefulness值,同时会调用Notifier中的wakefulness相关的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 private void setWakefulnessLocked (int wakefulness, int reason) { if (mWakefulness != wakefulness) { mWakefulness = wakefulness; mWakefulnessChanging = true ; mDirty |= DIRTY_WAKEFULNESS; mNotifier.onWakefulnessChangeStarted(wakefulness, reason); } }
在setWakefulnessLocked()
方法中,调用Notifier中的方法onWakefulnessChangeStarted()
做wakefulness改变开始时的工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public void onWakefulnessChangeStarted (final int wakefulness, int reason) { final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); if (mInteractive != interactive) { if (mInteractiveChanging) { handleLateInteractiveChange(); } mInputManagerInternal.setInteractive(interactive); mInputMethodManagerInternal.setInteractive(interactive); try { mBatteryStats.noteInteractive(interactive); } catch (RemoteException ex) { } mInteractive = interactive; mInteractiveChangeReason = reason; mInteractiveChanging = true ; handleEarlyInteractiveChange(); } }
onWakefulnessChangeStarted()
方法中根据wakefulness值判断了系统当前的交互状态,Awake/Dream状态为可交互,Doze/Asleep状态为不可交互。由于在setWakefulnessLocked()
中设置了wakefulness为Doze状态,因此此刻处于不可交互状态,接下来开始执行handleEarlyInteractiveChange()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 private void handleEarlyInteractiveChange () { synchronized (mLock) { if (mInteractive) { mHandler.post(new Runnable() { @Override public void run () { mPolicy.startedWakingUp(); } }); mPendingInteractiveState = INTERACTIVE_STATE_AWAKE; mPendingWakeUpBroadcast = true ; updatePendingBroadcastLocked(); } else { final int why = translateOffReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run () { mPolicy.startedGoingToSleep(why); } }); } } }
handleEarlyInteractiveChange()
方法中,由于mInteractive为false,将执行else部分调用mPolicy.startedGoingToSleep(why)
进行锁屏流程。
继续回到goToSleepNoUpdateLocked()
方法,由于没有指定跳过Doze状态直接进入Sleep,所以不会立即执行reallyGoToSleepNoUpdateLocked()
方法,此时 goToSleepNoUpdateLocked()
方法完毕并返回 true。
之后开始执行 updatePowerStateLocked()
方法了,在这里我们只看其灭屏时的一些处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private void updatePowerStateLocked () { try { boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); updateDreamLocked(dirtyPhase2, displayBecameReady); finishWakefulnessChangeIfNeededLocked(); updateSuspendBlockerLocked(); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } }
在updateDreamLocked()
中更新屏保状态时,如果此时处于Doze状态且屏保没有进行,则将调用reallyGoToSleepNoUpdateLocked()
方法,将wakefulness值设置为Sleep。相关代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void handleSandman () { synchronized (mLock) { if (wakefulness == WAKEFULNESS_DREAMING) { } else if (wakefulness == WAKEFULNESS_DOZING) { if (isDreaming) { return ; } reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID); updatePowerStateLocked(); } } }
reallyGoToSleepNoUpdateLocked()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private boolean reallyGoToSleepNoUpdateLocked (long eventTime, int uid) { if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) { return false ; } try { setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true ; }
至此Power按键灭屏过程结束,相关流程如图:
3.2、自动灭屏
自动灭屏由用户设置的休眠时间或用户活动影响,用户活动即最近一次用户和设备交互的时间,以此为起点达到休眠时间后开始执行灭屏流程。
userActivityNoUpdateLocked()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 private boolean userActivityNoUpdateLocked (long eventTime, int event, int flags, int uid) { if (eventTime < mLastSleepTime || eventTime < mLastWakeTime || !mBootCompleted || !mSystemReady) { return false ; } try { if (eventTime > mLastInteractivePowerHintTime) { powerHintInternal(PowerHint.INTERACTION, 0 ); mLastInteractivePowerHintTime = eventTime; } mNotifier.onUserActivity(event, uid); if (mUserInactiveOverrideFromWindowManager) { mUserInactiveOverrideFromWindowManager = false ; mOverriddenTimeout = -1 ; } if (mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0 ) { return false ; } if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0 ) { if (eventTime > mLastUserActivityTimeNoChangeLights && eventTime > mLastUserActivityTime) { mLastUserActivityTimeNoChangeLights = eventTime; mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; } return true ; } } else { if (eventTime > mLastUserActivityTime) { mLastUserActivityTime = eventTime; mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; } return true ; } } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return false ; }
在这个方法中,如果传入的参数 flag 为 PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS
,则将事件时间赋值给 mLastUserActivityTimeNoChangeLights,否则将事件时间赋值给 mLastUserActivityTime。这个 flag 标志用于延长亮屏或 Dim 的时长一小会儿。
当这个方法执行之后,就得到了 mLastUserActivityTime 或者 mLastUserActivityTimeNoChangeLights 的值,然后经过一些调用后,又会进入 updatePowerStateLocked()
方法中。在这个方法中,与超时灭屏直接相关的就是 for 循环部分.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private void updatePowerStateLocked () { try { for (;;) { int dirtyPhase1 = mDirty; dirtyPhase2 |= dirtyPhase1; mDirty = 0 ; updateWakeLockSummaryLocked(dirtyPhase1); updateUserActivitySummaryLocked(now, dirtyPhase1); if (!updateWakefulnessLocked(dirtyPhase1)) { break ; } } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } }
updateUserActivitySummaryLocked()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 private void updateUserActivitySummaryLocked (long now, int dirty) { if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0 ) { mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT); long nextTimeout = 0 ; if (mWakefulness == WAKEFULNESS_AWAKE || mWakefulness == WAKEFULNESS_DREAMING || mWakefulness == WAKEFULNESS_DOZING) { final int sleepTimeout = getSleepTimeoutLocked(); final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout); final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager; mUserActivitySummary = 0 ; if (mLastUserActivityTime >= mLastWakeTime) { nextTimeout = mLastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < nextTimeout) { mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { nextTimeout = mLastUserActivityTime + screenOffTimeout; if (now < nextTimeout) { mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } if (mUserActivitySummary == 0 && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) { nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout; if (now < nextTimeout) { if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) { mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } if (mUserActivitySummary == 0 ) { if (sleepTimeout >= 0 ) { final long anyUserActivity = Math.max(mLastUserActivityTime, mLastUserActivityTimeNoChangeLights); if (anyUserActivity >= mLastWakeTime) { nextTimeout = anyUserActivity + sleepTimeout; if (now < nextTimeout) { mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; } } } else { mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; nextTimeout = -1 ; } } if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) { if ((mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0 ) { if (nextTimeout >= now && mOverriddenTimeout == -1 ) { mOverriddenTimeout = nextTimeout; } } mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; nextTimeout = -1 ; } if (mUserActivitySummary != 0 && nextTimeout >= 0 ) { Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); msg.setAsynchronous(true ); mHandler.sendMessageAtTime(msg, nextTimeout); } } else { mUserActivitySummary = 0 ; } } }
MSG_USER_ACTIVITY_TIMEOUT的handler调用逻辑如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public void handleMessage (Message msg) { switch (msg.what) { case MSG_USER_ACTIVITY_TIMEOUT: handleUserActivityTimeout(); break ; } } private void handleUserActivityTimeout () { synchronized (mLock) { mDirty |= DIRTY_USER_ACTIVITY; updatePowerStateLocked(); } }
回到updatePowerStateLocked()
,执行updateWakefulnessLocked()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private boolean updateWakefulnessLocked (int dirty) { boolean changed = false ; if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE | DIRTY_DOCK_STATE)) != 0 ) { if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) { final long time = SystemClock.uptimeMillis(); if (shouldNapAtBedTimeLocked()) { changed = napNoUpdateLocked(time, Process.SYSTEM_UID); } else { changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0 , Process.SYSTEM_UID); } } } return changed; }
isItBedTimeYetLocked()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private boolean isItBedTimeYetLocked () { return mBootCompleted && !isBeingKeptAwakeLocked(); } private boolean isBeingKeptAwakeLocked () { return mStayOn || mProximityPositive || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0 || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0 || mScreenBrightnessBoostInProgress; }
shouldNapAtBedTimeLocked()
方法:返回true,则开始屏保,否则直接休眠。
1 2 3 4 5 6 7 private boolean shouldNapAtBedTimeLocked () { return mDreamsActivateOnSleepSetting || (mDreamsActivateOnDockSetting && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED); }
当开始休眠时,则调用goToSleepNoUpdateLocked()
方法,于是走休眠流程,之后的逻辑和Power键灭屏类似。整体流程如下: