Android PowerManagerService省電模式策略控制
前言
初識(shí)Android PowerManagerService省電模式 讓我們省電模式的概念有了初步的認(rèn)識(shí),
Android PowerManagerService 打開(kāi)省電模式 對(duì)打開(kāi)省電模式的代碼進(jìn)行了分析。
有了前面兩篇文章的基礎(chǔ),現(xiàn)在我們開(kāi)始分析如何控制省電模式策略,請(qǐng)讀者務(wù)必仔細(xì)。
本文涉及的文件如下:
- frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
- frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
監(jiān)聽(tīng)策略改變
// BatterySaverPolicy.java public void systemReady() { ConcurrentUtils.wtfIfLockHeld(TAG, mLock); // 1. 監(jiān)聽(tīng) Global 數(shù)據(jù) // 當(dāng)數(shù)據(jù)改變,回調(diào) onChange() mContentResolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.BATTERY_SAVER_CONSTANTS), false, this); mContentResolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this); // 無(wú)障礙模式相關(guān) final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class); acm.addAccessibilityStateChangeListener(enabled -> mAccessibilityEnabled.update(enabled)); mAccessibilityEnabled.initialize(acm.isEnabled()); // 車(chē)載相關(guān) UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class); uiModeManager.addOnProjectionStateChangedListener(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE, mContext.getMainExecutor(), mOnProjectionStateChangedListener); mAutomotiveProjectionActive.initialize( uiModeManager.getActiveProjectionTypes() != UiModeManager.PROJECTION_TYPE_NONE); // 2. 監(jiān)聽(tīng) Config 表中,命名空間DeviceConfig.NAMESPACE_BATTERY_SAVER下的所有數(shù)據(jù) // 當(dāng)數(shù)據(jù)改變時(shí),回調(diào) onPropertiesChanged() DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_SAVER, mContext.getMainExecutor(), this); // 3. 讀取 Config 表中,命名空間DeviceConfig.NAMESPACE_BATTERY_SAVER下的所有數(shù)據(jù) mLastDeviceConfigProperties = DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER); // 4. 獲取 Global 表中的數(shù)據(jù),并執(zhí)行更新操作 onChange(true, null); }
前兩步是監(jiān)聽(tīng)數(shù)據(jù),只不過(guò)回調(diào)的方式不同,但是最終都是根據(jù)數(shù)據(jù)更新省電模式策略,然后通知監(jiān)聽(tīng)者。
因此本文只分析其中一個(gè)回調(diào) onChange(),而另外一個(gè)回調(diào) onPropertiesChanged() 請(qǐng)讀者自行分析。
DeviceConfig 就是獲取 SettingsProvider 中 Config 表中的數(shù)據(jù),這些數(shù)據(jù)的 KEY 以命名空間開(kāi)頭,然后把所有這些數(shù)據(jù)封裝成一個(gè) DeviceConfig.Properties 對(duì)象。
后兩步,是主動(dòng)獲取一次數(shù)據(jù),然后主動(dòng)觸發(fā)一次 onChange() 回調(diào)。
// BatterySaverPolicy.java public void onChange(boolean selfChange, Uri uri) { refreshSettings(); } private void refreshSettings() { synchronized (mLock) { // 1. 獲取與設(shè)備無(wú)關(guān)的省電模式策略 // 例如,vibration_disabled=true,adjust_brightness_factor=0.5 final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS); // 2. 獲取與設(shè)備相關(guān)的省電模式策略 // 格式為, cpufreq-i=core-number:frequency/...,cpufreq-n=core-number:frequency/... String deviceSpecificSetting = getGlobalSetting( Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS); // 保存與設(shè)備相關(guān)的省電模式策略的KEY值 mDeviceSpecificSettingsSource = Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS; // 3. 如果與設(shè)備相關(guān)的省電策略為空,那么加載 framework-res 的 config.xml 中的配置 config_batterySaverDeviceSpecificConfig if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) { // 配置默認(rèn)也為空 deviceSpecificSetting = mContext.getString(getDeviceSpecificConfigResId()); // 表示是從配置文件中配置的 mDeviceSpecificSettingsSource = "(overlay)"; } // 4. 更新策略 if (!updateConstantsLocked(setting, deviceSpecificSetting)) { // 沒(méi)有變化,就不去執(zhí)行后面的通知監(jiān)聽(tīng)者的操作 return; } } // 5. 如果策略改變,通知監(jiān)聽(tīng)者 maybeNotifyListenersOfPolicyChange(); }
Settings.Global.BATTERY_SAVER_CONSTANTS 保存的是與設(shè)備無(wú)關(guān)的省電策略。例如,這個(gè)字段的值可以為 vibration_disabled=true,adjust_brightness_factor=0.5
,不同的策略通過(guò)逗號(hào)進(jìn)行分隔。從名字可以猜測(cè)出,前一個(gè)省電策略表示關(guān)閉振動(dòng),后一個(gè)省電策略表示屏幕亮度降低一半。
什么叫與設(shè)備無(wú)關(guān)策略?如果這個(gè)省電策略不會(huì)因設(shè)備不同而不同的話(huà),那這個(gè)策略就是與設(shè)備無(wú)關(guān),反之就是與設(shè)備有關(guān)策略。
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS 保存的是與設(shè)備相關(guān)的省點(diǎn)策略,目前只保存 CPU 限頻策略。 這個(gè)字段的值可能為 cpufreq-i=core-number:frequency,cpufreq-n=core-number:frequency
,其中 cpufreq-i 表示交互狀態(tài)下的CPU限頻策略,cpufreq-n 表示非交互狀態(tài)下的CPU限頻策略,core-number 表示 CPU 編號(hào),frequency 表示需要限制的頻率。交互狀態(tài)和非交互狀態(tài)的限頻策略以逗號(hào)進(jìn)行分隔。
當(dāng)然,在省電模式下,不一定只限制一個(gè)CPU的頻率,我們可以使用 / 來(lái)分隔不同的 CPU 限頻策略,例如 cpufreq-i=core-number:frequency/core-number:frequency/core-number:frequency
.
通常,亮屏狀態(tài)下為交互模式,滅屏狀態(tài)下為非交互模式。
從第三步中可以看出,可以在 framework-res 模塊的 config.xml 中配置 CPU 限頻策略。記住這里,不要看完了我一系列的省電模式的文章,最終連 CPU 限頻策略還不會(huì)配置哦!
第四步,會(huì)根據(jù)這些數(shù)據(jù)來(lái)更新省電模式策略。并且,如果省電模式策略改變了,那么還會(huì)執(zhí)行第五步,通知監(jiān)聽(tīng)者。
下面,重點(diǎn)分析第四步和第五步。
更新策略
現(xiàn)在,假設(shè) Settings.Global.BATTERY_SAVER_CONSTANTS 和 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS 保存的數(shù)據(jù)改變了,那么會(huì)調(diào)用 updateConstantsLocked() 更新省電模式策略
// BatterySaverPolicy.java boolean updateConstantsLocked(String setting, String deviceSpecificSetting) { // 如果是null,返回"" setting = TextUtils.emptyIfNull(setting); deviceSpecificSetting = TextUtils.emptyIfNull(deviceSpecificSetting); // 沒(méi)有變化,直接返回 if (setting.equals(mSettings) && deviceSpecificSetting.equals(mDeviceSpecificSettings)) { return false; } // 1. 保存設(shè)置 mSettings = setting; mDeviceSpecificSettings = deviceSpecificSetting; // 2. 根據(jù)配置,創(chuàng)建新的策略 Poilcy p = Policy.fromSettings(setting, deviceSpecificSetting, mLastDeviceConfigProperties, null, DEFAULT_FULL_POLICY); // 3. 更新默認(rèn)的省電模式策略 boolean changed = maybeUpdateDefaultFullPolicy(p); // 忽略 adaptive battery save 功能 mDefaultAdaptivePolicy = Policy.fromSettings("", "", mLastDeviceConfigProperties, KEY_SUFFIX_ADAPTIVE, DEFAULT_ADAPTIVE_POLICY); if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE && !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) { // adaptive policy changed changed = true; } mAdaptivePolicy = mDefaultAdaptivePolicy; // 4. 更新有效的省電模式策略 updatePolicyDependenciesLocked(); // 5. 返回狀態(tài),表示省電模式策略是否改變 return changed; }
第二步,根據(jù)配置的數(shù)據(jù)創(chuàng)建一個(gè)策略,注意最后一個(gè)參數(shù) DEFAULT_FULL_POLICY,它表示默認(rèn)的省電模式策略
// BatterySaverPolicy.java private static Policy fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy) { // 以逗號(hào)為分隔符解析字符串 final KeyValueListParser parser = new KeyValueListParser(','); configSuffix = TextUtils.emptyIfNull(configSuffix); // 1. 首先解析設(shè)備相關(guān)的策略參數(shù) try { parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings); } catch (IllegalArgumentException e) { Slog.wtf(TAG, "Bad device specific battery saver constants: " + deviceSpecificSettings); } // 讀取的值的格式為 core-number:frequency/core-number:frequency/... final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, ""); final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, ""); // 2. 再解析設(shè)備無(wú)關(guān)的策略參數(shù) try { parser.setString(settings == null ? "" : settings); } catch (IllegalArgumentException e) { Slog.wtf(TAG, "Bad battery saver constants: " + settings); } // 策略參數(shù)取值的優(yōu)先級(jí)為: Settings > DeviceConfig > 默認(rèn)省電策略 final float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, properties.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR + configSuffix, defaultPolicy.adjustBrightnessFactor)); final boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED, properties.getBoolean(KEY_ADVERTISE_IS_ENABLED + configSuffix, defaultPolicy.advertiseIsEnabled)); final boolean deferFullBackup = parser.getBoolean(KEY_DEFER_FULL_BACKUP, properties.getBoolean(KEY_DEFER_FULL_BACKUP + configSuffix, defaultPolicy.deferFullBackup)); final boolean deferKeyValueBackup = parser.getBoolean(KEY_DEFER_KEYVALUE_BACKUP, properties.getBoolean(KEY_DEFER_KEYVALUE_BACKUP + configSuffix, defaultPolicy.deferKeyValueBackup)); final boolean disableAnimation = parser.getBoolean(KEY_DISABLE_ANIMATION, properties.getBoolean(KEY_DISABLE_ANIMATION + configSuffix, defaultPolicy.disableAnimation)); final boolean disableAod = parser.getBoolean(KEY_DISABLE_AOD, properties.getBoolean(KEY_DISABLE_AOD + configSuffix, defaultPolicy.disableAod)); final boolean disableLaunchBoost = parser.getBoolean(KEY_DISABLE_LAUNCH_BOOST, properties.getBoolean(KEY_DISABLE_LAUNCH_BOOST + configSuffix, defaultPolicy.disableLaunchBoost)); final boolean disableOptionalSensors = parser.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS, properties.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS + configSuffix, defaultPolicy.disableOptionalSensors)); final boolean disableVibrationConfig = parser.getBoolean(KEY_DISABLE_VIBRATION, properties.getBoolean(KEY_DISABLE_VIBRATION + configSuffix, defaultPolicy.disableVibration)); final boolean enableBrightnessAdjustment = parser.getBoolean( KEY_ENABLE_BRIGHTNESS_ADJUSTMENT, properties.getBoolean(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + configSuffix, defaultPolicy.enableAdjustBrightness)); final boolean enableDataSaver = parser.getBoolean(KEY_ENABLE_DATASAVER, properties.getBoolean(KEY_ENABLE_DATASAVER + configSuffix, defaultPolicy.enableDataSaver)); final boolean enableFirewall = parser.getBoolean(KEY_ENABLE_FIREWALL, properties.getBoolean(KEY_ENABLE_FIREWALL + configSuffix, defaultPolicy.enableFirewall)); final boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE, properties.getBoolean(KEY_ENABLE_NIGHT_MODE + configSuffix, defaultPolicy.enableNightMode)); final boolean enableQuickDoze = parser.getBoolean(KEY_ENABLE_QUICK_DOZE, properties.getBoolean(KEY_ENABLE_QUICK_DOZE + configSuffix, defaultPolicy.enableQuickDoze)); final boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, properties.getBoolean(KEY_FORCE_ALL_APPS_STANDBY + configSuffix, defaultPolicy.forceAllAppsStandby)); final boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, properties.getBoolean(KEY_FORCE_BACKGROUND_CHECK + configSuffix, defaultPolicy.forceBackgroundCheck)); final int locationMode = parser.getInt(KEY_LOCATION_MODE, properties.getInt(KEY_LOCATION_MODE + configSuffix, defaultPolicy.locationMode)); final int soundTriggerMode = parser.getInt(KEY_SOUNDTRIGGER_MODE, properties.getInt(KEY_SOUNDTRIGGER_MODE + configSuffix, defaultPolicy.soundTriggerMode)); // 3. 創(chuàng)建一個(gè)新的策略 return new Policy( adjustBrightnessFactor, advertiseIsEnabled, (new CpuFrequencies()).parseString(cpuFreqInteractive), (new CpuFrequencies()).parseString(cpuFreqNoninteractive), deferFullBackup, deferKeyValueBackup, disableAnimation, disableAod, disableLaunchBoost, disableOptionalSensors, /* disableVibration */ disableVibrationConfig, enableBrightnessAdjustment, enableDataSaver, enableFirewall, enableNightMode, enableQuickDoze, forceAllAppsStandby, forceBackgroundCheck, locationMode, soundTriggerMode ); }
與設(shè)備相關(guān)的省電策略,也就是 CPU 限頻策略,如果空缺,也不會(huì)被任何配置取代。
與設(shè)備無(wú)關(guān)的省電策略,如果某一項(xiàng)空缺,會(huì)依次被 DeviceConfig 和 默認(rèn)的省電策略 DEFAULT_FULL_POLICY 取代。
最終通過(guò)解析的數(shù)據(jù),創(chuàng)建一個(gè)策略 Policy 對(duì)象。
新的策略已經(jīng)創(chuàng)建出來(lái),之后調(diào)用 maybeUpdateDefaultFullPolicy() 更新默認(rèn)的省電策略。
// BatterySaverPolicy.java private boolean maybeUpdateDefaultFullPolicy(Policy p) { boolean fullPolicyChanged = false; if (!mDefaultFullPolicy.equals(p)) { // mFullPolicy 會(huì)被 setFullPolicyLocked() 修改 // 如果 mFullPolicy 與 mDefaultFullPolicy 不同, 那么表示 mFullPolicy 被覆蓋 // 如果相同,表示沒(méi)有被覆蓋 boolean isDefaultFullPolicyOverridden = !mDefaultFullPolicy.equals(mFullPolicy); if (!isDefaultFullPolicyOverridden) { // mFullPolicy 沒(méi)有被覆蓋,就要同步進(jìn)行更新 mFullPolicy = p; // 現(xiàn)在處于省電模式中,需要通知監(jiān)聽(tīng)者 fullPolicyChanged = (mPolicyLevel == POLICY_LEVEL_FULL); } // 更新默認(rèn)的省電模式策略 mDefaultFullPolicy = p; } return fullPolicyChanged; }
mDefaultFullPolicy 代表的就是默認(rèn)的省電策略,這里會(huì)更新它,但是同時(shí),如果 mFullPolicy 沒(méi)有被 setFullPolicyLocked() 修改(源碼設(shè)計(jì)中稱(chēng)之為 overridden),那么也會(huì)同步更新它。
現(xiàn)在默認(rèn)的省點(diǎn)策略已經(jīng)更新,但是要應(yīng)用的最終策略還不是它,需要調(diào)用 updatePolicyDependenciesLocked() 來(lái)根據(jù)情況,更新一個(gè)有效的省點(diǎn)策略
// BatterySaverPolicy.java private void updatePolicyDependenciesLocked() { final Policy rawPolicy = getCurrentRawPolicyLocked(); final int locationMode; invalidatePowerSaveModeCaches(); if (mAutomotiveProjectionActive.get() && rawPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE && rawPolicy.locationMode != PowerManager.LOCATION_MODE_FOREGROUND_ONLY) { // If car projection is enabled, ensure that navigation works. locationMode = PowerManager.LOCATION_MODE_FOREGROUND_ONLY; } else { locationMode = rawPolicy.locationMode; } mEffectivePolicyRaw = new Policy( rawPolicy.adjustBrightnessFactor, rawPolicy.advertiseIsEnabled, rawPolicy.cpuFrequenciesForInteractive, rawPolicy.cpuFrequenciesForNoninteractive, rawPolicy.deferFullBackup, rawPolicy.deferKeyValueBackup, rawPolicy.disableAnimation, rawPolicy.disableAod, rawPolicy.disableLaunchBoost, rawPolicy.disableOptionalSensors, // Don't disable vibration when accessibility is on. rawPolicy.disableVibration && !mAccessibilityEnabled.get(), rawPolicy.enableAdjustBrightness, rawPolicy.enableDataSaver, rawPolicy.enableFirewall, // Don't force night mode when car projection is enabled. rawPolicy.enableNightMode && !mAutomotiveProjectionActive.get(), rawPolicy.enableQuickDoze, rawPolicy.forceAllAppsStandby, rawPolicy.forceBackgroundCheck, locationMode, rawPolicy.soundTriggerMode ); // ... }
很簡(jiǎn)單,根據(jù)是否是車(chē)載項(xiàng)目,以及是否打開(kāi)無(wú)障礙模式,更新有效的省電模式策略 mEffectivePolicyRaw。
通知監(jiān)聽(tīng)者
現(xiàn)在省電策略已經(jīng)更新完畢,如果策略改變了,那么需要通知監(jiān)聽(tīng)者
// BatterySaverPolicy.java private void maybeNotifyListenersOfPolicyChange() { final BatterySaverPolicyListener[] listeners; synchronized (mLock) { if (mPolicyLevel == POLICY_LEVEL_OFF) { // 省電模式?jīng)]有打開(kāi) return; } // Don't call out to listeners with the lock held. listeners = mListeners.toArray(new BatterySaverPolicyListener[mListeners.size()]); } mHandler.post(() -> { for (BatterySaverPolicyListener listener : listeners) { // 通知監(jiān)聽(tīng)者 listener.onBatterySaverPolicyChanged(this); } }); }
目前,省電策略的監(jiān)聽(tīng)者只有一個(gè) BatterySaverController
// BatterySaverController.java public void onBatterySaverPolicyChanged(BatterySaverPolicy policy) { if (!isPolicyEnabled()) { return; // No need to send it if not enabled. } mHandler.postStateChanged(/*sendBroadcast=*/ true, REASON_POLICY_CHANGED); }
最終會(huì)調(diào)用 handleBatterySaverStateChanged()
// BatterySaverController.java void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) { final LowPowerModeListener[] listeners; final boolean enabled; final boolean isInteractive = getPowerManager().isInteractive(); final ArrayMap<String, String> fileValues; synchronized (mLock) { enabled = getFullEnabledLocked() || getAdaptiveEnabledLocked(); mFullPreviouslyEnabled = getFullEnabledLocked(); mAdaptivePreviouslyEnabled = getAdaptiveEnabledLocked(); listeners = mListeners.toArray(new LowPowerModeListener[0]); mIsInteractive = isInteractive; // 1. 獲取CPU限頻策略 if (enabled) { fileValues = mBatterySaverPolicy.getFileValues(isInteractive); } else { fileValues = null; } } final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class); if (pmi != null) { pmi.setPowerMode(Mode.LOW_POWER, isEnabled()); } updateBatterySavingStats(); // 2. 應(yīng)用CPU限頻策略 if (ArrayUtils.isEmpty(fileValues)) { // 如果策略為空,那肯定是關(guān)閉了省電模式,此時(shí)需要恢復(fù)正常的CPU頻率 mFileUpdater.restoreDefault(); } else { // 策略不為空,首先保存節(jié)點(diǎn)中原本的值到 /data/system/battery-saver/default-values.xml,然后向節(jié)點(diǎn)寫(xiě)值 mFileUpdater.writeFiles(fileValues); } if (sendBroadcast) { // 3. 發(fā)送廣播 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); // Send the broadcast to a manifest-registered receiver that is specified in the config. if (getPowerSaveModeChangedListenerPackage().isPresent()) { intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED) .setPackage(getPowerSaveModeChangedListenerPackage().get()) .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } // Send internal version that requires signature permission. intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.DEVICE_POWER); // 4. 通知監(jiān)聽(tīng)者,省電策略已經(jīng)改變 for (LowPowerModeListener listener : listeners) { final PowerSaveState result = mBatterySaverPolicy.getBatterySaverPolicy(listener.getServiceType()); listener.onLowPowerModeChanged(result); } } }
這段代碼,我只分析如何應(yīng)用省電策略。
第一步,是獲取 CPU 限頻策略,以一個(gè) Map 表示,其中 KEY 為 CPU 限頻的節(jié)點(diǎn)路徑,VALUE 為被限制的頻率。
然后第二步是應(yīng)用這個(gè) CPU 限頻策略,其實(shí)就是向節(jié)點(diǎn)寫(xiě)值。 不過(guò)在寫(xiě)值之前,會(huì)先保存節(jié)點(diǎn)中原本的值到 /data/system/battery-saver/default-values.xml 文件中,這個(gè)文件的作用是,當(dāng)關(guān)閉省電模式,會(huì)恢復(fù) CPU 原本的頻率。
最后,通知監(jiān)聽(tīng)者,策略已經(jīng)改變,你們需要做相應(yīng)的適配。這些監(jiān)聽(tīng)者都是系統(tǒng)服務(wù),例如WindowManagerService 就是一個(gè)監(jiān)聽(tīng)者,它會(huì)根據(jù)省電模式策略,決定是否關(guān)閉動(dòng)畫(huà),關(guān)鍵代碼如下:
case NEW_ANIMATOR_SCALE: { // 省電模式下,scale 為 0 float scale = getCurrentAnimatorScale(); // 關(guān)閉 system_server 進(jìn)程的動(dòng)畫(huà) ValueAnimator.setDurationScale(scale); Session session = (Session)msg.obj; if (session != null) { try { session.mCallback.onAnimatorScaleChanged(scale); } catch (RemoteException e) { } } else { ArrayList<IWindowSessionCallback> callbacks = new ArrayList<IWindowSessionCallback>(); synchronized (mGlobalLock) { for (int i=0; i<mSessions.size(); i++) { callbacks.add(mSessions.valueAt(i).mCallback); } } for (int i=0; i<callbacks.size(); i++) { try { // 關(guān)閉 app 進(jìn)程的動(dòng)畫(huà) callbacks.get(i).onAnimatorScaleChanged(scale); } catch (RemoteException e) { } } } break; }
如何配置策略
看完了策略控制的源碼分析,總結(jié)下如何控制策略
- 修改 Settings.Global.BATTERY_SAVER_CONSTANTS 字段值,可以設(shè)置的字參考注釋文檔,或者參考源碼的解析部分。例如
vibration_disabled=true,adjust_brightness_factor=0.5
- 修改 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS字段值,但是這個(gè)只能修改 CPU 限頻策略。例如
cpufreq-i=0:1804810/1:1804900,cpufreq-n=0:1804700/1:1804600
。 - 可以通過(guò) framework-res 的 config.xml 的config_batterySaverDeviceSpecificConfig 配置默認(rèn)的 CPU 限頻策略。但是這個(gè)會(huì)被 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS 覆蓋,在有值的情況下。
結(jié)束
省電模式的文章,到此就結(jié)束了。本來(lái)我還準(zhǔn)備分析省電模式影響的功能,但是由于影響的功能有點(diǎn)多,但是我又無(wú)法精通所有的功能,因此我就不獻(xiàn)丑了去分析了。
在工作中,如果你熟悉的某個(gè)功能模塊,例如 WindowManagerService,它受省電模式影響,我相信,如果你看完我的文章,應(yīng)該能自行分析受影響的功能。
到此這篇關(guān)于Android PowerManagerService省電模式策略控制的文章就介紹到這了,更多相關(guān)Android PowerManagerService 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Kotlin使用flow實(shí)現(xiàn)倒計(jì)時(shí)功能(示例詳解)
這篇文章主要介紹了Kotlin使用flow實(shí)現(xiàn)倒計(jì)時(shí)功能,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02android自定義View實(shí)現(xiàn)手勢(shì)解鎖
這篇文章主要為大家詳細(xì)介紹了android自定義View實(shí)現(xiàn)手勢(shì)解鎖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Kotlin方法與Lambda表達(dá)式實(shí)踐使用介紹
這篇文章主要介紹了Kotlin方法與Lambda表達(dá)式實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09Android自定義View 使用PathMeasure簡(jiǎn)單模仿系統(tǒng)ProgressBar(四)
這篇文章主要為大家詳細(xì)介紹了Android自定義View,使用PathMeasure簡(jiǎn)單模仿系統(tǒng)ProgressBar,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android 組合控件實(shí)現(xiàn)布局的復(fù)用的方法
本篇文章主要介紹了Android 組合控件實(shí)現(xiàn)布局的復(fù)用的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08Android 使用自定義RecyclerView控件實(shí)現(xiàn)Gallery效果
這篇文章主要介紹了Android 使用自定義RecyclerView 實(shí)現(xiàn)Gallery效果,本文給大家簡(jiǎn)單介紹了RecyclerView的基本用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-10-10android中實(shí)現(xiàn)完全退出程序方法(退出所有activity)
這篇文章主要介紹了android中實(shí)現(xiàn)完全退出程序方法(退出所有activity),本文方法是博主個(gè)人使用的一個(gè)方法,據(jù)說(shuō)效果非常好,需要的朋友可以參考下2015-05-05