一,概述
本文通过分析屏保的启动过程以及分析系统无操作进入休眠的源码,来分享如何利用系统自带的DreamService
实现屏保,系统计时,无操作多少秒后,启动屏保页。先说一下系统的修改方案,然后通过源码,讲述一下修改的原理
二,修改方案
1,默认屏保的样式
frameworks/base/core/res/res/values/config.xml
<string name="config_dreamsDefaultComponent" translatable="false">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
+ <string name="config_dreamsDefaultComponent" translatable="false">包名/类名</string>
2,允许任何时候都可进入屏保
frameworks/base/core/res/res/values/config.xml
<bool name="config_dreamsEnabledOnBattery">false</bool>
+ <bool name="config_dreamsEnabledOnBattery">true</bool>
3,无操作进入屏保
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
long screenSaverNextTimeout = 0;//添加计算下次进入屏保的时间
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
//获取睡眠时长,为Settings.Secure.SLEEP_TIMEOUT的值和最小休眠时间的最大值,Settings.Secure.SLEEP_TIMEOUT一般为-1,
//表示禁用,因此该值默认为-1
final int sleepTimeout = getSleepTimeoutLocked();
//获取休眠时长,在Settings中设置的值
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
//获取Dim时长,由休眠时长剩Dim百分比得到
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
//用户活动是否由Window覆盖
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
final long screenSaverTimeout = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.SCREENSAVER_TIMEOUT,0);//无操作多少分钟后进入屏保的时间
//该值用来统计用户活动状态,每次进入该方法,置为0
mUserActivitySummary = 0;
//上次用户活动时间>=上次唤醒时间
if (mLastUserActivityTime >= mLastWakeTime) {
//下次超时时间为上次用户活动时间+休眠时间-Dim时间,到达这个时间后,将进入Dim状态
nextTimeout = mLastUserActivityTime
+ screenOffTimeout - screenDimDuration;
screenSaverNextTimeout = mLastUserActivityTime + screenSaverTimeout;//无操作后下次进入屏保的时间
//如果当前时间<nextTimeout,则此时处于亮屏状态,标记mUserActivitySummary为USER_ACTIVITY_SCREEN_BRIGHT
if (now < nextTimeout) {
//无操作后进入休眠的时间 大于 无操作后进入屏保的时间,
//而且当前的时间 大于 无操作后下次进入屏保的时间则进入屏保
if( screenSaverTimeout > 0 && screenOffTimeout > screenSaverTimeout && now > screenSaverNextTimeout ){
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
}else{//否则保持屏保亮屏
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
}
} else {
//如果当前时间>nextTimeout,此时有两种情况,要么进入Dim要么进入Sleep
//将上次用户活动时间+灭屏时间赋值给nextTimeout,如果该值大于当前时间,则说明此时应该处于Dim状态
//因此将标记mUserActivitySummary为USER_ACTIVITY_SCREEN_DIM
nextTimeout = mLastUserActivityTime + screenOffTimeout;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
//判断和USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS标记相关,如果带有此标记,才会进入该if
if (