Android 屏保时间的介绍
屏保 当Android 系统处于无操作一段时间之后就会处于一个屏保的状态,当再过一点时间Android 就会进入一个休眠状体。
默认时间的设置
SettingsProvider 里面设置默认的超时时间。defaults.xml 里面配置的默认值,
<integer name="def_screen_off_timeout">60000</integer> // 1分钟
DatabaseHelper 里面loadSystemSettings 里面对默认值进行设置。
private void loadSystemSettings(SQLiteDatabase db) {
SQLiteStatement stmt = null;
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
···
loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
R.integer.def_screen_off_timeout); // 本地化保存
···
} finally {
if (stmt != null) stmt.close();
}
}
如何对默认值进行设置。可以使用Overlay 进行设置,Overlay怎么设置 就可以参考google/atv/overlay/TvSettingsProviderOverlay 参考google 怎么设置的。
我们只对TvSettingsProvider 里面的defaults 进行重写把需要设置的 def_screen_off_timeout 重新赋值就行。
<integer name="def_screen_off_timeout">120000</integer> // 2分钟
应用的设置和使用
这种设置功能只在设置里面进行设置,其他的应用里面正常不会操作。
- 获取当前的默认时间
Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT,
DEFAULT_DREAM_TIME_MS); - 修改默认时间
Settings.System.putInt(mView.provideContext().getContentResolver(), SCREEN_OFF_TIMEOUT, time);
普通应用 当我们页面不像进入屏保是 使用 keep_screen_on。
1 manifest 里面 设置 android:keepScreenOn="true"
2 时java 代码里面进行设置。
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
3 是使用PowerManager WakeLock 使用,这种我没使用过,
pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyTag");
wl.acquire();
wl.release();
屏保的计算
PowerManagerService里面
updatePowerStateLocked 这个方法是PowerManagerService 的核心方法 里面是对 屏幕的各种状态,用户活动,电源情况等各种情况的梳理都在这个方法里面。
属性 mScreenOffTimeoutSetting 是对屏保时间的记录,正常应该会有初始值的获取和值变化的更新。
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
···
mSettingsObserver = new SettingsObserver(mHandler);
···
updateSettingsLocked(); // 初始化
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked(); // 更新各种状态
}
final ContentResolver resolver = mContext.getContentResolver();
···
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL); // 监听变化
···
}
private final class SettingsObserver extends ContentObserver {
@Override
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
handleSettingsChangedLocked(); // 变化时候进行
}
}
}
void handleSettingsChangedLocked() {
updateSettingsLocked(); // 监听变化
updatePowerStateLocked(); // 更新各种状态
}
updateSettingsLocked 里面 对 mScreenOffTimeoutSetting进行赋值。
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);
mSettingsObserver 里面监听到变化之后 立马调用 updateSettingsLocked 更新值的变化,之后调用updatePowerStateLocked,根据最新的值取更新各个状态。
updatePowerStateLocked 方法
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
private void updatePowerStateLocked() {
···
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
// 查询了一下 Trace 成对出现 key 一样 记录 cpu 线程 耗时等信息
// 类似于 android studio 的 profile 下抓取信息
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty); // 更新电源信息 是否 插入电源 电源类型 电池的状态 有变化的话 更新mDirty 的值 。
updateStayOnLocked(mDirty); // 更新屏幕唤醒
updateScreenBrightnessBoostLocked(mDirty);// 更新屏幕亮度 时间 增强结束 里面通过 handler 发送时间
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1); // 更新 mWakeLockSummary 遍历 所有的 mWakeLocks 把 WakeLock 信息都保存到 mWakeLockSummary 。
updateUserActivitySummaryLocked(now, dirtyPhase1); // 更新用户时间
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) { // 设置Wakefulness 状态 包含dream
break;
}
}
// Phase 2: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); // 请求display 进行变化操作
// Phase 4: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady); // dream 操作
// 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);
}
}
updatePowerStateLocked 方法里面有四个方法对屏保设置有关。
1 updateUserActivitySummaryLocked
方法 updateUserActivitySummaryLocked 更新mUserActivitySummary 用来总结用户请求系统状态,比如设置屏幕 bright dream dim 等。
注意 nextTimeout hasUserActivitySummary 循环内部 groupUserActivitySummary 和groupNextTimeout 内部变量。
内部循环 通过 groupUserActivitySummary groupNextTimeout 计算出 nextTimeout hasUserActivitySummary 。
最终调用 scheduleUserInactivityTimeout-- 》 mHandler ==〉》MSG_USER_ACTIVITY_TIMEOUT --》 handleUserActivityTimeout(){
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();}
/**
* Updates the value of mUserActivitySummary to summarize the user requested
* state of the system such as whether the screen should be bright or dim.
* Note that user activity is ignored when the system is asleep.
*
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_DISPLAY_GROUP_WAKEFULNESS | DIRTY_WAKE_LOCKS
| DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) == 0) {
return;
}
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
final long attentiveTimeout = getAttentiveTimeoutLocked();// 进入Sleep 之前得提示得延时时间
// 获取休眠 超时时长
final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
// 获取屏保超时时长
long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
attentiveTimeout);
// 获取dim时长 由 休眠市场 乘以 dim 百分比 获取再与默认值 做对比取最大值
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
// 根据 faceDown 标记 重新设置 屏保超时时长 脸部朝下的判断
screenOffTimeout =
getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
long nextTimeout = -1; // 最终 nextTime 计算下面Inactivity 的时间
boolean hasUserActivitySummary = false; // 用户请求是否变化
for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
int groupUserActivitySummary = 0; // 循环内部 用户请求屏幕变化
long groupNextTimeout = 0; // 循环内部 next inactivity 的时间
if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) {
final long lastUserActivityTime =
mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId);
final long lastUserActivityTimeNoChangeLights =
mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
groupId);
// 判断接下来是 继续 screen 还是 进入 dim
if (lastUserActivityTime >= mLastWakeTime) { // 判断 上次用户活动时间 大于上次wake 时间
groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
if (now < groupNextTimeout) { // 没到dim 时间 继续 亮屏
groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else {
groupNextTimeout = lastUserActivityTime + screenOffTimeout;
if (now < groupNextTimeout) { // 到了dim 时间 标记dim groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
// 根据 DisplayPowerRequest 来设置 显示类型
if (groupUserActivitySummary == 0
&& lastUserActivityTimeNoChangeLights >= mLastWakeTime) {
groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < groupNextTimeout) {
final DisplayPowerRequest displayPowerRequest =
mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
|| displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (groupUserActivitySummary == 0) {
if (sleepTimeout >= 0) { // 休眠时常
final long anyUserActivity = Math.max(lastUserActivityTime,
lastUserActivityTimeNoChangeLights);
if (anyUserActivity >= mLastWakeTime) {
groupNextTimeout = anyUserActivity + sleepTimeout;
if (now < groupNextTimeout) { // 还没超过休眠的时间
groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
}
}
} else {
groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;// 一直休眠
groupNextTimeout = -1;
}
}
if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM
&& userInactiveOverride) {
if ((groupUserActivitySummary &
(USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {// 保持 bright 或者dim
// Device is being kept awake by recent user activity
if (mOverriddenTimeout == -1) {
// Save when the next timeout would have occurred
mOverriddenTimeout = groupNextTimeout;
}
}
groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
groupNextTimeout = -1;
}
if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
&& (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
& WAKE_LOCK_STAY_AWAKE) == 0) { // 保持亮度并且 没有 STAY_AWAKE 的情况
groupNextTimeout = mAttentionDetector.updateUserActivity(groupNextTimeout,
screenDimDuration); // 获取下次检查dim 时间
}
hasUserActivitySummary |= groupUserActivitySummary != 0;
if (nextTimeout == -1) {
nextTimeout = groupNextTimeout;
} else if (groupNextTimeout != -1) {
nextTimeout = Math.min(nextTimeout, groupNextTimeout);
}
}
mDisplayGroupPowerStateMapper.setUserActivitySummaryLocked(groupId,
groupUserActivitySummary);
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: groupId=" + groupId
+ ", mWakefulness=" + wakefulnessToString(
mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId))
+ ", mUserActivitySummary=0x" + Integer.toHexString(
groupUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(groupNextTimeout));
}
}
final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
if (nextProfileTimeout > 0) {
nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
}
if (hasUserActivitySummary && nextTimeout >= 0) {
scheduleUserInactivityTimeout(nextTimeout);
}
}
2 updateWakefulnessLocked
方法。updateWakefulnessLocked 返回 false 退出循环
for 循环最多走一次 dirty = 0 时候 退出 有第二次的话 dirty 被重新赋值为0。
里面 sleepDisplayGroupNoUpdateLocked 和sleepDisplayGroupNoUpdateLocked 更新 wakefullness 的状态。
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 | DIRTY_ATTENTIVE | DIRTY_SETTINGS
| DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
final long time = mClock.uptimeMillis();
for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
//屏幕是唤醒状态并且将要推出唤醒 (屏保或者休眠)
if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(id) == WAKEFULNESS_AWAKE
&& isItBedTimeYetLocked(id)) {.
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time for group " + id);
}
if (isAttentiveTimeoutExpired(id, time)) { // 提醒时间到了
changed = sleepDisplayGroupNoUpdateLocked(id, time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
} else if (shouldNapAtBedTimeLocked()) {
//是否支持屏保
changed = dreamDisplayGroupNoUpdateLocked(id, time, Process.SYSTEM_UID);
} else {
// 正常灭屏 超市自动灭屏
changed = sleepDisplayGroupNoUpdateLocked(id, time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
}
}
}
}
return changed;
}
dreamDisplayGroupNoUpdateLocked 设置当前之后的状态是 dream 状态。
private boolean dreamDisplayGroupNoUpdateLocked(int groupId, long eventTime, int uid) {
···
mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, true);
setWakefulnessLocked(groupId, WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */
0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
···
return true;
}
3 updateDisplayPowerStateLocked 方法 里面声明了对DisplayPower 的进行的设置 初始化 DisplayPowerRequest displayPowerRequest 然后对他进行搁置参数的设置
然后请求请求成功后 final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
displayPowerRequest, mRequestWaitForNegativeProximity); mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
这里对setReady 对后面 更新Dream 的时候 有个使用的判断。
private boolean updateDisplayPowerStateLocked(int dirty) {
final boolean oldDisplayReady = mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked();
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) != 0) {
if ((dirty & DIRTY_QUIESCENT) != 0) {
if (mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
sQuiescent = false;
} else {
mDirty |= DIRTY_QUIESCENT;
}
}
for (final int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
final DisplayPowerRequest displayPowerRequest =
mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
displayPowerRequest.policy = getDesiredScreenPolicyLocked(groupId);
// Determine appropriate screen brightness and auto-brightness adjustments.
final boolean autoBrightness;
final float screenBrightnessOverride;
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
screenBrightnessOverride = mScreenBrightnessDefault;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
autoBrightness = false;
screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
} else {
autoBrightness = (mScreenBrightnessModeSetting
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
// Update display power request.
displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
displayPowerRequest.useAutoBrightness = autoBrightness;
displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
updatePowerRequestFromBatterySaverPolicy(displayPowerRequest);
if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if ((mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
& WAKE_LOCK_DRAW) != 0 && !mDrawWakeLockOverrideFromSidekick) {
if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
displayPowerRequest.dozeScreenState = Display.STATE_ON;
}
}
displayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManagerFloat;
} else {
displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
displayPowerRequest.dozeScreenBrightness =
PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
displayPowerRequest, mRequestWaitForNegativeProximity);
mNotifier.onScreenPolicyUpdate(displayPowerRequest.policy);
final boolean displayReadyStateChanged =
mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
final boolean poweringOn =
mDisplayGroupPowerStateMapper.isPoweringOnLocked(groupId);
if (ready && displayReadyStateChanged && poweringOn
&& mDisplayGroupPowerStateMapper.getWakefulnessLocked(
groupId) == WAKEFULNESS_AWAKE) {
mDisplayGroupPowerStateMapper.setPoweringOnLocked(groupId, false);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
final int latencyMs = (int) (mClock.uptimeMillis()
- mDisplayGroupPowerStateMapper.getLastPowerOnTimeLocked(groupId));
if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
Slog.w(TAG, "Screen on took " + latencyMs + " ms");
}
}
}
mRequestWaitForNegativeProximity = false;
}
return mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked() && !oldDisplayReady;
}
4 updateDreamLocked 方法
里面 调用到 scheduleSandmanLocked(); 里面 handler 发送 MSG_SANDMAN
if (mDisplayGroupPowerStateMapper.isSandmanSupported(id)) { // 是否支持dream
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
msg.arg1 = id;
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
handleSandman 对 是否start dream 进行了判断
上面 dreamDisplayGroupNoUpdateLocked 对 wakefulness 和 isSandmanSummoned 两个条件进行了设置
sleepDisplayGroupNoUpdateLocked 里面也对 WAKEFULNESS_DOZING 进行了设置。
mDisplayGroupPowerStateMapper.isReady(groupId))判断 updateDisplayPowerStateLocked 对这个ready 进行了设置
canDreamLocked对dream 的条件进行判断,主要是一些电量和状态,开关,后面有介绍。
canDozeLocked 对Doz条件的判断。
startDreaming 是true 的时候 DreamManager来进行 dream 开启。
private void handleSandman(int groupId) { // runs on handler thread
// Handle preconditions.
final boolean startDreaming;
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
if (!ArrayUtils.contains(ids, groupId)) {
// Group has been removed.
return;
}
wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) &&
mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId)
&& mDisplayGroupPowerStateMapper.isReady(groupId)) {
startDreaming = canDreamLocked(groupId) || canDozeLocked();
mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, false);
} else {
startDreaming = false;
}
}
// 上面判断是否dream 上面 dreamDisplayGroupNoUpdateLocked 对 wakefulness 和 isSandmanSummoned 两个条件进行了设置。
// Start dreaming if needed.
// We only control the dream on the handler thread, so we don't need to worry about
// concurrent attempts to start or stop the dream.
final boolean isDreaming;
if (mDreamManager != null) {
// Restart the dream whenever the sandman is summoned.
if (startDreaming) {
mDreamManager.stopDream(false /*immediate*/);
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
}
isDreaming = mDreamManager.isDreaming();
} else {
isDreaming = false;
}
// At this point, we either attempted to start the dream or no attempt will be made,
// so stop holding the display suspend blocker for Doze.
mDozeStartInProgress = false;
// Update dream state.
synchronized (mLock) {
final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
if (!ArrayUtils.contains(ids, groupId)) {
// Group has been removed.
return;
}
// Remember the initial battery level when the dream started.
if (startDreaming && isDreaming) {// 记录当前电池水平
mBatteryLevelWhenDreamStarted = mBatteryLevel;
if (wakefulness == WAKEFULNESS_DOZING) {
Slog.i(TAG, "Dozing...");
} else {
Slog.i(TAG, "Dreaming...");
}
}
// If preconditions changed, wait for the next iteration to determine
// whether the dream should continue (or be restarted).
if (mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId) // 如果是 start dream 的话 上面判断startdream 的时候 设置成false 了
|| mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != wakefulness) { // getWakefulnessLocked 改变的话return
return; // wait for next cycle
}
// Determine whether the dream should continue.
long now = mClock.uptimeMillis();
if (wakefulness == WAKEFULNESS_DREAMING) {
if (isDreaming && canDreamLocked(groupId)) {
// 当前 掉电比较快 mDreamsBatteryLevelDrainCutoffConfig 掉电一个标记 大于这个值 就要停止掉dream
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
&& mBatteryLevel < mBatteryLevelWhenDreamStarted
- mDreamsBatteryLevelDrainCutoffConfig
&& !isBeingKeptAwakeLocked(groupId)) {
// If the user activity timeout expired and the battery appears
// to be draining faster than it is charging then stop dreaming
// and go to sleep.
Slog.i(TAG, "Stopping dream because the battery appears to "
+ "be draining faster than it is charging. "
+ "Battery level when dream started: "
+ mBatteryLevelWhenDreamStarted + "%. "
+ "Battery level now: " + mBatteryLevel + "%.");
} else {
return; // continue dreaming
}
}
// 停止 dream
// Dream has ended or will be stopped. Update the power state.
if (isItBedTimeYetLocked(groupId)) {
final int flags = isAttentiveTimeoutExpired(groupId, now)
? PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE : 0;
// 休眠
sleepDisplayGroupNoUpdateLocked(groupId, now,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags, Process.SYSTEM_UID);
} else {
//唤醒
wakeDisplayGroupNoUpdateLocked(groupId, now, PowerManager.WAKE_REASON_UNKNOWN,
"android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
}
updatePowerStateLocked();
} else if (wakefulness == WAKEFULNESS_DOZING) {
if (isDreaming) {
return; // continue dozing
}
// 跟新 power state
// Doze has ended or will be stopped. Update the power state.
reallySleepDisplayGroupNoUpdateLocked(groupId, now, Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
// Stop dream.
if (isDreaming) {
mDreamManager.stopDream(false /*immediate*/);
}
}
canDreamLocked
private boolean canDreamLocked(int groupId) {
final DisplayPowerRequest displayPowerRequest =
mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
if (!mBootCompleted // 初始化走完
|| getWakefulnessLocked() != WAKEFULNESS_DREAMING // wakefullness 是 WAKEFULNESS_DREAMING
|| !mDreamsSupportedConfig // 设备支持
|| !mDreamsEnabledSetting // dream开关开启
|| !displayPowerRequest.isBrightOrDim() // 没有request Bright 或者是Dim
|| displayPowerRequest.isVr()
|| (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & (
USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM
| USER_ACTIVITY_SCREEN_DREAM)) == 0) {
return false;
}
if (!isBeingKeptAwakeLocked(groupId)) { // 不处于唤醒状态
if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) { // 没充电 电源选项没配置 不可dream
return false;
}
if (!mIsPowered
&& mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) { // 没充电 电量过低
return false;
}
// 1 充电 2 dream充电最小电池水平小与0 3 当前电量水平大于dream充电最小电池水平 三个 满足一个是true
return !mIsPowered
|| mDreamsBatteryLevelMinimumWhenPoweredConfig < 0
|| mBatteryLevel >= mDreamsBatteryLevelMinimumWhenPoweredConfig;
}
return true;
}
canDozeLocked 判断就计较简单 判断wakefulness
private boolean canDozeLocked() {
return getWakefulnessLocked() == WAKEFULNESS_DOZING;
}