1/*
2 * Copyright (C) 2010 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;
24import android.os.PowerManager;
25import android.util.Log;
26
27import java.io.FileDescriptor;
28import java.io.PrintWriter;
29import java.util.ArrayList;
30
31public class BatteryController extends BroadcastReceiver {
32    private static final String TAG = "BatteryController";
33    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
34
35    private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
36    private final PowerManager mPowerManager;
37
38    private int mLevel;
39    private boolean mPluggedIn;
40    private boolean mCharging;
41    private boolean mCharged;
42    private boolean mPowerSave;
43
44    public BatteryController(Context context) {
45        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
46
47        IntentFilter filter = new IntentFilter();
48        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
49        filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
50        filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
51        context.registerReceiver(this, filter);
52
53        updatePowerSave();
54    }
55
56    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
57        pw.println("BatteryController state:");
58        pw.print("  mLevel="); pw.println(mLevel);
59        pw.print("  mPluggedIn="); pw.println(mPluggedIn);
60        pw.print("  mCharging="); pw.println(mCharging);
61        pw.print("  mCharged="); pw.println(mCharged);
62        pw.print("  mPowerSave="); pw.println(mPowerSave);
63    }
64
65    public void addStateChangedCallback(BatteryStateChangeCallback cb) {
66        mChangeCallbacks.add(cb);
67        cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
68    }
69
70    public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
71        mChangeCallbacks.remove(cb);
72    }
73
74    public void onReceive(Context context, Intent intent) {
75        final String action = intent.getAction();
76        if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
77            mLevel = (int)(100f
78                    * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
79                    / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
80            mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
81
82            final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
83                    BatteryManager.BATTERY_STATUS_UNKNOWN);
84            mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
85            mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
86
87            fireBatteryLevelChanged();
88        } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
89            updatePowerSave();
90        } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
91            setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
92        }
93    }
94
95    public boolean isPowerSave() {
96        return mPowerSave;
97    }
98
99    private void updatePowerSave() {
100        setPowerSave(mPowerManager.isPowerSaveMode());
101    }
102
103    private void setPowerSave(boolean powerSave) {
104        if (powerSave == mPowerSave) return;
105        mPowerSave = powerSave;
106        if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
107        firePowerSaveChanged();
108    }
109
110    private void fireBatteryLevelChanged() {
111        final int N = mChangeCallbacks.size();
112        for (int i = 0; i < N; i++) {
113            mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
114        }
115    }
116
117    private void firePowerSaveChanged() {
118        final int N = mChangeCallbacks.size();
119        for (int i = 0; i < N; i++) {
120            mChangeCallbacks.get(i).onPowerSaveChanged();
121        }
122    }
123
124    public interface BatteryStateChangeCallback {
125        void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
126        void onPowerSaveChanged();
127    }
128}
129