屏幕保护有两个设置可选:默认为插入基座充电时
通过DreamBackend启用屏保,并且保存选择的时机
//QSSI.13\packages\apps\Settings\src\com\android\settings\dream\WhenToDreamPicker.java
@Override
protected boolean setDefaultKey(String key) {
mBackend.setWhenToDream(DreamSettings.getSettingFromPrefKey(key));
return true;
}
//QSSI.13\frameworks\base\packages\SettingsLib\src\com\android\settingslib\dream\DreamBackend.java
//启用屏保:
public void startDreaming() {
logd("startDreaming()");
if (mDreamManager == null) {
return;
}
try {
mDreamManager.dream();
} catch (RemoteException e) {
Log.w(TAG, "Failed to dream", e);
}
}
//记录启用时机
public void setWhenToDream(@WhenToDream int whenToDream) {
setEnabled(whenToDream != NEVER);
switch (whenToDream) {
case WHILE_CHARGING:
setActivatedOnDock(false);
setActivatedOnSleep(true);
break;
case WHILE_DOCKED:
setActivatedOnDock(true);
setActivatedOnSleep(false);
break;
case EITHER:
setActivatedOnDock(true);
setActivatedOnSleep(true);
break;
case NEVER:
default:
break;
}
}
public void setActivatedOnDock(boolean value) {
logd("setActivatedOnDock(%s)", value);
setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, value);
}
public void setActivatedOnSleep(boolean value) {
logd("setActivatedOnSleep(%s)", value);
setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, value);
}
DreamBackend是对屏保管理的类,最终会通过IDreamManager来执行到DreamManagerService
启动屏保时,先获取系统安装的所有屏保,通过下列代码可以得到我们自己的开发的屏保
PackageManager pm = mContext.getPackageManager();
Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);
List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,
PackageManager.GET_META_DATA);
然后再将屏保设置我们自己开发的
//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public void setActiveDream(ComponentName dream) {
logd("setActiveDream(%s)", dream);
if (mDreamManager == null)
return;
try {
ComponentName[] dreams = { dream };
mDreamManager.setDreamComponents(dream == null ? null : dreams);
} catch (RemoteException e) {
Log.w(TAG, "Failed to set active dream to " + dream, e);
}
}
如果没有设置,系统会有一个默认的屏保,使用以下方法可以获取默认屏保
//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public ComponentName getDefaultDream() {
if (mDreamManager == null)
return null;
try {
return mDreamManager.getDefaultDreamComponent();
} catch (RemoteException e) {
Log.w(TAG, "Failed to get default dream", e);
return null;
}
}
然后用户有任何操作,屏保都会停止,实现逻辑是在DreamService里面的
//QSSI.13\frameworks\base\core\java\android\service\dreams\DreamService.java
/** {@inheritDoc} */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
// TODO: create more flexible version of mInteractive that allows clicks
// but finish()es on any other kind of activity
if (!mInteractive && event.getActionMasked() == MotionEvent.ACTION_UP) {
if (mDebug) Slog.v(mTag, "Waking up on touchEvent");
wakeUp();
return true;
}
return mWindow.superDispatchTouchEvent(event);
}
public final void wakeUp() {
wakeUp(false);
}
private void wakeUp(boolean fromSystem) {
if (mDebug) {
Slog.v(mTag, "wakeUp(): fromSystem=" + fromSystem + ", mWaking=" + mWaking
+ ", mFinished=" + mFinished);
}
if (!mWaking && !mFinished) {
mWaking = true;
if (mActivity != null) {
// During wake up the activity should be translucent to allow the application
// underneath to start drawing. Normally, the WM animation system takes care of
// this, but here we give the dream application some time to perform a custom exit
// animation. If it uses a view animation, the WM doesn't know about it and can't
// make the activity translucent in the normal way. Therefore, here we ensure that
// the activity is translucent during wake up regardless of what animation is used
// in onWakeUp().
mActivity.convertToTranslucent(null, null);
}
// As a minor optimization, invoke the callback first in case it simply
// calls finish() immediately so there wouldn't be much point in telling
// the system that we are finishing the dream gently.
onWakeUp();
// Now tell the system we are waking gently, unless we already told
// it we were finishing immediately.
if (!fromSystem && !mFinished) {
if (mActivity == null) {
Slog.w(mTag, "WakeUp was called before the dream was attached.");
} else {
try {
mDreamManager.finishSelf(mDreamToken, false /*immediate*/);
} catch (RemoteException ex) {
// system server died
}
}
}
}
}
屏保实现充电显示的逻辑在PowerManagerService里面
//QSSI.13\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
系统设置启用和时机
//是否打开屏保
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ENABLED,
mDreamsEnabledByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
//仅充电时设置此值为1
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
//基座充电时,此值为1
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
PowerManagerService里面主要是处理电源相关的逻辑,所以updatePowerStateLocked()方法会时时调用,更新电源状态,然后根据不同状态进行不同处理
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
mUpdatePowerStateInProgress = true;
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 = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update power state of all PowerGroups.
final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);
// Phase 4: Update dream state (depends on power group ready signal).
updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);
// 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);
mUpdatePowerStateInProgress = false;
}
}
private boolean updateWakefulnessLocked(int dirty) {
....
if (shouldNapAtBedTimeLocked()) {
//判断是否需要屏保
changed = dreamPowerGroupLocked(powerGroup, time,
Process.SYSTEM_UID, /* allowWake= */ false);
}
...
}
@GuardedBy("mLock")
private boolean shouldNapAtBedTimeLocked() {
return mDreamsActivateOnSleepSetting
|| (mDreamsActivateOnDockSetting
&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
在updatePowerStateLocked方法里面,会更新屏保状态,调用updateDreamLocked方法
private void updateDreamLocked(int dirty, boolean powerGroupBecameReady) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED
| DIRTY_ATTENTIVE
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0 || powerGroupBecameReady) {
if (areAllPowerGroupsReadyLocked()) {
scheduleSandmanLocked();
}
}
}
scheduleSandmanLocked方法里面会发送一个消息
private void scheduleSandmanLocked() {
if (!mSandmanScheduled) {
mSandmanScheduled = true;
for (int idx = 0; idx < mPowerGroups.size(); idx++) {
final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
if (powerGroup.supportsSandmanLocked()) {
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
msg.arg1 = powerGroup.getGroupId();
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
}
}
在PowerManagerHandler里面处理MSG_SANDMAN消息
private final class PowerManagerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
case MSG_SANDMAN:
handleSandman(msg.arg1);
break;
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
break;
case MSG_CHECK_FOR_LONG_WAKELOCKS:
checkForLongWakeLocks();
break;
case MSG_ATTENTIVE_TIMEOUT:
handleAttentiveTimeout();
break;
}
return true;
}
}
主要处理逻辑是在handleSandman里面
private void handleSandman(int groupId) { // runs on handler thread
// Handle preconditions.
final boolean startDreaming;
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
if (!mPowerGroups.contains(groupId)) {
// Group has been removed.
return;
}
final PowerGroup powerGroup = mPowerGroups.get(groupId);
wakefulness = powerGroup.getWakefulnessLocked();
// 首先判断是否可以启动屏保
// 如果可以启动屏保且当前锁状态为WAKEFULNESS_NAPPING时,由表示需要启动屏保
if (powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) {
startDreaming = canDreamLocked(powerGroup) || canDozeLocked(powerGroup);
powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ false);
} else {
startDreaming = false;
}
}
// 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(/* immediate= */ false,
"power manager request before starting dream" /*reason*/);
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING,
"power manager request" /*reason*/);
}
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) {
if (!mPowerGroups.contains(groupId)) {
// Group has been removed.
return;
}
// Remember the initial battery level when the dream started.
//如果屏保正在运行且相关设置允许启动屏保,将状态设置为WAKEFULNESS_DREAMING
if (startDreaming && isDreaming) {
mDreamsBatteryLevelDrain = 0;
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).
final PowerGroup powerGroup = mPowerGroups.get(groupId);
if (powerGroup.isSandmanSummonedLocked()
|| powerGroup.getWakefulnessLocked() != wakefulness) {
return; // wait for next cycle
}
....
// Stop dream.
if (isDreaming) {
mDreamManager.stopDream(/* immediate= */ false, "power manager request" /*reason*/);
}
}
从代码可以看出mWakefulness变量与是否启动屏保密切相关,当启动屏保时,mWakefulness状态发生变化
@GuardedBy("mLock")
int recalculateGlobalWakefulnessLocked() {
int deviceWakefulness = WAKEFULNESS_ASLEEP;
for (int i = 0; i < mPowerGroups.size(); i++) {
final int wakefulness = mPowerGroups.valueAt(i).getWakefulnessLocked();
if (wakefulness == WAKEFULNESS_AWAKE) {
return WAKEFULNESS_AWAKE;
} else if (wakefulness == WAKEFULNESS_DREAMING
&& (deviceWakefulness == WAKEFULNESS_ASLEEP
|| deviceWakefulness == WAKEFULNESS_DOZING)) {
//此状态下,屏保会被启动
deviceWakefulness = WAKEFULNESS_DREAMING;
} else if (wakefulness == WAKEFULNESS_DOZING
&& deviceWakefulness == WAKEFULNESS_ASLEEP) {
deviceWakefulness = WAKEFULNESS_DOZING;
}
}
return deviceWakefulness;
}
在停止屏保时,会依次调用handleDreamFinishedLocked –>wakeUpNoUpdateLocked
在wakeUpNoUpdateLocked方法里面,mWakefulness 状态发生变化