Android5.1 手机Settings加入从不休眠

时间:2021-11-22 20:35:13

Settings的apk的目录是在packages\apps\Settings下,由于我们添加的从不休眠是在显示项里面,所以我们就直接看DisplaySettings.java的代码了。

    @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Activity activity = getActivity();
final ContentResolver resolver = activity.getContentResolver();
//加入display_settings的Preferences
addPreferencesFromResource(R.xml.display_settings);

mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);
if (mScreenSaverPreference != null
&& getResources().getBoolean(
com.android.internal.R.bool.config_dreamsSupported) == false) {
getPreferenceScreen().removePreference(mScreenSaverPreference);
}
//找到屏幕休眠时间的ListPreference
mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,//从settings数据库中获取屏幕休眠时间
FALLBACK_SCREEN_TIMEOUT_VALUE);
//mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
//
long timeoutValue = (currentTimeout == Integer.MAX_VALUE) ? -1 : currentTimeout;//如果从数据库得到最大值,改成-1
mScreenTimeoutPreference.setValue(String.valueOf(timeoutValue));
//
mScreenTimeoutPreference.setOnPreferenceChangeListener(this);//监听变化
disableUnusableTimeouts(mScreenTimeoutPreference);
//updateTimeoutPreferenceDescription(currentTimeout);
updateTimeoutPreferenceDescription(timeoutValue);//更新屏幕上的信息

我们先看下display_settings.xml文件中screen_timeout这个ListPreference;

        <ListPreference
android:key="screen_timeout"
android:title="@string/screen_timeout"
android:summary="@string/screen_timeout_summary"
android:persistent="false"
android:entries="@array/screen_timeout_entries"
android:entryValues="@array/screen_timeout_values" />

接下来我们看下updateTimeoutPreferenceDescription这个函数,这个函数最后调用preference.setSummary主要更新屏幕上的信息

    private void updateTimeoutPreferenceDescription(long currentTimeout) {
ListPreference preference = mScreenTimeoutPreference;
String summary;
if (currentTimeout == -1) {//如果为-1,string为永不
// Unsupported value
summary = preference.getContext().getString(R.string.screen_never_timeout_summary);
} else if (currentTimeout < -1) {
// Unsupported value
summary = "";
} else {
final CharSequence[] entries = preference.getEntries();
final CharSequence[] values = preference.getEntryValues();
if (entries == null || entries.length == 0) {
summary = "";
} else {
int best = 0;
for (int i = 0; i < values.length; i++) {
long timeout = Long.parseLong(values[i].toString());
/*if (currentTimeout >= timeout) {
best = i;
}*/
if (currentTimeout >= timeout && timeout > 0) {//timeout为了过滤-1
best = i;
}
}
summary = preference.getContext().getString(R.string.screen_timeout_summary,
entries[best]);
}
}
preference.setSummary(summary);
}

先看下R.string.screen_timeout_summary这个string

<string name="screen_timeout_summary" msgid="327761329263064327">"无操作<xliff:g id="TIMEOUT_DESCRIPTION">%1$s</xliff:g>后"</string>

可以看下dream_timeout_entries的xml文件

  <string-array name="dream_timeout_entries">
<item msgid="3149294732238283185">"永不"</item>
<item msgid="2194151041885903260">"15 秒"</item>
<item msgid="5892295237131074341">"30 秒"</item>
<item msgid="3538441365970038213">"1 分钟"</item>
<item msgid="412343871668955639">"2 分钟"</item>
<item msgid="5076853889688991690">"5 分钟"</item>
<item msgid="1903860996174927898">"10 分钟"</item>
<item msgid="6415509612413178727">"30 分钟"</item>
</string-array>

因此两者组合起来会有"无操作5分钟后",这样的效果。


