Android 屏保時間的介紹
屏保 當(dāng)Android 系統(tǒng)處于無操作一段時間之后就會處于一個屏保的狀態(tài)残拐,當(dāng)再過一點時間Android 就會進(jìn)入一個休眠狀體渗磅。
默認(rèn)時間的設(shè)置
SettingsProvider 里面設(shè)置默認(rèn)的超時時間。defaults.xml 里面配置的默認(rèn)值寿桨,
<integer name="def_screen_off_timeout">60000</integer> // 1分鐘
DatabaseHelper 里面loadSystemSettings 里面對默認(rèn)值進(jìn)行設(shè)置司光。
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();
}
}
如何對默認(rèn)值進(jìn)行設(shè)置琅坡。可以使用Overlay 進(jìn)行設(shè)置,Overlay怎么設(shè)置 就可以參考google/atv/overlay/TvSettingsProviderOverlay 參考google 怎么設(shè)置的残家。
我們只對TvSettingsProvider 里面的defaults 進(jìn)行重寫把需要設(shè)置的 def_screen_off_timeout 重新賦值就行榆俺。
<integer name="def_screen_off_timeout">120000</integer> // 2分鐘
應(yīng)用的設(shè)置和使用
這種設(shè)置功能只在設(shè)置里面進(jìn)行設(shè)置,其他的應(yīng)用里面正常不會操作。
- 獲取當(dāng)前的默認(rèn)時間
Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT,
DEFAULT_DREAM_TIME_MS); - 修改默認(rèn)時間
Settings.System.putInt(mView.provideContext().getContentResolver(), SCREEN_OFF_TIMEOUT, time);
普通應(yīng)用 當(dāng)我們頁面不像進(jìn)入屏保是 使用 keep_screen_on茴晋。
1 manifest 里面 設(shè)置 android:keepScreenOn="true"
2 時java 代碼里面進(jìn)行設(shè)置陪捷。
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 的核心方法 里面是對 屏幕的各種狀態(tài)市袖,用戶活動,電源情況等各種情況的梳理都在這個方法里面掀虎。
屬性 mScreenOffTimeoutSetting 是對屏保時間的記錄凌盯,正常應(yīng)該會有初始值的獲取和值變化的更新付枫。
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
···
mSettingsObserver = new SettingsObserver(mHandler);
···
updateSettingsLocked(); // 初始化
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked(); // 更新各種狀態(tài)
}
final ContentResolver resolver = mContext.getContentResolver();
···
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL); // 監(jiān)聽變化
···
}
private final class SettingsObserver extends ContentObserver {
@Override
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
handleSettingsChangedLocked(); // 變化時候進(jìn)行
}
}
}
void handleSettingsChangedLocked() {
updateSettingsLocked(); // 監(jiān)聽變化
updatePowerStateLocked(); // 更新各種狀態(tài)
}
updateSettingsLocked 里面 對 mScreenOffTimeoutSetting進(jìn)行賦值烹玉。
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);
mSettingsObserver 里面監(jiān)聽到變化之后 立馬調(diào)用 updateSettingsLocked 更新值的變化,之后調(diào)用updatePowerStateLocked阐滩,根據(jù)最新的值取更新各個狀態(tài)二打。
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 成對出現(xiàn) key 一樣 記錄 cpu 線程 耗時等信息
// 類似于 android studio 的 profile 下抓取信息
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty); // 更新電源信息 是否 插入電源 電源類型 電池的狀態(tài) 有變化的話 更新mDirty 的值 。
updateStayOnLocked(mDirty); // 更新屏幕喚醒
updateScreenBrightnessBoostLocked(mDirty);// 更新屏幕亮度 時間 增強結(jié)束 里面通過 handler 發(fā)送時間
// 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)) { // 設(shè)置Wakefulness 狀態(tài) 包含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 進(jìn)行變化操作
// Phase 4: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady); // dream 操作
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked(); // 發(fā)送通知
// 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 方法里面有四個方法對屏保設(shè)置有關(guān)继效。
1 updateUserActivitySummaryLocked
方法 updateUserActivitySummaryLocked 更新mUserActivitySummary 用來總結(jié)用戶請求系統(tǒng)狀態(tài),比如設(shè)置屏幕 bright dream dim 等装获。
注意 nextTimeout hasUserActivitySummary 循環(huán)內(nèi)部 groupUserActivitySummary 和groupNextTimeout 內(nèi)部變量瑞信。
內(nèi)部循環(huán) 通過 groupUserActivitySummary groupNextTimeout 計算出 nextTimeout hasUserActivitySummary 。
最終調(diào)用 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();// 進(jìn)入Sleep 之前得提示得延時時間
// 獲取休眠 超時時長
final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
// 獲取屏保超時時長
long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
attentiveTimeout);
// 獲取dim時長 由 休眠市場 乘以 dim 百分比 獲取再與默認(rèn)值 做對比取最大值
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
// 根據(jù) faceDown 標(biāo)記 重新設(shè)置 屏保超時時長 臉部朝下的判斷
screenOffTimeout =
getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
long nextTimeout = -1; // 最終 nextTime 計算下面Inactivity 的時間
boolean hasUserActivitySummary = false; // 用戶請求是否變化
for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
int groupUserActivitySummary = 0; // 循環(huán)內(nèi)部 用戶請求屏幕變化
long groupNextTimeout = 0; // 循環(huán)內(nèi)部 next inactivity 的時間
if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) {
final long lastUserActivityTime =
mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId);
final long lastUserActivityTimeNoChangeLights =
mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
groupId);
// 判斷接下來是 繼續(xù) screen 還是 進(jìn)入 dim
if (lastUserActivityTime >= mLastWakeTime) { // 判斷 上次用戶活動時間 大于上次wake 時間
groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
if (now < groupNextTimeout) { // 沒到dim 時間 繼續(xù) 亮屏
groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else {
groupNextTimeout = lastUserActivityTime + screenOffTimeout;
if (now < groupNextTimeout) { // 到了dim 時間 標(biāo)記dim groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
// 根據(jù) DisplayPowerRequest 來設(shè)置 顯示類型
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 退出循環(huán)
for 循環(huán)最多走一次 dirty = 0 時候 退出 有第二次的話 dirty 被重新賦值為0凡简。
里面 sleepDisplayGroupNoUpdateLocked 和sleepDisplayGroupNoUpdateLocked 更新 wakefullness 的狀態(tài)。
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()) {
//屏幕是喚醒狀態(tài)并且將要推出喚醒 (屏本啵或者休眠)
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 設(shè)置當(dāng)前之后的狀態(tài)是 dream 狀態(tài)秤涩。
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 的進(jìn)行的設(shè)置 初始化 DisplayPowerRequest displayPowerRequest 然后對他進(jìn)行擱置參數(shù)的設(shè)置
然后請求請求成功后 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 方法
里面 調(diào)用到 scheduleSandmanLocked(); 里面 handler 發(fā)送 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 進(jìn)行了判斷
上面 dreamDisplayGroupNoUpdateLocked 對 wakefulness 和 isSandmanSummoned 兩個條件進(jìn)行了設(shè)置
sleepDisplayGroupNoUpdateLocked 里面也對 WAKEFULNESS_DOZING 進(jìn)行了設(shè)置司抱。
mDisplayGroupPowerStateMapper.isReady(groupId))判斷 updateDisplayPowerStateLocked 對這個ready 進(jìn)行了設(shè)置
canDreamLocked對dream 的條件進(jìn)行判斷筐眷,主要是一些電量和狀態(tài),開關(guān)习柠,后面有介紹匀谣。
canDozeLocked 對Doz條件的判斷。
startDreaming 是true 的時候 DreamManager來進(jìn)行 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 兩個條件進(jìn)行了設(shè)置武翎。
// 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) {// 記錄當(dāng)前電池水平
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 的時候 設(shè)置成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)) {
// 當(dāng)前 掉電比較快 mDreamsBatteryLevelDrainCutoffConfig 掉電一個標(biāo)記 大于這個值 就要停止掉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 // 設(shè)備支持
|| !mDreamsEnabledSetting // dream開關(guān)開啟
|| !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)) { // 不處于喚醒狀態(tài)
if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) { // 沒充電 電源選項沒配置 不可dream
return false;
}
if (!mIsPowered
&& mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) { // 沒充電 電量過低
return false;
}
// 1 充電 2 dream充電最小電池水平小與0 3 當(dāng)前電量水平大于dream充電最小電池水平 三個 滿足一個是true
return !mIsPowered
|| mDreamsBatteryLevelMinimumWhenPoweredConfig < 0
|| mBatteryLevel >= mDreamsBatteryLevelMinimumWhenPoweredConfig;
}
return true;
}
canDozeLocked 判斷就計較簡單 判斷wakefulness
private boolean canDozeLocked() {
return getWakefulnessLocked() == WAKEFULNESS_DOZING;
}