blob: 6726c9200a58480a845576d35c243791dac818f5 [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;
27import android.util.Log;
Jason Monk98d7c7a2016-04-12 13:08:31 -040028import com.android.systemui.DemoMode;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070029
30import java.io.FileDescriptor;
31import java.io.PrintWriter;
32import java.util.ArrayList;
33
34/**
35 * Default implementation of a {@link BatteryController}. This controller monitors for battery
36 * level change events that are broadcasted by the system.
37 */
38public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
39 private static final String TAG = "BatteryController";
40
41 public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
42
43 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
44
45 private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
46 private final PowerManager mPowerManager;
47 private final Handler mHandler;
Jason Monk98d7c7a2016-04-12 13:08:31 -040048 private final Context mContext;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070049
50 protected int mLevel;
51 protected boolean mPluggedIn;
52 protected boolean mCharging;
53 protected boolean mCharged;
54 protected boolean mPowerSave;
55 private boolean mTestmode = false;
Jason Monk159dfb72016-09-30 09:41:03 -040056 private boolean mHasReceivedBattery = false;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070057
58 public BatteryControllerImpl(Context context) {
Jason Monk98d7c7a2016-04-12 13:08:31 -040059 mContext = context;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070060 mHandler = new Handler();
61 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
62
Jason Monk98d7c7a2016-04-12 13:08:31 -040063 registerReceiver();
64 updatePowerSave();
65 }
66
67 private void registerReceiver() {
Anthony Chenda62fdcd52016-04-06 16:15:14 -070068 IntentFilter filter = new IntentFilter();
69 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
70 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
71 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
72 filter.addAction(ACTION_LEVEL_TEST);
Jason Monk98d7c7a2016-04-12 13:08:31 -040073 mContext.registerReceiver(this, filter);
Anthony Chenda62fdcd52016-04-06 16:15:14 -070074 }
75
76 @Override
77 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
78 pw.println("BatteryController state:");
79 pw.print(" mLevel="); pw.println(mLevel);
80 pw.print(" mPluggedIn="); pw.println(mPluggedIn);
81 pw.print(" mCharging="); pw.println(mCharging);
82 pw.print(" mCharged="); pw.println(mCharged);
83 pw.print(" mPowerSave="); pw.println(mPowerSave);
84 }
85
86 @Override
87 public void setPowerSaveMode(boolean powerSave) {
88 mPowerManager.setPowerSaveMode(powerSave);
89 }
90
91 @Override
92 public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
Jason Monk324a28f2016-07-12 13:34:12 -040093 synchronized (mChangeCallbacks) {
94 mChangeCallbacks.add(cb);
95 }
Jason Monk159dfb72016-09-30 09:41:03 -040096 if (!mHasReceivedBattery) return;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070097 cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
98 cb.onPowerSaveChanged(mPowerSave);
99 }
100
101 @Override
102 public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
Jason Monk324a28f2016-07-12 13:34:12 -0400103 synchronized (mChangeCallbacks) {
104 mChangeCallbacks.remove(cb);
105 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700106 }
107
108 @Override
109 public void onReceive(final Context context, Intent intent) {
110 final String action = intent.getAction();
111 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
112 if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
Jason Monk159dfb72016-09-30 09:41:03 -0400113 mHasReceivedBattery = true;
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700114 mLevel = (int)(100f
115 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
116 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
117 mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
118
119 final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
120 BatteryManager.BATTERY_STATUS_UNKNOWN);
121 mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
122 mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
123
124 fireBatteryLevelChanged();
125 } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
126 updatePowerSave();
127 } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
128 setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
129 } else if (action.equals(ACTION_LEVEL_TEST)) {
130 mTestmode = true;
131 mHandler.post(new Runnable() {
132 int curLevel = 0;
133 int incr = 1;
134 int saveLevel = mLevel;
135 boolean savePlugged = mPluggedIn;
136 Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
137 @Override
138 public void run() {
139 if (curLevel < 0) {
140 mTestmode = false;
141 dummy.putExtra("level", saveLevel);
142 dummy.putExtra("plugged", savePlugged);
143 dummy.putExtra("testmode", false);
144 } else {
145 dummy.putExtra("level", curLevel);
146 dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
147 : 0);
148 dummy.putExtra("testmode", true);
149 }
150 context.sendBroadcast(dummy);
151
152 if (!mTestmode) return;
153
154 curLevel += incr;
155 if (curLevel == 100) {
156 incr *= -1;
157 }
158 mHandler.postDelayed(this, 200);
159 }
160 });
161 }
162 }
163
164 @Override
165 public boolean isPowerSave() {
166 return mPowerSave;
167 }
168
169 private void updatePowerSave() {
170 setPowerSave(mPowerManager.isPowerSaveMode());
171 }
172
173 private void setPowerSave(boolean powerSave) {
174 if (powerSave == mPowerSave) return;
175 mPowerSave = powerSave;
176 if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
177 firePowerSaveChanged();
178 }
179
180 protected void fireBatteryLevelChanged() {
Jason Monk324a28f2016-07-12 13:34:12 -0400181 synchronized (mChangeCallbacks) {
182 final int N = mChangeCallbacks.size();
183 for (int i = 0; i < N; i++) {
184 mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
185 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700186 }
187 }
188
189 private void firePowerSaveChanged() {
Jason Monk324a28f2016-07-12 13:34:12 -0400190 synchronized (mChangeCallbacks) {
191 final int N = mChangeCallbacks.size();
192 for (int i = 0; i < N; i++) {
193 mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
194 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700195 }
196 }
Jason Monk98d7c7a2016-04-12 13:08:31 -0400197
198 private boolean mDemoMode;
199
200 @Override
201 public void dispatchDemoCommand(String command, Bundle args) {
202 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
203 mDemoMode = true;
204 mContext.unregisterReceiver(this);
205 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
206 mDemoMode = false;
207 registerReceiver();
208 updatePowerSave();
209 } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
210 String level = args.getString("level");
211 String plugged = args.getString("plugged");
212 if (level != null) {
213 mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
214 }
215 if (plugged != null) {
216 mPluggedIn = Boolean.parseBoolean(plugged);
217 }
218 fireBatteryLevelChanged();
219 }
220 }
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700221}