Android5.1 手機Settings加入從不休眠

Settings的apk的目錄是在packages\apps\Settings下,由於我們添加的從不休眠是在顯示項裏面,所以我們就直接看DisplaySettings.Java的代碼了。

[java] view plain copy
  1. @Override  
  2. public void onCreate(Bundle savedInstanceState) {  
  3.     super.onCreate(savedInstanceState);  
  4.     final Activity activity = getActivity();  
  5.     final ContentResolver resolver = activity.getContentResolver();  
  6. 入display_settings的Preferences  
  7.     addPreferencesFromResource(R.xml.display_settings);  
  8.   
  9.     mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);  
  10.     if (mScreenSaverPreference != null  
  11.             && getResources().getBoolean(  
  12.                     com.android.internal.R.bool.config_dreamsSupported) == false) {  
  13.         getPreferenceScreen().removePreference(mScreenSaverPreference);  
  14.     }  
  15. 到屏幕休眠時間的ListPreference  
  16.     mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);  
  17.     final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,//從settings數據庫中獲取屏幕休眠時間  
  18.             FALLBACK_SCREEN_TIMEOUT_VALUE);  
  19.     //mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));  
  20.     //  
  21.     long timeoutValue = (currentTimeout == Integer.MAX_VALUE) ? -1 : currentTimeout;//如果從數據庫得到最大值,改成-1  
  22.     mScreenTimeoutPreference.setValue(String.valueOf(timeoutValue));  
  23.     //  
  24.     mScreenTimeoutPreference.setOnPreferenceChangeListener(this);//監聽變化  
  25.     disableUnusableTimeouts(mScreenTimeoutPreference);  
  26.     //updateTimeoutPreferenceDescription(currentTimeout);  
  27.     updateTimeoutPreferenceDescription(timeoutValue);//更新屏幕上的信息  

我們先看下display_settings.xml文件中screen_timeout這個ListPreference;

[html] view plain copy
  1. <ListPreference  
  2.         android:key="screen_timeout"  
  3.         android:title="@string/screen_timeout"  
  4.         android:summary="@string/screen_timeout_summary"  
  5.         android:persistent="false"  
  6.         android:entries="@array/screen_timeout_entries"  
  7.         android:entryValues="@array/screen_timeout_values" />  

接下來我們看下updateTimeoutPreferenceDescription這個函數,這個函數最後調用preference.setSummary主要更新屏幕上的信息

[java] view plain copy
  1. private void updateTimeoutPreferenceDescription(long currentTimeout) {  
  2.     ListPreference preference = mScreenTimeoutPreference;  
  3.     String summary;  
  4.     if (currentTimeout == -1) {//如果爲-1,string爲永不  
  5.         // Unsupported value  
  6.         summary = preference.getContext().getString(R.string.screen_never_timeout_summary);  
  7.     } else if (currentTimeout < -1) {  
  8.         // Unsupported value  
  9.         summary = "";  
  10.     } else {  
  11.         final CharSequence[] entries = preference.getEntries();  
  12.         final CharSequence[] values = preference.getEntryValues();  
  13.         if (entries == null || entries.length == 0) {  
  14.             summary = "";  
  15.         } else {  
  16.             int best = 0;  
  17.             for (int i = 0; i < values.length; i++) {  
  18.                 long timeout = Long.parseLong(values[i].toString());  
  19.                 /*if (currentTimeout >= timeout) { 
  20.                     best = i; 
  21.                 }*/  
  22.                 if (currentTimeout >= timeout && timeout > 0) {//timeout爲了過濾-1  
  23.                     best = i;  
  24.                 }  
  25.             }  
  26.             summary = preference.getContext().getString(R.string.screen_timeout_summary,  
  27.                     entries[best]);  
  28.         }  
  29.     }  
  30.     preference.setSummary(summary);  
  31. }  

先看下R.string.screen_timeout_summary這個string

[html] view plain copy
  1. <string name="screen_timeout_summary" msgid="327761329263064327">"無操作<xliff:g id="TIMEOUT_DESCRIPTION">%1$s</xliff:g>後"</string>  

可以看下dream_timeout_entries的xml文件

