1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.fuelgauge; 17 18 import android.content.BroadcastReceiver; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.IntentFilter; 22 import android.database.ContentObserver; 23 import android.os.BatteryManager; 24 import android.os.Handler; 25 import android.os.PowerManager; 26 import android.provider.Settings; 27 import android.support.annotation.VisibleForTesting; 28 import android.support.v7.preference.Preference; 29 import android.support.v7.preference.PreferenceScreen; 30 import android.util.Log; 31 import com.android.settings.R; 32 import com.android.settings.Utils; 33 import com.android.settings.core.PreferenceController; 34 import com.android.settings.core.lifecycle.Lifecycle; 35 import com.android.settings.core.lifecycle.LifecycleObserver; 36 import com.android.settings.core.lifecycle.events.OnStart; 37 import com.android.settings.core.lifecycle.events.OnStop; 38 import com.android.settings.dashboard.conditional.BatterySaverCondition; 39 import com.android.settings.dashboard.conditional.ConditionManager; 40 import com.android.settings.widget.MasterSwitchPreference; 41 42 import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGING; 43 44 public class BatterySaverController extends PreferenceController implements 45 Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop { 46 private static final String KEY_BATTERY_SAVER = "battery_saver_summary"; 47 private static final String TAG = "BatterySaverController"; 48 private static final boolean DEBUG = false; 49 50 private final BatteryStateChangeReceiver mBatteryStateChangeReceiver; 51 private final PowerManager mPowerManager; 52 private MasterSwitchPreference mBatterySaverPref; 53 BatterySaverController(Context context, Lifecycle lifecycle)54 public BatterySaverController(Context context, Lifecycle lifecycle) { 55 super(context); 56 57 lifecycle.addObserver(this); 58 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 59 mBatteryStateChangeReceiver = new BatteryStateChangeReceiver(); 60 } 61 62 @Override isAvailable()63 public boolean isAvailable() { 64 return true; 65 } 66 67 @Override getPreferenceKey()68 public String getPreferenceKey() { 69 return KEY_BATTERY_SAVER; 70 } 71 72 @Override displayPreference(PreferenceScreen screen)73 public void displayPreference(PreferenceScreen screen) { 74 super.displayPreference(screen); 75 mBatterySaverPref = (MasterSwitchPreference) screen.findPreference(KEY_BATTERY_SAVER); 76 } 77 78 @Override updateState(Preference preference)79 public void updateState(Preference preference) { 80 mBatterySaverPref.setChecked(mPowerManager.isPowerSaveMode()); 81 updateSummary(); 82 } 83 84 @Override onPreferenceChange(Preference preference, Object newValue)85 public boolean onPreferenceChange(Preference preference, Object newValue) { 86 final boolean saverOn = (Boolean) newValue; 87 if (saverOn != mPowerManager.isPowerSaveMode() 88 && !mPowerManager.setPowerSaveMode(saverOn)) { 89 // Do nothing if power save mode doesn't set correctly 90 return false; 91 } 92 93 refreshConditionManager(); 94 updateSummary(); 95 return true; 96 } 97 98 @Override onStart()99 public void onStart() { 100 mContext.getContentResolver().registerContentObserver( 101 Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL) 102 , true, mObserver); 103 104 mBatteryStateChangeReceiver.setListening(true); 105 } 106 107 @Override onStop()108 public void onStop() { 109 mContext.getContentResolver().unregisterContentObserver(mObserver); 110 mBatteryStateChangeReceiver.setListening(false); 111 } 112 113 @VisibleForTesting refreshConditionManager()114 void refreshConditionManager() { 115 ConditionManager.get(mContext).getCondition(BatterySaverCondition.class).refreshState(); 116 } 117 updateSummary()118 private void updateSummary() { 119 final boolean mode = mPowerManager.isPowerSaveMode(); 120 final int format = mode ? R.string.battery_saver_on_summary 121 : R.string.battery_saver_off_summary; 122 final int percent = Settings.Global.getInt(mContext.getContentResolver(), 123 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0); 124 final int percentFormat = percent > 0 ? R.string.battery_saver_desc_turn_on_auto_pct 125 : R.string.battery_saver_desc_turn_on_auto_never; 126 127 final String summary = mContext.getString(format, mContext.getString(percentFormat, 128 Utils.formatPercentage(percent))); 129 130 mBatterySaverPref.setSummary(summary); 131 } 132 133 private final ContentObserver mObserver = new ContentObserver(new Handler()) { 134 @Override 135 public void onChange(boolean selfChange) { 136 updateSummary(); 137 } 138 }; 139 140 private final class BatteryStateChangeReceiver extends BroadcastReceiver { 141 private boolean mRegistered; 142 143 @Override onReceive(Context context, Intent intent)144 public void onReceive(Context context, Intent intent) { 145 if (DEBUG) { 146 Log.d(TAG, "Received " + intent.getAction()); 147 } 148 final String action = intent.getAction(); 149 if (action.equals(ACTION_POWER_SAVE_MODE_CHANGING)) { 150 mBatterySaverPref.setChecked(mPowerManager.isPowerSaveMode()); 151 updateSummary(); 152 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 153 final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); 154 // disable BSM switch if phone is plugged in or at 100% while plugged in 155 final boolean enabled = !(status == BatteryManager.BATTERY_STATUS_CHARGING 156 || status == BatteryManager.BATTERY_STATUS_FULL); 157 158 mBatterySaverPref.setSwitchEnabled(enabled); 159 } 160 } 161 setListening(boolean listening)162 public void setListening(boolean listening) { 163 if (listening && !mRegistered) { 164 final IntentFilter ifilter = new IntentFilter(); 165 ifilter.addAction(Intent.ACTION_BATTERY_CHANGED); 166 ifilter.addAction(ACTION_POWER_SAVE_MODE_CHANGING); 167 mContext.registerReceiver(this, ifilter); 168 mRegistered = true; 169 } else if (!listening && mRegistered) { 170 mContext.unregisterReceiver(this); 171 mRegistered = false; 172 } 173 } 174 175 } 176 } 177