blob: 7221efab0bb261afc9db58c643149dda10ede374 [file] [log] [blame]
Anthony Chenda62fdcd52016-04-06 16:15:14 -07001/*
2 * Copyright (C) 2016 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
17package com.android.systemui.statusbar.policy;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.os.BatteryManager;
Jason Monk98d7c7a2016-04-12 13:08:31 -040024import android.os.Bundle;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070025import android.os.Handler;
26import android.os.PowerManager;
Lucas Dupin92a62e52018-01-30 17:22:20 -080027import android.os.PowerSaveState;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070028import android.util.Log;
Lucas Dupin92a62e52018-01-30 17:22:20 -080029
30import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki16a0dd22018-03-20 10:40:37 -070031import com.android.settingslib.fuelgauge.BatterySaverUtils;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070032
33import java.io.FileDescriptor;
34import java.io.PrintWriter;
35import java.util.ArrayList;
36
37/**
38 * Default implementation of a {@link BatteryController}. This controller monitors for battery
39 * level change events that are broadcasted by the system.
40 */
41public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
42 private static final String TAG = "BatteryController";
43
44 public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
45
46 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
47
48 private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
49 private final PowerManager mPowerManager;
50 private final Handler mHandler;
Jason Monk98d7c7a2016-04-12 13:08:31 -040051 private final Context mContext;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070052
53 protected int mLevel;
54 protected boolean mPluggedIn;
55 protected boolean mCharging;
56 protected boolean mCharged;
57 protected boolean mPowerSave;
Lucas Dupin92a62e52018-01-30 17:22:20 -080058 protected boolean mAodPowerSave;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070059 private boolean mTestmode = false;
Jason Monk159dfb72016-09-30 09:41:03 -040060 private boolean mHasReceivedBattery = false;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070061
62 public BatteryControllerImpl(Context context) {
Lucas Dupin92a62e52018-01-30 17:22:20 -080063 this(context, context.getSystemService(PowerManager.class));
64 }
65
66 @VisibleForTesting
67 BatteryControllerImpl(Context context, PowerManager powerManager) {
Jason Monk98d7c7a2016-04-12 13:08:31 -040068 mContext = context;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070069 mHandler = new Handler();
Lucas Dupin92a62e52018-01-30 17:22:20 -080070 mPowerManager = powerManager;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070071
Jason Monk98d7c7a2016-04-12 13:08:31 -040072 registerReceiver();
73 updatePowerSave();
74 }
75
76 private void registerReceiver() {
Anthony Chenda62fdcd52016-04-06 16:15:14 -070077 IntentFilter filter = new IntentFilter();
78 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
79 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
80 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
81 filter.addAction(ACTION_LEVEL_TEST);
Jason Monk98d7c7a2016-04-12 13:08:31 -040082 mContext.registerReceiver(this, filter);
Anthony Chenda62fdcd52016-04-06 16:15:14 -070083 }
84
85 @Override
86 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
87 pw.println("BatteryController state:");
88 pw.print(" mLevel="); pw.println(mLevel);
89 pw.print(" mPluggedIn="); pw.println(mPluggedIn);
90 pw.print(" mCharging="); pw.println(mCharging);
91 pw.print(" mCharged="); pw.println(mCharged);
92 pw.print(" mPowerSave="); pw.println(mPowerSave);
93 }
94
95 @Override
96 public void setPowerSaveMode(boolean powerSave) {
Makoto Onuki16a0dd22018-03-20 10:40:37 -070097 BatterySaverUtils.setPowerSaveMode(mContext, powerSave, /*needFirstTimeWarning*/ true);
Anthony Chenda62fdcd52016-04-06 16:15:14 -070098 }
99
100 @Override
Jason Monk88529052016-11-04 13:29:58 -0400101 public void addCallback(BatteryController.BatteryStateChangeCallback cb) {
Jason Monk324a28f2016-07-12 13:34:12 -0400102 synchronized (mChangeCallbacks) {
103 mChangeCallbacks.add(cb);
104 }
Jason Monk159dfb72016-09-30 09:41:03 -0400105 if (!mHasReceivedBattery) return;
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700106 cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
107 cb.onPowerSaveChanged(mPowerSave);
108 }
109
110 @Override
Jason Monk88529052016-11-04 13:29:58 -0400111 public void removeCallback(BatteryController.BatteryStateChangeCallback cb) {
Jason Monk324a28f2016-07-12 13:34:12 -0400112 synchronized (mChangeCallbacks) {
113 mChangeCallbacks.remove(cb);
114 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700115 }
116
117 @Override
118 public void onReceive(final Context context, Intent intent) {
119 final String action = intent.getAction();
120 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
121 if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
Jason Monk159dfb72016-09-30 09:41:03 -0400122 mHasReceivedBattery = true;
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700123 mLevel = (int)(100f
124 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
125 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
126 mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
127
128 final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
129 BatteryManager.BATTERY_STATUS_UNKNOWN);
130 mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
131 mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
132
133 fireBatteryLevelChanged();
134 } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
135 updatePowerSave();
136 } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
137 setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
138 } else if (action.equals(ACTION_LEVEL_TEST)) {
139 mTestmode = true;
140 mHandler.post(new Runnable() {
141 int curLevel = 0;
142 int incr = 1;
143 int saveLevel = mLevel;
144 boolean savePlugged = mPluggedIn;
145 Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
146 @Override
147 public void run() {
148 if (curLevel < 0) {
149 mTestmode = false;
150 dummy.putExtra("level", saveLevel);
151 dummy.putExtra("plugged", savePlugged);
152 dummy.putExtra("testmode", false);
153 } else {
154 dummy.putExtra("level", curLevel);
155 dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
156 : 0);
157 dummy.putExtra("testmode", true);
158 }
159 context.sendBroadcast(dummy);
160
161 if (!mTestmode) return;
162
163 curLevel += incr;
164 if (curLevel == 100) {
165 incr *= -1;
166 }
167 mHandler.postDelayed(this, 200);
168 }
169 });
170 }
171 }
172
173 @Override
174 public boolean isPowerSave() {
175 return mPowerSave;
176 }
177
Lucas Dupin92a62e52018-01-30 17:22:20 -0800178 @Override
179 public boolean isAodPowerSave() {
180 return mAodPowerSave;
181 }
182
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700183 private void updatePowerSave() {
184 setPowerSave(mPowerManager.isPowerSaveMode());
185 }
186
187 private void setPowerSave(boolean powerSave) {
188 if (powerSave == mPowerSave) return;
189 mPowerSave = powerSave;
Lucas Dupin92a62e52018-01-30 17:22:20 -0800190
191 // AOD power saving setting might be different from PowerManager power saving mode.
192 PowerSaveState state = mPowerManager.getPowerSaveState(PowerManager.ServiceType.AOD);
193 mAodPowerSave = state.batterySaverEnabled;
194
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700195 if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
196 firePowerSaveChanged();
197 }
198
199 protected void fireBatteryLevelChanged() {
Jason Monk324a28f2016-07-12 13:34:12 -0400200 synchronized (mChangeCallbacks) {
201 final int N = mChangeCallbacks.size();
202 for (int i = 0; i < N; i++) {
203 mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
204 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700205 }
206 }
207
208 private void firePowerSaveChanged() {
Jason Monk324a28f2016-07-12 13:34:12 -0400209 synchronized (mChangeCallbacks) {
210 final int N = mChangeCallbacks.size();
211 for (int i = 0; i < N; i++) {
212 mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
213 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700214 }
215 }
Jason Monk98d7c7a2016-04-12 13:08:31 -0400216
217 private boolean mDemoMode;
218
219 @Override
220 public void dispatchDemoCommand(String command, Bundle args) {
221 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
222 mDemoMode = true;
223 mContext.unregisterReceiver(this);
224 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
225 mDemoMode = false;
226 registerReceiver();
227 updatePowerSave();
228 } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
Evan Laird706d9682017-05-30 15:03:29 -0400229 String level = args.getString("level");
230 String plugged = args.getString("plugged");
231 String powerSave = args.getString("powersave");
232 if (level != null) {
233 mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
234 }
235 if (plugged != null) {
236 mPluggedIn = Boolean.parseBoolean(plugged);
237 }
238 if (powerSave != null) {
239 mPowerSave = powerSave.equals("true");
240 firePowerSaveChanged();
241 }
Jason Monk98d7c7a2016-04-12 13:08:31 -0400242 fireBatteryLevelChanged();
243 }
244 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700245}