[html] view plain copy
  1. <string-array name="dream_timeout_entries">  
  2.   <item msgid="3149294732238283185">"永不"</item>  
  3.   <item msgid="2194151041885903260">"15 秒"</item>  
  4.   <item msgid="5892295237131074341">"30 秒"</item>  
  5.   <item msgid="3538441365970038213">"1 分鐘"</item>  
  6.   <item msgid="412343871668955639">"2 分鐘"</item>  
  7.   <item msgid="5076853889688991690">"5 分鐘"</item>  
  8.   <item msgid="1903860996174927898">"10 分鐘"</item>  
  9.   <item msgid="6415509612413178727">"30 分鐘"</item>  
  10. </string-array>  

因此兩者組合起來會有"無操作5分鐘後",這樣的效果。


另外onPreferenceChange這個函數,是當你選擇選項變化時調用。

[java] view plain copy
  1. public boolean onPreferenceChange(Preference preference, Object objValue) {  
  2.     final String key = preference.getKey();  
  3.     if (KEY_SCREEN_TIMEOUT.equals(key)) {//當時屏幕休眠時間那一項改變  
  4.         /*try { 
  5.             int value = Integer.parseInt((String) objValue); 
  6.             Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value); 
  7.             Log.e(TAG, "DisplaySettings:currentTimeout:" + value); 
  8.             updateTimeoutPreferenceDescription(value); 
  9.         } catch (NumberFormatException e) { 
  10.             Log.e(TAG, "could not persist screen timeout setting", e); 
  11.         }*/  
  12.         int value = Integer.parseInt((String) objValue);// 先獲取值  
  13.         int oldvalue = Integer.parseInt(((ListPreference)preference).getValue());  
  14.         if (value != oldvalue) {  
  15.             int timeoutValue = ( -1 == value) ? Integer.MAX_VALUE : value;//如果值爲-1,變爲最大值  
  16.             try {  
  17.                 Log.e(TAG, "timeoutValue is: " + timeoutValue);  
  18.                 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, timeoutValue);//保存到settings這個數據庫中  
  19.                 updateTimeoutPreferenceDescription(value);//更新顯示部分  
  20.             } catch (NumberFormatException e) {  
  21.                 Log.e(TAG, "could not persist screen timeout setting", e);  
  22.             }  
  23.         }  
  24.     }  
  25.     if (KEY_FONT_SIZE.equals(key)) {  
  26.         writeFontSizePreference(objValue);  
  27.     }  
  28.     if (preference == mAutoBrightnessPreference) {  
  29.         boolean auto = (Boolean) objValue;  
  30.         Settings.System.putInt(getContentResolver(), SCREEN_BRIGHTNESS_MODE,  
  31.                 auto ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : SCREEN_BRIGHTNESS_MODE_MANUAL);  
  32.     }  
  33.     if (preference == mLiftToWakePreference) {  
  34.         boolean value = (Boolean) objValue;  
  35.         Settings.Secure.putInt(getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0);  
  36.     }  
  37.     if (preference == mDozePreference) {  
  38.         boolean value = (Boolean) objValue;  
  39.         Settings.Secure.putInt(getContentResolver(), DOZE_ENABLED, value ? 1 : 0);  
  40.     }  
  41.     return true;  
  42. }  

我們可以看下screen_timeout_values的xml文件,在最後面添加了一個-1,也就是當選擇"永不“的時候會傳入一個-1,這時候會變成一個Integer.MAX_VALUE 存數據庫

[html] view plain copy
  1. <string-array name="screen_timeout_values" translatable="false">  
  2.     <!-- Do not translate. -->  
  3.     <item>15000</item>  
  4.     <!-- Do not translate. -->  
  5.     <item>30000</item>  
  6.     <!-- Do not translate. -->  
  7.     <item>60000</item>  
  8.     <!-- Do not translate. -->  
  9.     <item>120000</item>  
  10.     <!-- Do not translate. -->  
  11.     <item>300000</item>  
  12.     <!-- Do not translate. -->  
  13.     <item>600000</item>  
  14.     <!-- Do not translate. -->  
  15.     <item>1800000</item>  
  16.     <item>-1</item>  
  17. </string-array>  