另外onPreferenceChange这个函数,是当你选择选项变化时调用。

    public boolean onPreferenceChange(Preference preference, Object objValue) {
final String key = preference.getKey();
if (KEY_SCREEN_TIMEOUT.equals(key)) {//当时屏幕休眠时间那一项改变
/*try {
int value = Integer.parseInt((String) objValue);
Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
Log.e(TAG, "DisplaySettings:currentTimeout:" + value);
updateTimeoutPreferenceDescription(value);
} catch (NumberFormatException e) {
Log.e(TAG, "could not persist screen timeout setting", e);
}*/
int value = Integer.parseInt((String) objValue);// 先获取值
int oldvalue = Integer.parseInt(((ListPreference)preference).getValue());
if (value != oldvalue) {
int timeoutValue = ( -1 == value) ? Integer.MAX_VALUE : value;//如果值为-1,变为最大值
try {
Log.e(TAG, "timeoutValue is: " + timeoutValue);
Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, timeoutValue);//保存到settings这个数据库中
updateTimeoutPreferenceDescription(value);//更新显示部分
} catch (NumberFormatException e) {
Log.e(TAG, "could not persist screen timeout setting", e);
}
}
}
if (KEY_FONT_SIZE.equals(key)) {
writeFontSizePreference(objValue);
}
if (preference == mAutoBrightnessPreference) {
boolean auto = (Boolean) objValue;
Settings.System.putInt(getContentResolver(), SCREEN_BRIGHTNESS_MODE,
auto ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : SCREEN_BRIGHTNESS_MODE_MANUAL);
}
if (preference == mLiftToWakePreference) {
boolean value = (Boolean) objValue;
Settings.Secure.putInt(getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0);
}
if (preference == mDozePreference) {
boolean value = (Boolean) objValue;
Settings.Secure.putInt(getContentResolver(), DOZE_ENABLED, value ? 1 : 0);
}
return true;
}

我们可以看下screen_timeout_values的xml文件,在最后面添加了一个-1,也就是当选择"永不“的时候会传入一个-1,这时候会变成一个Integer.MAX_VALUE 存数据库。

    <string-array name="screen_timeout_values" translatable="false">
<!-- Do not translate. -->
<item>15000</item>
<!-- Do not translate. -->
<item>30000</item>
<!-- Do not translate. -->
<item>60000</item>
<!-- Do not translate. -->
<item>120000</item>
<!-- Do not translate. -->
<item>300000</item>
<!-- Do not translate. -->
<item>600000</item>
<!-- Do not translate. -->
<item>1800000</item>
<item>-1</item>
</string-array>

这样就完成了在settings中添加永不休眠这个功能。


下面我们再来看下PowerManagerService中如何将settings添加的这个功能生效。

在PowerManagerService中的systemReady函数中注册了对settings数据库SCREEN_OFF_TIMEOUT的监听

            resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
而mSettingsObserver的类如下:

    private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}

@Override
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
handleSettingsChangedLocked();
}
}
}

再看handleSettingsChangedLocked函数:

    private void handleSettingsChangedLocked() {
updateSettingsLocked();
updatePowerStateLocked();
}

    private void updateSettingsLocked() {
final ContentResolver resolver = mContext.getContentResolver();

mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ENABLED,
mDreamsEnabledByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);//获取settings数据库中SCREEN_OFF_TIMEOUT的值

更新了mScreenOffTimeoutSetting之后,会去调用updatePowerStateLocked函数,更新整个PowerManagerService的状态:

通过在updateUserActivitySummaryLocked函数中调用getScreenOffTimeoutLocked函数:

    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;
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
final int sleepTimeout = getSleepTimeoutLocked();
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);//调用getScreenOffTimeoutLocked函数
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);

在getScreenOffTimeoutLocked函数中用mScreenOffTimeoutSetting这个成员变量:

    private int getScreenOffTimeoutLocked(int sleepTimeout) {
int timeout = mScreenOffTimeoutSetting;
if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
}
if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
}
if (sleepTimeout >= 0) {
timeout = Math.min(timeout, sleepTimeout);
}
return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}