Merge "For Auto, display battery status as that of a connected device." into nyc-dev
This commit is contained in:
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.car;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadsetClient;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothProfile.ServiceListener;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A {@link BatteryController} that is specific to the Auto use-case. For Auto, the battery icon
|
||||
* displays the battery status of a device that is connected via bluetooth and not the system's
|
||||
* battery.
|
||||
*/
|
||||
public class CarBatteryController extends BroadcastReceiver implements BatteryController {
|
||||
private static final String TAG = "CarBatteryController";
|
||||
|
||||
// According to the Bluetooth HFP 1.5 specification, battery levels are indicated by a
|
||||
// value from 1-5, where these values represent the following:
|
||||
// 0%% - 0, 1-25%% - 1, 26-50%% - 2, 51-75%% - 3, 76-99%% - 4, 100%% - 5
|
||||
// As a result, set the level as the average within that range.
|
||||
private static final int BATTERY_LEVEL_EMPTY = 0;
|
||||
private static final int BATTERY_LEVEL_1 = 12;
|
||||
private static final int BATTERY_LEVEL_2 = 28;
|
||||
private static final int BATTERY_LEVEL_3 = 63;
|
||||
private static final int BATTERY_LEVEL_4 = 87;
|
||||
private static final int BATTERY_LEVEL_FULL = 100;
|
||||
|
||||
private static final int INVALID_BATTERY_LEVEL = -1;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
private BluetoothHeadsetClient mBluetoothHeadsetClient;
|
||||
|
||||
private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
|
||||
|
||||
private int mLevel;
|
||||
|
||||
/**
|
||||
* An interface indicating the container of a View that will display what the information
|
||||
* in the {@link CarBatteryController}.
|
||||
*/
|
||||
public interface BatteryViewHandler {
|
||||
void hideBatteryView();
|
||||
void showBatteryView();
|
||||
}
|
||||
|
||||
private BatteryViewHandler mBatteryViewHandler;
|
||||
|
||||
public CarBatteryController(Context context) {
|
||||
mContext = context;
|
||||
|
||||
mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener,
|
||||
BluetoothProfile.HEADSET_CLIENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("CarBatteryController state:");
|
||||
pw.print(" mLevel=");
|
||||
pw.println(mLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPowerSaveMode(boolean powerSave) {
|
||||
// No-op. No power save mode for the car.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.add(cb);
|
||||
|
||||
// There is no way to know if the phone is plugged in or charging via bluetooth, so pass
|
||||
// false for these values.
|
||||
cb.onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */);
|
||||
cb.onPowerSaveChanged(false /* isPowerSave */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.remove(cb);
|
||||
}
|
||||
|
||||
public void addBatteryViewHandler(BatteryViewHandler batteryViewHandler) {
|
||||
mBatteryViewHandler = batteryViewHandler;
|
||||
}
|
||||
|
||||
public void startListening() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT);
|
||||
mContext.registerReceiver(this, filter);
|
||||
}
|
||||
|
||||
public void stopListening() {
|
||||
mContext.unregisterReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "onReceive(). action: " + action);
|
||||
}
|
||||
|
||||
if (BluetoothHeadsetClient.ACTION_AG_EVENT.equals(action)) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Received ACTION_AG_EVENT");
|
||||
}
|
||||
|
||||
int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL,
|
||||
INVALID_BATTERY_LEVEL);
|
||||
|
||||
updateBatteryLevel(batteryLevel);
|
||||
|
||||
if (batteryLevel != INVALID_BATTERY_LEVEL && mBatteryViewHandler != null) {
|
||||
mBatteryViewHandler.showBatteryView();
|
||||
}
|
||||
} else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
|
||||
Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED event: "
|
||||
+ oldState + " -> " + newState);
|
||||
|
||||
}
|
||||
BluetoothDevice device =
|
||||
(BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
updateBatteryIcon(device, newState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the battery level to a percentage that can be displayed on-screen and notifies
|
||||
* any {@link BatteryStateChangeCallback}s of this.
|
||||
*/
|
||||
private void updateBatteryLevel(int batteryLevel) {
|
||||
if (batteryLevel == INVALID_BATTERY_LEVEL) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Battery level invalid. Ignoring.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The battery level is a value between 0-5. Let the default battery level be 0.
|
||||
switch (batteryLevel) {
|
||||
case 5:
|
||||
mLevel = BATTERY_LEVEL_FULL;
|
||||
break;
|
||||
case 4:
|
||||
mLevel = BATTERY_LEVEL_4;
|
||||
break;
|
||||
case 3:
|
||||
mLevel = BATTERY_LEVEL_3;
|
||||
break;
|
||||
case 2:
|
||||
mLevel = BATTERY_LEVEL_2;
|
||||
break;
|
||||
case 1:
|
||||
mLevel = BATTERY_LEVEL_1;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
mLevel = BATTERY_LEVEL_EMPTY;
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Battery level: " + batteryLevel + "; setting mLevel as: " + mLevel);
|
||||
}
|
||||
|
||||
notifyBatteryLevelChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display of the battery icon depending on the given connection state from the
|
||||
* given {@link BluetoothDevice}.
|
||||
*/
|
||||
private void updateBatteryIcon(BluetoothDevice device, int newState) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Device connected");
|
||||
}
|
||||
|
||||
if (mBatteryViewHandler != null) {
|
||||
mBatteryViewHandler.showBatteryView();
|
||||
}
|
||||
|
||||
if (mBluetoothHeadsetClient == null || device == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if battery information is available and immediately update.
|
||||
Bundle featuresBundle = mBluetoothHeadsetClient.getCurrentAgEvents(device);
|
||||
if (featuresBundle == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int batteryLevel = featuresBundle.getInt(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL,
|
||||
INVALID_BATTERY_LEVEL);
|
||||
updateBatteryLevel(batteryLevel);
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Device disconnected");
|
||||
}
|
||||
|
||||
if (mBatteryViewHandler != null) {
|
||||
mBatteryViewHandler.hideBatteryView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowerSave() {
|
||||
// Power save is not valid for the car, so always return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
private void notifyBatteryLevelChanged() {
|
||||
for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) {
|
||||
mChangeCallbacks.get(i)
|
||||
.onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */);
|
||||
}
|
||||
}
|
||||
|
||||
private final ServiceListener mHfpServiceListener = new ServiceListener() {
|
||||
@Override
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
if (profile == BluetoothProfile.HEADSET_CLIENT) {
|
||||
mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(int profile) {
|
||||
if (profile == BluetoothProfile.HEADSET_CLIENT) {
|
||||
mBluetoothHeadsetClient = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -22,37 +22,75 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewStub;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.systemui.BatteryMeterView;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.phone.PhoneStatusBar;
|
||||
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
|
||||
/**
|
||||
* A status bar (and navigation bar) tailored for the automotive use case.
|
||||
*/
|
||||
public class CarStatusBar extends PhoneStatusBar {
|
||||
public class CarStatusBar extends PhoneStatusBar implements
|
||||
CarBatteryController.BatteryViewHandler {
|
||||
private static final String TAG = "CarStatusBar";
|
||||
|
||||
private TaskStackListenerImpl mTaskStackListener;
|
||||
|
||||
private CarNavigationBarView mCarNavigationBar;
|
||||
private CarNavigationBarController mController;
|
||||
private FullscreenUserSwitcher mFullscreenUserSwitcher;
|
||||
|
||||
private CarBatteryController mCarBatteryController;
|
||||
private BatteryMeterView mBatteryMeterView;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
mTaskStackListener = new TaskStackListenerImpl();
|
||||
SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
|
||||
registerPackageChangeReceivers();
|
||||
|
||||
mCarBatteryController.startListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
mCarBatteryController.stopListening();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PhoneStatusBarView makeStatusBarView() {
|
||||
PhoneStatusBarView statusBarView = super.makeStatusBarView();
|
||||
|
||||
mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
|
||||
|
||||
// By default, the BatteryMeterView should not be visible. It will be toggled visible
|
||||
// when a device has connected by bluetooth.
|
||||
mBatteryMeterView.setVisibility(View.GONE);
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
|
||||
}
|
||||
|
||||
return statusBarView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BatteryController createBatteryController() {
|
||||
mCarBatteryController = new CarBatteryController(mContext);
|
||||
mCarBatteryController.addBatteryViewHandler(this);
|
||||
return mCarBatteryController;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,6 +123,28 @@ public class CarStatusBar extends PhoneStatusBar {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showBatteryView() {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
|
||||
}
|
||||
|
||||
if (mBatteryMeterView != null) {
|
||||
mBatteryMeterView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBatteryView() {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
|
||||
}
|
||||
|
||||
if (mBatteryMeterView != null) {
|
||||
mBatteryMeterView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
@@ -21,9 +21,7 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.StackId;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
@@ -147,6 +145,7 @@ import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChan
|
||||
import com.android.systemui.statusbar.policy.AccessibilityController;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
|
||||
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
|
||||
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
|
||||
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
|
||||
import com.android.systemui.statusbar.policy.CastControllerImpl;
|
||||
@@ -826,7 +825,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
// Other icons
|
||||
mLocationController = new LocationControllerImpl(mContext,
|
||||
mHandlerThread.getLooper()); // will post a notification
|
||||
mBatteryController = new BatteryController(mContext);
|
||||
mBatteryController = createBatteryController();
|
||||
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
|
||||
@Override
|
||||
public void onPowerSaveChanged(boolean isPowerSave) {
|
||||
@@ -943,6 +942,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
return mStatusBarView;
|
||||
}
|
||||
|
||||
protected BatteryController createBatteryController() {
|
||||
return new BatteryControllerImpl(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reInflateViews() {
|
||||
super.reInflateViews();
|
||||
|
||||
@@ -16,158 +16,33 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BatteryController extends BroadcastReceiver {
|
||||
private static final String TAG = "BatteryController";
|
||||
public interface BatteryController {
|
||||
/**
|
||||
* Prints the current state of the {@link BatteryController} to the given {@link PrintWriter}.
|
||||
*/
|
||||
void dump(FileDescriptor fd, PrintWriter pw, String[] args);
|
||||
|
||||
public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
|
||||
/**
|
||||
* Sets if the current device is in power save mode.
|
||||
*/
|
||||
void setPowerSaveMode(boolean powerSave);
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
/**
|
||||
* Returns {@code true} if the device is currently in power save mode.
|
||||
*/
|
||||
boolean isPowerSave();
|
||||
|
||||
private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
|
||||
private final PowerManager mPowerManager;
|
||||
private final Handler mHandler;
|
||||
void addStateChangedCallback(BatteryStateChangeCallback cb);
|
||||
void removeStateChangedCallback(BatteryStateChangeCallback cb);
|
||||
|
||||
private int mLevel;
|
||||
private boolean mPluggedIn;
|
||||
private boolean mCharging;
|
||||
private boolean mCharged;
|
||||
private boolean mPowerSave;
|
||||
private boolean mTestmode = false;
|
||||
|
||||
public BatteryController(Context context) {
|
||||
mHandler = new Handler();
|
||||
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
|
||||
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
|
||||
filter.addAction(ACTION_LEVEL_TEST);
|
||||
context.registerReceiver(this, filter);
|
||||
|
||||
updatePowerSave();
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("BatteryController state:");
|
||||
pw.print(" mLevel="); pw.println(mLevel);
|
||||
pw.print(" mPluggedIn="); pw.println(mPluggedIn);
|
||||
pw.print(" mCharging="); pw.println(mCharging);
|
||||
pw.print(" mCharged="); pw.println(mCharged);
|
||||
pw.print(" mPowerSave="); pw.println(mPowerSave);
|
||||
}
|
||||
|
||||
public void setPowerSaveMode(boolean powerSave) {
|
||||
mPowerManager.setPowerSaveMode(powerSave);
|
||||
}
|
||||
|
||||
public void addStateChangedCallback(BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.add(cb);
|
||||
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
||||
cb.onPowerSaveChanged(mPowerSave);
|
||||
}
|
||||
|
||||
public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.remove(cb);
|
||||
}
|
||||
|
||||
public void onReceive(final Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
|
||||
if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
|
||||
mLevel = (int)(100f
|
||||
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
|
||||
mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
|
||||
|
||||
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
|
||||
BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
|
||||
mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
|
||||
|
||||
fireBatteryLevelChanged();
|
||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
||||
updatePowerSave();
|
||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
|
||||
setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
|
||||
} else if (action.equals(ACTION_LEVEL_TEST)) {
|
||||
mTestmode = true;
|
||||
mHandler.post(new Runnable() {
|
||||
int curLevel = 0;
|
||||
int incr = 1;
|
||||
int saveLevel = mLevel;
|
||||
boolean savePlugged = mPluggedIn;
|
||||
Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||
@Override
|
||||
public void run() {
|
||||
if (curLevel < 0) {
|
||||
mTestmode = false;
|
||||
dummy.putExtra("level", saveLevel);
|
||||
dummy.putExtra("plugged", savePlugged);
|
||||
dummy.putExtra("testmode", false);
|
||||
} else {
|
||||
dummy.putExtra("level", curLevel);
|
||||
dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
|
||||
: 0);
|
||||
dummy.putExtra("testmode", true);
|
||||
}
|
||||
context.sendBroadcast(dummy);
|
||||
|
||||
if (!mTestmode) return;
|
||||
|
||||
curLevel += incr;
|
||||
if (curLevel == 100) {
|
||||
incr *= -1;
|
||||
}
|
||||
mHandler.postDelayed(this, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPowerSave() {
|
||||
return mPowerSave;
|
||||
}
|
||||
|
||||
private void updatePowerSave() {
|
||||
setPowerSave(mPowerManager.isPowerSaveMode());
|
||||
}
|
||||
|
||||
private void setPowerSave(boolean powerSave) {
|
||||
if (powerSave == mPowerSave) return;
|
||||
mPowerSave = powerSave;
|
||||
if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
|
||||
firePowerSaveChanged();
|
||||
}
|
||||
|
||||
private void fireBatteryLevelChanged() {
|
||||
final int N = mChangeCallbacks.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePowerSaveChanged() {
|
||||
final int N = mChangeCallbacks.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
|
||||
}
|
||||
}
|
||||
|
||||
public interface BatteryStateChangeCallback {
|
||||
/**
|
||||
* A listener that will be notified whenever a change in battery level or power save mode
|
||||
* has occurred.
|
||||
*/
|
||||
interface BatteryStateChangeCallback {
|
||||
void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
|
||||
void onPowerSaveChanged(boolean isPowerSave);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link BatteryController}. This controller monitors for battery
|
||||
* level change events that are broadcasted by the system.
|
||||
*/
|
||||
public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
|
||||
private static final String TAG = "BatteryController";
|
||||
|
||||
public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
|
||||
private final PowerManager mPowerManager;
|
||||
private final Handler mHandler;
|
||||
|
||||
protected int mLevel;
|
||||
protected boolean mPluggedIn;
|
||||
protected boolean mCharging;
|
||||
protected boolean mCharged;
|
||||
protected boolean mPowerSave;
|
||||
private boolean mTestmode = false;
|
||||
|
||||
public BatteryControllerImpl(Context context) {
|
||||
mHandler = new Handler();
|
||||
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
|
||||
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
|
||||
filter.addAction(ACTION_LEVEL_TEST);
|
||||
context.registerReceiver(this, filter);
|
||||
|
||||
updatePowerSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("BatteryController state:");
|
||||
pw.print(" mLevel="); pw.println(mLevel);
|
||||
pw.print(" mPluggedIn="); pw.println(mPluggedIn);
|
||||
pw.print(" mCharging="); pw.println(mCharging);
|
||||
pw.print(" mCharged="); pw.println(mCharged);
|
||||
pw.print(" mPowerSave="); pw.println(mPowerSave);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPowerSaveMode(boolean powerSave) {
|
||||
mPowerManager.setPowerSaveMode(powerSave);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.add(cb);
|
||||
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
||||
cb.onPowerSaveChanged(mPowerSave);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
|
||||
mChangeCallbacks.remove(cb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
|
||||
if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
|
||||
mLevel = (int)(100f
|
||||
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
|
||||
mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
|
||||
|
||||
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
|
||||
BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
|
||||
mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
|
||||
|
||||
fireBatteryLevelChanged();
|
||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
||||
updatePowerSave();
|
||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
|
||||
setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
|
||||
} else if (action.equals(ACTION_LEVEL_TEST)) {
|
||||
mTestmode = true;
|
||||
mHandler.post(new Runnable() {
|
||||
int curLevel = 0;
|
||||
int incr = 1;
|
||||
int saveLevel = mLevel;
|
||||
boolean savePlugged = mPluggedIn;
|
||||
Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||
@Override
|
||||
public void run() {
|
||||
if (curLevel < 0) {
|
||||
mTestmode = false;
|
||||
dummy.putExtra("level", saveLevel);
|
||||
dummy.putExtra("plugged", savePlugged);
|
||||
dummy.putExtra("testmode", false);
|
||||
} else {
|
||||
dummy.putExtra("level", curLevel);
|
||||
dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
|
||||
: 0);
|
||||
dummy.putExtra("testmode", true);
|
||||
}
|
||||
context.sendBroadcast(dummy);
|
||||
|
||||
if (!mTestmode) return;
|
||||
|
||||
curLevel += incr;
|
||||
if (curLevel == 100) {
|
||||
incr *= -1;
|
||||
}
|
||||
mHandler.postDelayed(this, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowerSave() {
|
||||
return mPowerSave;
|
||||
}
|
||||
|
||||
private void updatePowerSave() {
|
||||
setPowerSave(mPowerManager.isPowerSaveMode());
|
||||
}
|
||||
|
||||
private void setPowerSave(boolean powerSave) {
|
||||
if (powerSave == mPowerSave) return;
|
||||
mPowerSave = powerSave;
|
||||
if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
|
||||
firePowerSaveChanged();
|
||||
}
|
||||
|
||||
protected void fireBatteryLevelChanged() {
|
||||
final int N = mChangeCallbacks.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePowerSaveChanged() {
|
||||
final int N = mChangeCallbacks.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user