這樣就完成了在settings中添加永不休眠這個功能。


下面我們再來看下PowerManagerService中如何將settings添加的這個功能生效。

在PowerManagerService中的systemReady函數中註冊了對settings數據庫SCREEN_OFF_TIMEOUT的監聽

[java] view plain copy
  1. resolver.registerContentObserver(Settings.System.getUriFor(  
  2.         Settings.System.SCREEN_OFF_TIMEOUT),  
  3.         false, mSettingsObserver, UserHandle.USER_ALL);  
而mSettingsObserver的類如下:

[java] view plain copy
  1. private final class SettingsObserver extends ContentObserver {  
  2.     public SettingsObserver(Handler handler) {  
  3.         super(handler);  
  4.     }  
  5.   
  6.     @Override  
  7.     public void onChange(boolean selfChange, Uri uri) {  
  8.         synchronized (mLock) {  
  9.             handleSettingsChangedLocked();  
  10.         }  
  11.     }  
  12. }  

再看handleSettingsChangedLocked函數:

[java] view plain copy
  1. private void handleSettingsChangedLocked() {  
  2.     updateSettingsLocked();  
  3.     updatePowerStateLocked();  
  4. }  

[java] view plain copy
  1. private void updateSettingsLocked() {  
  2.     final ContentResolver resolver = mContext.getContentResolver();  
  3.   
  4.     mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,  
  5.             Settings.Secure.SCREENSAVER_ENABLED,  
  6.             mDreamsEnabledByDefaultConfig ? 1 : 0,  
  7.             UserHandle.USER_CURRENT) != 0);  
  8.     mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,  
  9.             Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,  
  10.             mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,  
  11.             UserHandle.USER_CURRENT) != 0);  
  12.     mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,  
  13.             Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,  
  14.             mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,  
  15.             UserHandle.USER_CURRENT) != 0);  
  16.     mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,  
  17.             Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,  
  18.             UserHandle.USER_CURRENT);//獲取settings數據庫中SCREEN_OFF_TIMEOUT的值  

更新了mScreenOffTimeoutSetting之後,會去調用updatePowerStateLocked函數,更新整個PowerManagerService的狀態:

通過在updateUserActivitySummaryLocked函數中調用getScreenOffTimeoutLocked函數:

[java] view plain copy
  1. private void updateUserActivitySummaryLocked(long now, int dirty) {  
  2.     // Update the status of the user activity timeout timer.  
  3.     if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY  
  4.             | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {  
  5.         mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);  
  6.   
  7.         long nextTimeout = 0;  
  8.         if (mWakefulness == WAKEFULNESS_AWAKE  
  9.                 || mWakefulness == WAKEFULNESS_DREAMING  
  10.                 || mWakefulness == WAKEFULNESS_DOZING) {  
  11.             final int sleepTimeout = getSleepTimeoutLocked();  
  12.             final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);//調用getScreenOffTimeoutLocked函數  
  13.             final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);  

在getScreenOffTimeoutLocked函數中用mScreenOffTimeoutSetting這個成員變量:



2,若是android5.0的code,請在前面的修改基礎上再修改下面的代碼:

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

 private int getScreenOffTimeoutLocked(int sleepTimeout) {


        if (sleepTimeout >= 0) {
            timeout = Math.min(timeout, sleepTimeout);
            Slog.d("TAG", "..33333333..sendMessageAtTime");

        }

//add_begin

        if(timeout < 0 ){
            timeout = Integer.MAX_VALUE ;

        }

//add_end

        if (mUserActivityTimeoutMin) {
            timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromCMD);
        }
        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
    }

[java] view plain copy
  1. private int getScreenOffTimeoutLocked(int sleepTimeout) {  
  2.     int timeout = mScreenOffTimeoutSetting;  
  3.     if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {  
  4.         timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);  
  5.     }  
  6.     if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {  
  7.         timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);  
  8.     }  
  9.     if (sleepTimeout >= 0) {  
  10.         timeout = Math.min(timeout, sleepTimeout);  
  11.     }  
  12.     return Math.max(timeout, mMinimumScreenOffTimeoutConfig);  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章