summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/app/IBatteryService.aidl26
-rw-r--r--core/java/android/app/SystemServiceRegistry.java4
-rw-r--r--core/java/android/os/BatteryManager.java160
-rw-r--r--core/java/android/os/BatteryManagerInternal.java21
-rw-r--r--core/java/android/os/BatteryProperties.java54
-rw-r--r--core/java/android/os/IBatteryPropertiesRegistrar.aidl2
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl15
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java89
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java29
-rw-r--r--core/java/com/android/internal/os/DockBatteryStatsImpl.java56
-rw-r--r--core/res/AndroidManifest.xml9
-rw-r--r--core/res/res/values/cm_strings.xml7
-rw-r--r--packages/SystemUI/res/layout/keyguard_status_bar.xml10
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml9
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml10
-rw-r--r--packages/SystemUI/res/layout/system_icons.xml10
-rw-r--r--packages/SystemUI/res/values/cm_arrays.xml42
-rw-r--r--packages/SystemUI/res/values/cm_strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java38
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/BatteryMeterView.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java30
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java192
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java159
-rw-r--r--services/core/java/com/android/server/BatteryService.java286
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags7
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java114
32 files changed, 1501 insertions, 88 deletions
diff --git a/Android.mk b/Android.mk
index ba8e891..4964a4b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,6 +72,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IAppTask.aidl \
core/java/android/app/ITaskStackListener.aidl \
core/java/android/app/IBackupAgent.aidl \
+ core/java/android/app/IBatteryService.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/IProcessObserver.aidl \
diff --git a/core/java/android/app/IBatteryService.aidl b/core/java/android/app/IBatteryService.aidl
new file mode 100644
index 0000000..196159b
--- /dev/null
+++ b/core/java/android/app/IBatteryService.aidl
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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 android.app;
+
+/**
+ * System private API for talking with the battery service.
+ *
+ * {@hide}
+ */
+interface IBatteryService {
+ boolean isDockBatterySupported();
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3d264c6..34c967f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -254,7 +254,9 @@ final class SystemServiceRegistry {
new StaticServiceFetcher<BatteryManager>() {
@Override
public BatteryManager createService() {
- return new BatteryManager();
+ IBinder b = ServiceManager.getService(Context.BATTERY_SERVICE);
+ IBatteryService service = IBatteryService.Stub.asInterface(b);
+ return new BatteryManager(service);
}});
registerService(Context.NFC_SERVICE, NfcManager.class,
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 1f3e9a7..050820c 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,7 @@
package android.os;
+import android.app.IBatteryService;
import android.content.Context;
import android.os.BatteryProperty;
import android.os.IBatteryPropertiesRegistrar;
@@ -95,6 +97,79 @@ public class BatteryManager {
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock status constant.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_STATUS = "dock_status";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock health constant.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_HEALTH = "dock_health";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * boolean indicating whether a dock battery is present.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_PRESENT = "dock_present";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer field containing the current dock battery level, from 0 to
+ * {@link #EXTRA_SCALE}.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_LEVEL = "dock_level";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the maximum dock battery level.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_SCALE = "dock_scale";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the resource ID of a small status bar icon
+ * indicating the current dock battery state.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_ICON_SMALL = "dock_icon-small";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer indicating whether the device is plugged in to a dock power
+ * source.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_PLUGGED = "dock_plugged";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock battery voltage level.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_VOLTAGE = "dock_voltage";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock battery temperature.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_TEMPERATURE = "dock_temperature";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * String describing the technology of the current dock battery.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_TECHNOLOGY = "dock_technology";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
* Int value set to nonzero if an unsupported charger is attached
* to the device.
* {@hide}
@@ -133,10 +208,23 @@ public class BatteryManager {
/** Power source is wireless. */
public static final int BATTERY_PLUGGED_WIRELESS = 4;
+ // values of the "dock_plugged" field in the ACTION_BATTERY_CHANGED intent.
+ // These must be powers of 2.
+ /** Power source is an DockAC charger.
+ * @hide*/
+ public static final int BATTERY_DOCK_PLUGGED_AC = 1;
+ /** Power source is an DockUSB charger.
+ * @hide*/
+ public static final int BATTERY_DOCK_PLUGGED_USB = 2;
+
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+ /** @hide */
+ public static final int BATTERY_DOCK_PLUGGED_ANY =
+ BATTERY_DOCK_PLUGGED_AC | BATTERY_DOCK_PLUGGED_USB;
+
/**
* Sent when the device's battery has started charging (or has reached full charge
* and the device is on power). This is a good time to do work that you would like to
@@ -191,6 +279,7 @@ public class BatteryManager {
*/
public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5;
+ private final IBatteryService mBatteryService;
private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
@@ -202,6 +291,27 @@ public class BatteryManager {
ServiceManager.getService(BatteryStats.SERVICE_NAME));
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
ServiceManager.getService("batteryproperties"));
+ mBatteryService = null;
+ }
+
+ /** @hide */
+ public BatteryManager(IBatteryService service) {
+ super();
+ mBatteryStats = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
+ ServiceManager.getService("batteryproperties"));
+ mBatteryService = service;
+ }
+
+ /** @hide */
+ public boolean isDockBatterySupported() {
+ try {
+ return mBatteryService != null && mBatteryService.isDockBatterySupported();
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+ return false;
}
/**
@@ -223,8 +333,10 @@ public class BatteryManager {
*
* Returns the requested value, or Long.MIN_VALUE if property not
* supported on this system or on other error.
+ * fromDock determines if the property is query from the normal battery
+ * or the dock battery.
*/
- private long queryProperty(int id) {
+ private long queryProperty(int id, boolean fromDock) {
long ret;
if (mBatteryPropertiesRegistrar == null) {
@@ -234,7 +346,13 @@ public class BatteryManager {
try {
BatteryProperty prop = new BatteryProperty();
- if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)
+ final int callResult;
+ if (!fromDock) {
+ callResult = mBatteryPropertiesRegistrar.getProperty(id, prop);
+ } else {
+ callResult = mBatteryPropertiesRegistrar.getDockProperty(id, prop);
+ }
+ if (callResult == 0)
ret = prop.getLong();
else
ret = Long.MIN_VALUE;
@@ -255,7 +373,7 @@ public class BatteryManager {
* @return the property value, or Integer.MIN_VALUE if not supported.
*/
public int getIntProperty(int id) {
- return (int)queryProperty(id);
+ return (int)queryProperty(id, false);
}
/**
@@ -268,6 +386,40 @@ public class BatteryManager {
* @return the property value, or Long.MIN_VALUE if not supported.
*/
public long getLongProperty(int id) {
- return queryProperty(id);
+ return queryProperty(id, false);
+ }
+
+ /**
+ * Return the value of a dock battery property of integer type. If the
+ * platform does not provide the property queried, this value will
+ * be Integer.MIN_VALUE.
+ *
+ * @param id identifier of the requested property
+ *
+ * @return the property value, or Integer.MIN_VALUE if not supported.
+ * @hide
+ */
+ public int getIntDockProperty(int id) {
+ if (!isDockBatterySupported()) {
+ return Integer.MIN_VALUE;
+ }
+ return (int)queryProperty(id, true);
+ }
+
+ /**
+ * Return the value of a dock battery property of long type If the
+ * platform does not provide the property queried, this value will
+ * be Long.MIN_VALUE.
+ *
+ * @param id identifier of the requested property
+ *
+ * @return the property value, or Long.MIN_VALUE if not supported.
+ * @hide
+ */
+ public long getLongDockProperty(int id) {
+ if (!isDockBatterySupported()) {
+ return Long.MIN_VALUE;
+ }
+ return queryProperty(id, true);
}
}
diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java
index f3a95b9..1abb3d5 100644
--- a/core/java/android/os/BatteryManagerInternal.java
+++ b/core/java/android/os/BatteryManagerInternal.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +44,26 @@ public abstract class BatteryManagerInternal {
public abstract boolean getBatteryLevelLow();
/**
+ * Returns whether dock batteries is supported
+ */
+ public abstract boolean isDockBatterySupported();
+
+ /**
+ * Returns the current dock plug type.
+ */
+ public abstract int getDockPlugType();
+
+ /**
+ * Returns dock battery level as a percentage.
+ */
+ public abstract int getDockBatteryLevel();
+
+ /**
+ * Returns whether we currently consider the dock battery level to be low.
+ */
+ public abstract boolean getDockBatteryLevelLow();
+
+ /**
* Returns a non-zero value if an unsupported charger is attached.
*/
public abstract int getInvalidCharger();
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index 29e868c..cad741a 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -1,4 +1,5 @@
/* Copyright 2013, The Android Open Source Project
+ * Copyright 2016, The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +32,16 @@ public class BatteryProperties implements Parcelable {
public int batteryTemperature;
public String batteryTechnology;
+ public boolean dockBatterySupported;
+ public boolean chargerDockAcOnline;
+ public int dockBatteryStatus;
+ public int dockBatteryHealth;
+ public boolean dockBatteryPresent;
+ public int dockBatteryLevel;
+ public int dockBatteryVoltage;
+ public int dockBatteryTemperature;
+ public String dockBatteryTechnology;
+
public BatteryProperties() {
}
@@ -46,6 +57,16 @@ public class BatteryProperties implements Parcelable {
batteryVoltage = other.batteryVoltage;
batteryTemperature = other.batteryTemperature;
batteryTechnology = other.batteryTechnology;
+
+ dockBatterySupported = other.dockBatterySupported;
+ chargerDockAcOnline = other.chargerDockAcOnline;
+ dockBatteryStatus = other.dockBatteryStatus;
+ dockBatteryHealth = other.dockBatteryHealth;
+ dockBatteryPresent = other.dockBatteryPresent;
+ dockBatteryLevel = other.dockBatteryLevel;
+ dockBatteryVoltage = other.dockBatteryVoltage;
+ dockBatteryTemperature = other.dockBatteryTemperature;
+ dockBatteryTechnology = other.dockBatteryTechnology;
}
/*
@@ -65,6 +86,27 @@ public class BatteryProperties implements Parcelable {
batteryVoltage = p.readInt();
batteryTemperature = p.readInt();
batteryTechnology = p.readString();
+
+ dockBatterySupported = p.readInt() == 1 ? true : false;
+ if (dockBatterySupported) {
+ chargerDockAcOnline = p.readInt() == 1 ? true : false;
+ dockBatteryStatus = p.readInt();
+ dockBatteryHealth = p.readInt();
+ dockBatteryPresent = p.readInt() == 1 ? true : false;
+ dockBatteryLevel = p.readInt();
+ dockBatteryVoltage = p.readInt();
+ dockBatteryTemperature = p.readInt();
+ dockBatteryTechnology = p.readString();
+ } else {
+ chargerDockAcOnline = false;
+ dockBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+ dockBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN;
+ dockBatteryPresent = false;
+ dockBatteryLevel = 0;
+ dockBatteryVoltage = 0;
+ dockBatteryTemperature = 0;
+ dockBatteryTechnology = "";
+ }
}
public void writeToParcel(Parcel p, int flags) {
@@ -79,6 +121,18 @@ public class BatteryProperties implements Parcelable {
p.writeInt(batteryVoltage);
p.writeInt(batteryTemperature);
p.writeString(batteryTechnology);
+
+ p.writeInt(dockBatterySupported ? 1 : 0);
+ if (dockBatterySupported) {
+ p.writeInt(chargerDockAcOnline ? 1 : 0);
+ p.writeInt(dockBatteryStatus);
+ p.writeInt(dockBatteryHealth);
+ p.writeInt(dockBatteryPresent ? 1 : 0);
+ p.writeInt(dockBatteryLevel);
+ p.writeInt(dockBatteryVoltage);
+ p.writeInt(dockBatteryTemperature);
+ p.writeString(dockBatteryTechnology);
+ }
}
public static final Parcelable.Creator<BatteryProperties> CREATOR
diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
index fd01802..43b9650 100644
--- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl
+++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
@@ -1,5 +1,6 @@
/*
** Copyright 2013, The Android Open Source Project
+** Copyright 2016, The CyanogenMod Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -27,4 +28,5 @@ interface IBatteryPropertiesRegistrar {
void registerListener(IBatteryPropertiesListener listener);
void unregisterListener(IBatteryPropertiesListener listener);
int getProperty(in int id, out BatteryProperty prop);
+ int getDockProperty(in int id, out BatteryProperty prop);
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3cddbf6..ba92f48 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -121,4 +122,18 @@ interface IBatteryStats {
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
+
+
+ /** @hide */
+ byte[] getDockStatistics();
+ /** @hide */
+ ParcelFileDescriptor getDockStatisticsStream();
+ /** @hide **/
+ void resetStatistics();
+ /** @hide **/
+ void setDockBatteryState(int status, int health, int plugType, int level, int temp, int volt);
+ /** @hide **/
+ long getAwakeTimeDockBattery();
+ /** @hide **/
+ long getAwakeTimeDockPlugged();
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..54a4e86 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.SensorManager;
import android.net.ConnectivityManager;
+import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.Uid;
import android.os.Bundle;
@@ -61,15 +62,18 @@ public final class BatteryStatsHelper {
private static final String TAG = BatteryStatsHelper.class.getSimpleName();
private static BatteryStats sStatsXfer;
+ private static BatteryStats sDockStatsXfer;
private static Intent sBatteryBroadcastXfer;
private static ArrayMap<File, BatteryStats> sFileXfer = new ArrayMap<>();
final private Context mContext;
+ final private BatteryManager mBatteryService;
final private boolean mCollectBatteryBroadcast;
final private boolean mWifiOnly;
private IBatteryStats mBatteryInfo;
private BatteryStats mStats;
+ private BatteryStats mDockStats;
private Intent mBatteryBroadcast;
private PowerProfile mPowerProfile;
@@ -160,19 +164,28 @@ public final class BatteryStatsHelper {
public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) {
mContext = context;
+ mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE));
mCollectBatteryBroadcast = collectBatteryBroadcast;
mWifiOnly = wifiOnly;
}
public void storeStatsHistoryInFile(String fname) {
+ internalStoreStatsHistoryInFile(getStats(), fname);
+ }
+
+ public void storeDockStatsHistoryInFile(String fname) {
+ internalStoreStatsHistoryInFile(getDockStats(), fname);
+ }
+
+ public void internalStoreStatsHistoryInFile(BatteryStats stats, String fname) {
synchronized (sFileXfer) {
File path = makeFilePath(mContext, fname);
- sFileXfer.put(path, this.getStats());
+ sFileXfer.put(path, stats);
FileOutputStream fout = null;
try {
fout = new FileOutputStream(path);
Parcel hist = Parcel.obtain();
- getStats().writeToParcelWithoutUids(hist, 0);
+ stats.writeToParcelWithoutUids(hist, 0);
byte[] histData = hist.marshall();
fout.write(histData);
} catch (IOException e) {
@@ -229,18 +242,38 @@ public final class BatteryStatsHelper {
/** Clears the current stats and forces recreating for future use. */
public void clearStats() {
mStats = null;
+ mDockStats = null;
+ }
+
+ private void clearAllStats() {
+ clearStats();
+ sStatsXfer = null;
+ sDockStatsXfer = null;
+ sBatteryBroadcastXfer = null;
+ for (File f : sFileXfer.keySet()) {
+ f.delete();
+ }
+ sFileXfer.clear();
}
public BatteryStats getStats() {
if (mStats == null) {
- load();
+ loadStats();
}
return mStats;
}
+ public BatteryStats getDockStats() {
+ if (mDockStats == null) {
+ loadDockStats();
+ }
+ return mDockStats;
+ }
+
public Intent getBatteryBroadcast() {
if (mBatteryBroadcast == null && mCollectBatteryBroadcast) {
- load();
+ loadStats();
+ loadDockStats();
}
return mBatteryBroadcast;
}
@@ -257,6 +290,7 @@ public final class BatteryStatsHelper {
public void create(Bundle icicle) {
if (icicle != null) {
mStats = sStatsXfer;
+ mDockStats = sDockStatsXfer;
mBatteryBroadcast = sBatteryBroadcastXfer;
}
mBatteryInfo = IBatteryStats.Stub.asInterface(
@@ -266,6 +300,7 @@ public final class BatteryStatsHelper {
public void storeState() {
sStatsXfer = mStats;
+ sDockStatsXfer = mDockStats;
sBatteryBroadcastXfer = mBatteryBroadcast;
}
@@ -321,6 +356,7 @@ public final class BatteryStatsHelper {
long rawUptimeUs) {
// Initialize mStats if necessary.
getStats();
+ getDockStats();
mMaxPower = 0;
mMaxRealPower = 0;
@@ -739,7 +775,7 @@ public final class BatteryStatsHelper {
}
}
- private void load() {
+ private void loadStats() {
if (mBatteryInfo == null) {
return;
}
@@ -750,6 +786,26 @@ public final class BatteryStatsHelper {
}
}
+ private void loadDockStats() {
+ if (mBatteryInfo == null) {
+ return;
+ }
+ if (mBatteryService.isDockBatterySupported()) {
+ mDockStats = getDockStats(mBatteryInfo);
+ } else {
+ mDockStats = null;
+ }
+ }
+
+ public void resetStatistics() {
+ try {
+ clearAllStats();
+ mBatteryInfo.resetStatistics();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException:", e);
+ }
+ }
+
private static BatteryStatsImpl getStats(IBatteryStats service) {
try {
ParcelFileDescriptor pfd = service.getStatisticsStream();
@@ -772,4 +828,27 @@ public final class BatteryStatsHelper {
}
return new BatteryStatsImpl();
}
+
+ private static BatteryStatsImpl getDockStats(IBatteryStats service) {
+ try {
+ ParcelFileDescriptor pfd = service.getDockStatisticsStream();
+ if (pfd != null) {
+ FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ try {
+ byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
+ Parcel parcel = Parcel.obtain();
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ BatteryStatsImpl stats = com.android.internal.os.DockBatteryStatsImpl.CREATOR
+ .createFromParcel(parcel);
+ return stats;
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read statistics stream", e);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException:", e);
+ }
+ return new BatteryStatsImpl();
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 64b7768..28cc13f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2007 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +92,7 @@ import java.util.concurrent.locks.ReentrantLock;
* battery life. All times are represented in microseconds except where indicated
* otherwise.
*/
-public final class BatteryStatsImpl extends BatteryStats {
+public class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
public static final boolean DEBUG_ENERGY = false;
@@ -6839,13 +6840,13 @@ public final class BatteryStatsImpl extends BatteryStats {
public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
if (systemDir != null) {
- mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
- new File(systemDir, "batterystats.bin.tmp"));
+ mFile = new JournaledFile(new File(systemDir, getStatsName() + ".bin"),
+ new File(systemDir, getStatsName() + ".bin.tmp"));
} else {
mFile = null;
}
- mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
- mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
+ mCheckinFile = new AtomicFile(new File(systemDir, getStatsName() + "-checkin.bin"));
+ mDailyFile = new AtomicFile(new File(systemDir, getStatsName () + "-daily.xml"));
mExternalSync = externalSync;
mHandler = new MyHandler(handler.getLooper());
mStartCount++;
@@ -6921,6 +6922,16 @@ public final class BatteryStatsImpl extends BatteryStats {
readFromParcel(p);
}
+ /** @hide */
+ protected String getStatsName() {
+ return "batterystats";
+ }
+
+ /** @hide */
+ protected String getLogName() {
+ return "BatteryStats";
+ }
+
public void setPowerProfile(PowerProfile profile) {
synchronized (this) {
mPowerProfile = profile;
@@ -8434,7 +8445,13 @@ public final class BatteryStatsImpl extends BatteryStats {
public void setBatteryStateLocked(int status, int health, int plugType, int level,
int temp, int volt) {
- final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
+ // We need to add a extra check over the status because of dock batteries
+ // PlugType doesn't means that the dock battery is charging (some devices
+ // doesn't charge under dock usb)
+ boolean onBattery = plugType == BATTERY_PLUGGED_NONE &&
+ (status != BatteryManager.BATTERY_STATUS_CHARGING ||
+ status != BatteryManager.BATTERY_STATUS_FULL);
+
final long uptime = SystemClock.uptimeMillis();
final long elapsedRealtime = SystemClock.elapsedRealtime();
if (!mHaveBatteryLevel) {
diff --git a/core/java/com/android/internal/os/DockBatteryStatsImpl.java b/core/java/com/android/internal/os/DockBatteryStatsImpl.java
new file mode 100644
index 0000000..6099ad2
--- /dev/null
+++ b/core/java/com/android/internal/os/DockBatteryStatsImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod 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.internal.os;
+
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.File;
+
+public final class DockBatteryStatsImpl extends BatteryStatsImpl {
+ public DockBatteryStatsImpl() {
+ super();
+ }
+
+ public DockBatteryStatsImpl(Parcel p) {
+ super(p);
+ }
+
+ public DockBatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
+ super(systemDir, handler, externalSync);
+ }
+
+ protected String getStatsName() {
+ return "dockbatterystats";
+ }
+
+ protected String getLogName() {
+ return "DockBatteryStats";
+ }
+
+ public static final Parcelable.Creator<DockBatteryStatsImpl> CREATOR =
+ new Parcelable.Creator<DockBatteryStatsImpl>() {
+ public DockBatteryStatsImpl createFromParcel(Parcel in) {
+ return new DockBatteryStatsImpl(in);
+ }
+
+ public DockBatteryStatsImpl[] newArray(int size) {
+ return new DockBatteryStatsImpl[size];
+ }
+ };
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6ef5bde..7b3738f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2377,6 +2377,15 @@
<permission android:name="android.permission.BATTERY_STATS"
android:protectionLevel="signature|privileged|development" />
+ <!-- Allows an application to reset the device battery statistics.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RESET_BATTERY_STATS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:label="@string/permlab_resetBatteryStats"
+ android:description="@string/permdesc_resetBatteryStats"
+ android:protectionLevel="signature|system|development" />
+
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.
@hide pending API council -->
diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml
index 688b2f9..9b03793 100644
--- a/core/res/res/values/cm_strings.xml
+++ b/core/res/res/values/cm_strings.xml
@@ -225,4 +225,11 @@
<!-- Battery fully charged notification -->
<string name="notify_battery_fully_charged_title">Battery fully charged</string>
<string name="notify_battery_fully_charged_text">Disconnect your device from the charger to improve battery longevity.</string>
+
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose
+ whether they want to allow the application to do this. -->
+ <string name="permlab_resetBatteryStats">reset battery statistics</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose
+ whether they want to allow the application to do this. -->
+ <string name="permdesc_resetBatteryStats">Allows an application to reset the current low-level battery usage data.</string>
</resources>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 6cca05f..fcd7e62 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -62,6 +62,16 @@
android:visibility="gone"
android:textSize="@dimen/battery_level_text_size"
android:importantForAccessibility="noHideDescendants"/>
+ <com.android.systemui.DockBatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:paddingEnd="@dimen/battery_level_padding_end"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:visibility="gone"
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"/>
</LinearLayout>
<com.android.keyguard.CarrierText
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 3bedf3f..51f7df7 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -103,6 +103,15 @@
android:textColor="@color/status_bar_battery_level_text_color"
android:textSize="@dimen/battery_level_text_size" />
+ <com.android.systemui.BatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:textSize="@dimen/battery_level_text_size"
+ android:visibility="gone"/>
+
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 5effca4..a017a2e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -94,6 +94,16 @@
android:textColor="@color/status_bar_battery_level_text_color"
android:textSize="@dimen/battery_level_text_size"
android:importantForAccessibility="noHideDescendants"/>
+ <com.android.systemui.DockBatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_expanded"
+ android:paddingEnd="@dimen/battery_level_padding_end"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"
+ android:visibility="gone"/>
</LinearLayout>
<TextView
diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml
index 8d15898..82e0667 100644
--- a/packages/SystemUI/res/layout/system_icons.xml
+++ b/packages/SystemUI/res/layout/system_icons.xml
@@ -38,4 +38,12 @@
android:layout_width="9.5dp"
android:layout_marginBottom="@dimen/battery_margin_bottom"
android:layout_marginStart="@dimen/signal_cluster_battery_padding"/>
-</LinearLayout> \ No newline at end of file
+
+ <com.android.systemui.DockBatteryMeterView android:id="@+id/dock_battery"
+ android:layout_height="14.5dp"
+ android:layout_width="9.5dp"
+ android:layout_marginBottom="@dimen/battery_margin_bottom"
+ android:layout_marginStart="@dimen/signal_cluster_battery_padding"
+ android:visibility="gone"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values/cm_arrays.xml b/packages/SystemUI/res/values/cm_arrays.xml
index 0664d05..7508a65 100644
--- a/packages/SystemUI/res/values/cm_arrays.xml
+++ b/packages/SystemUI/res/values/cm_arrays.xml
@@ -101,4 +101,46 @@
<item>@string/accessibility_quick_settings_live_display_changed_night</item>
<item>@string/accessibility_quick_settings_live_display_changed_outdoor</item>
</string-array>
+
+ <array name="dockbatterymeter_bolt_points" translatable="false">
+ <item>129</item><item>0</item>
+ <item>199</item><item>0</item>
+ <item>199</item><item>168</item>
+ <item>240</item><item>168</item>
+ <item>240</item><item>0</item>
+ <item>312</item><item>0</item>
+ <item>312</item><item>168</item>
+ <item>441</item><item>168</item>
+ <item>441</item><item>252</item>
+ <item>312</item><item>400</item>
+ <item>286</item><item>400</item>
+ <item>286</item><item>702</item>
+ <item>157</item><item>702</item>
+ <item>154</item><item>400</item>
+ <item>129</item><item>400</item>
+ <item>0</item><item>251</item>
+ <item>0</item><item>168</item>
+ <item>129</item><item>168</item>
+ </array>
+
+ <array name="dockbatterymeter_inverted_bolt_points" translatable="false">
+ <item>0</item><item>154</item>
+ <item>302</item><item>154</item>
+ <item>302</item><item>129</item>
+ <item>451</item><item>0</item>
+ <item>534</item><item>0</item>
+ <item>534</item><item>129</item>
+ <item>702</item><item>129</item>
+ <item>702</item><item>199</item>
+ <item>534</item><item>199</item>
+ <item>534</item><item>265</item>
+ <item>702</item><item>265</item>
+ <item>702</item><item>312</item>
+ <item>534</item><item>312</item>
+ <item>534</item><item>441</item>
+ <item>451</item><item>441</item>
+ <item>302</item><item>312</item>
+ <item>302</item><item>286</item>
+ <item>0</item><item>286</item>
+ </array>
</resources>
diff --git a/packages/SystemUI/res/values/cm_strings.xml b/packages/SystemUI/res/values/cm_strings.xml
index 5cbca44..200a236 100644
--- a/packages/SystemUI/res/values/cm_strings.xml
+++ b/packages/SystemUI/res/values/cm_strings.xml
@@ -261,4 +261,7 @@
<!-- CellularTile data sim not configured state string -->
<string name="data_sim_not_configured">No data SIM</string>
+
+ <!-- Content description of the dock battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_dock_battery_level">Dock battery <xliff:g id="number">%d</xliff:g> percent.</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java
index 4717a0b..247e965 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java
@@ -17,6 +17,7 @@
package com.android.systemui;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryStateRegistar;
import android.content.Context;
import android.content.res.Configuration;
@@ -28,7 +29,10 @@ import java.text.NumberFormat;
public class BatteryLevelTextView extends TextView implements
BatteryController.BatteryStateChangeCallback{
- private BatteryController mBatteryController;
+
+ private BatteryStateRegistar mBatteryStateRegistar;
+ private boolean mBatteryPresent;
+
private boolean mBatteryCharging;
private boolean mForceShow;
private boolean mAttached;
@@ -38,7 +42,9 @@ public class BatteryLevelTextView extends TextView implements
public BatteryLevelTextView(Context context, AttributeSet attrs) {
super(context, attrs);
- mRequestedVisibility = getVisibility();
+ // setBatteryStateRegistar (if called) will made the view visible and ready to be hidden
+ // if the view shouldn't be displayed. Otherwise this view should be hidden from start.
+ mRequestedVisibility = GONE;
}
public void setForceShown(boolean forceShow) {
@@ -46,10 +52,11 @@ public class BatteryLevelTextView extends TextView implements
updateVisibility();
}
- public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
+ public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) {
+ mRequestedVisibility = VISIBLE;
+ mBatteryStateRegistar = batteryStateRegistar;
if (mAttached) {
- mBatteryController.addStateChangedCallback(this);
+ mBatteryStateRegistar.addStateChangedCallback(this);
}
}
@@ -69,10 +76,12 @@ public class BatteryLevelTextView extends TextView implements
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn,
+ boolean charging) {
String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
setText(percentage);
- if (mBatteryCharging != charging) {
+ if (mBatteryPresent != present || mBatteryCharging != charging) {
+ mBatteryPresent = present;
mBatteryCharging = charging;
updateVisibility();
}
@@ -94,8 +103,8 @@ public class BatteryLevelTextView extends TextView implements
public void onAttachedToWindow() {
super.onAttachedToWindow();
- if (mBatteryController != null) {
- mBatteryController.addStateChangedCallback(this);
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
}
mAttached = true;
@@ -106,21 +115,22 @@ public class BatteryLevelTextView extends TextView implements
super.onDetachedFromWindow();
mAttached = false;
- if (mBatteryController != null) {
- mBatteryController.removeStateChangedCallback(this);
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.removeStateChangedCallback(this);
}
}
private void updateVisibility() {
- boolean showNextPercent = mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE
- || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE);
+ boolean showNextPercent = mBatteryPresent && (
+ mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE
+ || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE));
if (mStyle == BatteryController.STYLE_GONE) {
showNextPercent = false;
} else if (mStyle == BatteryController.STYLE_TEXT) {
showNextPercent = true;
}
- if (showNextPercent || mForceShow) {
+ if (mBatteryStateRegistar != null && (showNextPercent || mForceShow)) {
super.setVisibility(mRequestedVisibility);
} else {
super.setVisibility(GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 244b7f7..e606156 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -17,6 +17,7 @@
package com.android.systemui;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryStateRegistar;
import android.animation.ArgbEvaluator;
import android.content.BroadcastReceiver;
@@ -73,6 +74,7 @@ public class BatteryMeterView extends View implements DemoMode,
private final Path mClipPath = new Path();
private final Path mTextPath = new Path();
+ private BatteryStateRegistar mBatteryStateRegistar;
private BatteryController mBatteryController;
private boolean mPowerSaveEnabled;
@@ -92,7 +94,7 @@ public class BatteryMeterView extends View implements DemoMode,
private BatteryMeterDrawable mBatteryMeterDrawable;
private int mIconTint = Color.WHITE;
- private class BatteryTracker extends BroadcastReceiver {
+ protected class BatteryTracker extends BroadcastReceiver {
public static final int UNKNOWN_LEVEL = -1;
// current battery status
@@ -128,7 +130,6 @@ public class BatteryMeterView extends View implements DemoMode,
technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
-
setContentDescription(
context.getString(R.string.accessibility_battery_level, level));
if (mBatteryMeterDrawable != null) {
@@ -193,7 +194,9 @@ public class BatteryMeterView extends View implements DemoMode,
// preload the battery level
mTracker.onReceive(getContext(), sticky);
}
- mBatteryController.addStateChangedCallback(this);
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
mAttached = true;
}
@@ -203,7 +206,9 @@ public class BatteryMeterView extends View implements DemoMode,
mAttached = false;
getContext().unregisterReceiver(mTracker);
- mBatteryController.removeStateChangedCallback(this);
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.removeStateChangedCallback(this);
+ }
}
public BatteryMeterView(Context context) {
@@ -279,20 +284,28 @@ public class BatteryMeterView extends View implements DemoMode,
width = height;
} else if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) {
onSizeChanged(width, height, 0, 0); // Force a size changed event
- } else if (mMeterMode.compareTo(BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) == 0) {
+ } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) {
width = (int)(height * 1.2f);
}
setMeasuredDimension(width, height);
}
+ public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) {
+ mBatteryStateRegistar = batteryStateRegistar;
+ if (!mAttached) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
+ }
+
public void setBatteryController(BatteryController batteryController) {
mBatteryController = batteryController;
mPowerSaveEnabled = mBatteryController.isPowerSave();
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn,
+ boolean charging) {
// TODO: Use this callback instead of own broadcast receiver.
}
@@ -742,9 +755,7 @@ public class BatteryMeterView extends View implements DemoMode,
}
private float[] loadBoltPoints(Resources res) {
- final int[] pts = res.getIntArray((mHorizontal
- ? R.array.batterymeter_inverted_bolt_points
- : R.array.batterymeter_bolt_points));
+ final int[] pts = res.getIntArray(getBoltPointsArrayResource());
int maxX = 0, maxY = 0;
for (int i = 0; i < pts.length; i += 2) {
maxX = Math.max(maxX, pts[i]);
@@ -757,6 +768,12 @@ public class BatteryMeterView extends View implements DemoMode,
}
return ptsF;
}
+
+ protected int getBoltPointsArrayResource() {
+ return mHorizontal
+ ? R.array.batterymeter_inverted_bolt_points
+ : R.array.batterymeter_bolt_points;
+ }
}
protected class CircleBatteryMeterDrawable implements BatteryMeterDrawable {
@@ -858,7 +875,7 @@ public class BatteryMeterView extends View implements DemoMode,
}
private float[] loadBoltPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
+ final int[] pts = res.getIntArray(getBoltPointsArrayResource());
int maxX = 0, maxY = 0;
for (int i = 0; i < pts.length; i += 2) {
maxX = Math.max(maxX, pts[i]);
@@ -872,6 +889,10 @@ public class BatteryMeterView extends View implements DemoMode,
return ptsF;
}
+ protected int getBoltPointsArrayResource() {
+ return R.array.batterymeter_bolt_points;
+ }
+
private void drawCircle(Canvas canvas, BatteryTracker tracker,
float textX, RectF drawRect) {
boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN;
diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java
new file mode 100644
index 0000000..1678e94
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+
+public class DockBatteryLevelTextView extends BatteryLevelTextView {
+
+ public DockBatteryLevelTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setPaintFlags(getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java
new file mode 100755
index 0000000..b80e6d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod 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;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.BatteryManager;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class DockBatteryMeterView extends BatteryMeterView {
+
+ private BatteryManager mBatteryService;
+ private final boolean mSupported;
+
+ private class DockBatteryTracker extends BatteryTracker {
+
+ public DockBatteryTracker() {
+ super();
+ present = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
+
+ if (mSupported) {
+ level = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100));
+
+ present = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false);
+ plugType = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0);
+ // We need to add a extra check over the status because of dock batteries
+ // PlugType doesn't means that the dock battery is charging (some devices
+ // doesn't charge under dock usb)
+ plugged = plugType != 0 && (status == BatteryManager.BATTERY_STATUS_CHARGING ||
+ status == BatteryManager.BATTERY_STATUS_FULL);
+ health = intent.getIntExtra(BatteryManager.EXTRA_DOCK_HEALTH,
+ BatteryManager.BATTERY_HEALTH_UNKNOWN);
+ status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ technology = intent.getStringExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY);
+ voltage = intent.getIntExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, 0);
+ temperature = intent.getIntExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, 0);
+
+
+ if (present && (mMeterMode != BatteryMeterMode.BATTERY_METER_GONE &&
+ mMeterMode != BatteryMeterMode.BATTERY_METER_TEXT)) {
+ setContentDescription(context.getString(
+ R.string.accessibility_dock_battery_level, level));
+ setVisibility(View.VISIBLE);
+ invalidate();
+ } else {
+ setContentDescription(null);
+ setVisibility(View.GONE);
+ }
+ } else {
+ setContentDescription(null);
+ setVisibility(View.GONE);
+
+ // If dock is not supported then we don't need this receiver anymore
+ getContext().unregisterReceiver(this);
+ }
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ testmode = true;
+ post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = level;
+ int savePlugged = plugType;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ testmode = 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_DOCK_PLUGGED_AC : 0);
+ dummy.putExtra("testmode", true);
+ }
+ getContext().sendBroadcast(dummy);
+
+ if (!testmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ postDelayed(this, 200);
+ }
+ });
+ }
+ }
+ }
+
+ public DockBatteryMeterView(Context context) {
+ this(context, null, 0);
+ }
+
+ public DockBatteryMeterView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DockBatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE));
+ mSupported = mBatteryService.isDockBatterySupported();
+ mDemoTracker = new DockBatteryTracker();
+ mTracker = new DockBatteryTracker();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ // We already unregistered the listener once when we decided
+ // support was absent. Don't do it again.
+ if (mSupported) {
+ super.onDetachedFromWindow();
+ }
+ }
+
+ @Override
+ public void setMode(BatteryMeterMode mode) {
+ super.setMode(mode);
+ int visibility = getVisibility();
+ if (visibility == View.VISIBLE && !mSupported) {
+ setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) {
+ Resources res = mContext.getResources();
+ switch (mode) {
+ case BATTERY_METER_CIRCLE:
+ return new DockCircleBatteryMeterDrawable(res);
+ case BATTERY_METER_ICON_LANDSCAPE:
+ return new DockNormalBatteryMeterDrawable(res, true);
+ case BATTERY_METER_TEXT:
+ case BATTERY_METER_GONE:
+ return null;
+ default:
+ return new DockNormalBatteryMeterDrawable(res, false);
+ }
+ }
+
+ protected class DockNormalBatteryMeterDrawable extends NormalBatteryMeterDrawable {
+
+ public DockNormalBatteryMeterDrawable(Resources res, boolean horizontal) {
+ super(res, horizontal);
+ }
+
+ @Override
+ protected int getBoltPointsArrayResource() {
+ return mHorizontal
+ ? R.array.dockbatterymeter_inverted_bolt_points
+ : R.array.dockbatterymeter_bolt_points;
+ }
+ }
+
+ protected class DockCircleBatteryMeterDrawable extends CircleBatteryMeterDrawable {
+ public DockCircleBatteryMeterDrawable(Resources res) {
+ super(res);
+ }
+
+ @Override
+ protected int getBoltPointsArrayResource() {
+ return R.array.dockbatterymeter_bolt_points;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7524732..ec307de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- *
+ * Copyright (C) 2016 The CyanogenMod 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
@@ -31,8 +31,10 @@ import android.widget.TextView;
import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.BatteryMeterView;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -49,8 +51,8 @@ public class KeyguardStatusBarView extends RelativeLayout {
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
private BatteryLevelTextView mBatteryLevel;
+ private BatteryLevelTextView mDockBatteryLevel;
- private BatteryController mBatteryController;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private int mSystemIconsSwitcherHiddenExpandedMargin;
@@ -69,6 +71,7 @@ public class KeyguardStatusBarView extends RelativeLayout {
mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text);
+ mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text);
mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text);
loadDimens();
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
@@ -110,6 +113,9 @@ public class KeyguardStatusBarView extends RelativeLayout {
removeView(mMultiUserSwitch);
}
mBatteryLevel.setVisibility(View.VISIBLE);
+ if (mDockBatteryLevel != null) {
+ mDockBatteryLevel.setVisibility(View.VISIBLE);
+ }
}
private void updateSystemIconsLayoutParams() {
@@ -130,9 +136,26 @@ public class KeyguardStatusBarView extends RelativeLayout {
}
public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
- mBatteryLevel.setBatteryController(batteryController);
+ BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery));
+ v.setBatteryStateRegistar(batteryController);
+ v.setBatteryController(batteryController);
+ mBatteryLevel.setBatteryStateRegistar(batteryController);
+ }
+
+ public void setDockBatteryController(DockBatteryController dockBatteryController) {
+ DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery));
+ if (dockBatteryController != null) {
+ v.setBatteryStateRegistar(dockBatteryController);
+ mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController);
+ } else {
+ if (v != null ) {
+ removeView(v);
+ }
+ if (mDockBatteryLevel != null) {
+ removeView(mDockBatteryLevel);
+ mDockBatteryLevel = null;
+ }
+ }
}
public void setUserSwitcherController(UserSwitcherController controller) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index a64f6d8..c5e74a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -64,6 +64,7 @@ import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.AsyncTask;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -124,6 +125,7 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.DemoMode;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Prefs;
@@ -160,10 +162,11 @@ import com.android.systemui.statusbar.VisualizerView;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
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.BatteryStateRegistar.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
@@ -297,7 +300,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// These are no longer handled by the policy, because we need custom strategies for them
BluetoothControllerImpl mBluetoothController;
SecurityControllerImpl mSecurityController;
+ BatteryManager mBatteryManager;
BatteryController mBatteryController;
+ DockBatteryController mDockBatteryController;
LocationControllerImpl mLocationController;
NetworkControllerImpl mNetworkController;
HotspotControllerImpl mHotspotController;
@@ -1052,6 +1057,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mLocationController = new LocationControllerImpl(mContext,
mHandlerThread.getLooper()); // will post a notification
}
+ if (mBatteryManager == null) {
+ mBatteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE);
+ }
if (mBatteryController == null) {
mBatteryController = new BatteryController(mContext, mHandler);
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
@@ -1064,7 +1072,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ public void onBatteryLevelChanged(boolean present, int level,
+ boolean pluggedIn, boolean charging) {
// noop
}
@@ -1074,6 +1083,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
});
}
+ if (mBatteryManager.isDockBatterySupported()) {
+ if (mDockBatteryController == null) {
+ mDockBatteryController = new DockBatteryController(mContext, mHandler);
+ }
+ }
if (mNetworkController == null) {
mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
}
@@ -1271,13 +1285,36 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUserInfoController.reloadUserInfo();
mHeader.setBatteryController(mBatteryController);
+
BatteryMeterView batteryMeterView =
((BatteryMeterView) mStatusBarView.findViewById(R.id.battery));
+ batteryMeterView.setBatteryStateRegistar(mBatteryController);
batteryMeterView.setBatteryController(mBatteryController);
batteryMeterView.setAnimationsEnabled(false);
((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text))
- .setBatteryController(mBatteryController);
+ .setBatteryStateRegistar(mBatteryController);
mKeyguardStatusBar.setBatteryController(mBatteryController);
+ mHeader.setDockBatteryController(mDockBatteryController);
+ mKeyguardStatusBar.setDockBatteryController(mDockBatteryController);
+ if (mDockBatteryController != null) {
+ DockBatteryMeterView dockBatteryMeterView =
+ ((DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery));
+ dockBatteryMeterView.setBatteryStateRegistar(mDockBatteryController);
+ ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text))
+ .setBatteryStateRegistar(mDockBatteryController);
+ } else {
+ DockBatteryMeterView dockBatteryMeterView =
+ (DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery);
+ if (dockBatteryMeterView != null) {
+ mStatusBarView.removeView(dockBatteryMeterView);
+ }
+ BatteryLevelTextView dockBatteryLevel =
+ (BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text);
+ if (dockBatteryLevel != null) {
+ mStatusBarView.removeView(dockBatteryLevel);
+ }
+ }
+
mVisualizerView.setKeyguardMonitor(mKeyguardMonitor);
mHeader.setNextAlarmController(mNextAlarmController);
mHeader.setWeatherController(mWeatherController);
@@ -3348,6 +3385,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mBatteryController != null) {
mBatteryController.dump(fd, pw, args);
}
+ if (mDockBatteryController != null) {
+ mDockBatteryController.dump(fd, pw, args);
+ }
if (mNextAlarmController != null) {
mNextAlarmController.dump(fd, pw, args);
}
@@ -3657,6 +3697,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mBatteryController != null) {
mBatteryController.setUserId(mCurrentUserId);
}
+ if (mDockBatteryController != null) {
+ mDockBatteryController.setUserId(mCurrentUserId);
+ }
}
private void resetUserSetupObserver() {
@@ -4184,6 +4227,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (modeChange || command.equals(COMMAND_BATTERY)) {
dispatchDemoCommandToView(command, args, R.id.battery);
+ dispatchDemoCommandToView(command, args, R.id.dock_battery);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
mIconController.dispatchDemoCommand(command, args);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 27c8a4d..339d469 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -17,9 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.AlarmManager;
-import android.app.IUserSwitchObserver;
import android.app.PendingIntent;
import android.content.ContentUris;
import android.content.ContentResolver;
@@ -58,6 +56,7 @@ import android.widget.Toast;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.BatteryMeterView;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.cm.UserContentObserver;
@@ -65,6 +64,7 @@ import com.android.systemui.qs.QSDragPanel;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -108,6 +108,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private ImageView mQsDetailHeaderProgress;
private TextView mEmergencyCallsOnly;
private BatteryLevelTextView mBatteryLevel;
+ private BatteryLevelTextView mDockBatteryLevel;
private TextView mAlarmStatus;
private TextView mWeatherLine1, mWeatherLine2;
private TextView mEditTileDoneText;
@@ -138,7 +139,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private float mAvatarCollapsedScaleFactor;
private ActivityStarter mActivityStarter;
- private BatteryController mBatteryController;
private NextAlarmController mNextAlarmController;
private WeatherController mWeatherController;
private QSDragPanel mQSPanel;
@@ -193,6 +193,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text);
+ mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text);
mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
mAlarmStatus.setOnClickListener(this);
mSignalCluster = findViewById(R.id.signal_cluster);
@@ -340,9 +341,26 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
- mBatteryLevel.setBatteryController(batteryController);
+ BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery));
+ v.setBatteryStateRegistar(batteryController);
+ v.setBatteryController(batteryController);
+ mBatteryLevel.setBatteryStateRegistar(batteryController);
+ }
+
+ public void setDockBatteryController(DockBatteryController dockBatteryController) {
+ DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery));
+ if (dockBatteryController != null) {
+ v.setBatteryStateRegistar(dockBatteryController);
+ mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController);
+ } else {
+ if (v != null) {
+ removeView(v);
+ }
+ if (mDockBatteryLevel != null) {
+ removeView(mDockBatteryLevel);
+ mDockBatteryLevel = null;
+ }
+ }
}
public void setNextAlarmController(NextAlarmController nextAlarmController) {
@@ -414,6 +432,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
mBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded);
mBatteryLevel.setVisibility(View.VISIBLE);
+ if (mDockBatteryLevel != null) {
+ mDockBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded);
+ mDockBatteryLevel.setVisibility(View.VISIBLE);
+ }
}
private void updateSignalClusterDetachment() {
@@ -763,6 +785,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
applyAlpha(mDateExpanded, values.dateExpandedAlpha);
applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
+ if (mDockBatteryLevel != null) {
+ applyAlpha(mDockBatteryLevel, values.batteryLevelAlpha);
+ }
applyAlpha(mSettingsContainer, values.settingsAlpha);
applyAlpha(mWeatherLine1, values.settingsAlpha);
applyAlpha(mWeatherLine2, values.settingsAlpha);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index a154544..c59a0d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -34,7 +34,7 @@ import java.util.ArrayList;
import cyanogenmod.providers.CMSettings;
-public class BatteryController extends BroadcastReceiver {
+public class BatteryController extends BroadcastReceiver implements BatteryStateRegistar {
private static final String TAG = "BatteryController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -52,6 +52,7 @@ public class BatteryController extends BroadcastReceiver {
private final PowerManager mPowerManager;
private int mLevel;
+ private boolean mPresent;
private boolean mPluggedIn;
private boolean mCharging;
private boolean mCharged;
@@ -85,18 +86,21 @@ public class BatteryController extends BroadcastReceiver {
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("BatteryController state:");
pw.print(" mLevel="); pw.println(mLevel);
+ pw.print(" mPresent="); pw.println(mPresent);
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 addStateChangedCallback(BatteryStateChangeCallback cb) {
mChangeCallbacks.add(cb);
- cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
cb.onBatteryStyleChanged(mStyle, mPercentMode);
}
+ @Override
public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
mChangeCallbacks.remove(cb);
}
@@ -107,6 +111,7 @@ public class BatteryController extends BroadcastReceiver {
mLevel = (int)(100f
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+ mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
@@ -140,7 +145,7 @@ public class BatteryController extends BroadcastReceiver {
private void fireBatteryLevelChanged() {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
}
}
@@ -158,12 +163,6 @@ public class BatteryController extends BroadcastReceiver {
}
}
- public interface BatteryStateChangeCallback {
- void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
- void onPowerSaveChanged();
- void onBatteryStyleChanged(int style, int percentMode);
- }
-
private final class SettingsObserver extends ContentObserver {
private ContentResolver mResolver;
private boolean mRegistered;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java
new file mode 100644
index 0000000..9fe9bb4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod 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;
+
+public interface BatteryStateRegistar {
+ interface BatteryStateChangeCallback {
+ void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, boolean charging);
+ void onPowerSaveChanged();
+ void onBatteryStyleChanged(int style, int percentMode);
+ }
+
+ public void addStateChangedCallback(BatteryStateChangeCallback cb);
+ public void removeStateChangedCallback(BatteryStateChangeCallback cb);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java
new file mode 100644
index 0000000..3faf7d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod 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.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import cyanogenmod.providers.CMSettings;
+
+public class DockBatteryController extends BroadcastReceiver implements BatteryStateRegistar {
+
+ private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+
+ private int mLevel;
+ private boolean mPresent;
+ private boolean mPluggedIn;
+ private boolean mCharging;
+ private boolean mCharged;
+ private boolean mPowerSave;
+
+ private int mStyle;
+ private int mPercentMode;
+ private int mUserId;
+ private SettingsObserver mObserver;
+
+ public DockBatteryController(Context context, Handler handler) {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ context.registerReceiver(this, filter);
+
+ mObserver = new SettingsObserver(context, handler);
+ mObserver.observe();
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ mObserver.observe();
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("BatteryController state:");
+ pw.print(" mLevel="); pw.println(mLevel);
+ pw.print(" mPresent="); pw.println(mPresent);
+ 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 addStateChangedCallback(BatteryStateChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
+ cb.onBatteryStyleChanged(mStyle, mPercentMode);
+ }
+
+ @Override
+ public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ mLevel = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100));
+ mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false);
+ mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0) != 0;
+
+ final int status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
+ mCharging = mPluggedIn && (mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING);
+
+ fireBatteryLevelChanged();
+ }
+ }
+
+ private void fireBatteryLevelChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPresent, mCharging);
+ }
+ }
+
+ private void fireSettingsChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode);
+ }
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private ContentResolver mResolver;
+ private boolean mRegistered;
+
+ private final Uri STYLE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE);
+ private final Uri PERCENT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT);
+
+ public SettingsObserver(Context context, Handler handler) {
+ super(handler);
+ mResolver = context.getContentResolver();
+ }
+
+ public void observe() {
+ if (mRegistered) {
+ mResolver.unregisterContentObserver(this);
+ }
+ mResolver.registerContentObserver(STYLE_URI, false, this, mUserId);
+ mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId);
+ mRegistered = true;
+
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
+
+ private void update() {
+ mStyle = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId);
+ mPercentMode = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId);
+
+ fireSettingsChanged();
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 63c3e97..f20cfe9 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +26,7 @@ import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import android.app.ActivityManagerNative;
+import android.app.IBatteryService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -87,6 +89,21 @@ import cyanogenmod.providers.CMSettings;
* a degree Centigrade</p>
* <p>&quot;technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
*
+ * <p>If a dock battery is present, then this Intent data will be present too related
+ * to dock battery information:</p>
+ * <p>&quot;dock_scale&quot; - int, the maximum value for the charge level</p>
+ * <p>&quot;dock_level&quot; - int, charge level, from 0 through &quot;scale&quot; inclusive</p>
+ * <p>&quot;dock_status&quot; - String, the current charging status.<br />
+ * <p>&quot;dock_health&quot; - String, the current battery health.<br />
+ * <p>&quot;dock_present&quot; - boolean, true if the battery is present<br />
+ * <p>&quot;dock_icon-small&quot; - int, suggested small icon to use for this state</p>
+ * <p>&quot;dock_plugged&quot; - int, 0 if the device is not plugged in; 1 if plugged
+ * into an AC power adapter; 2 if plugged in via USB.</p>
+ * <p>&quot;dock_voltage&quot; - int, current battery voltage in millivolts</p>
+ * <p>&quot;dock_temperature&quot; - int, current battery temperature in tenths of
+ * a degree Centigrade</p>
+ * <p>&quot;dock_technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
+ *
* <p>
* The battery service may be called by the power manager while holding its locks so
* we take care to post all outcalls into the activity manager to a handler.
@@ -135,6 +152,14 @@ public final class BatteryService extends SystemService {
private boolean mLastBatteryLevelCritical;
private int mLastMaxChargingCurrent;
+ private boolean mDockBatterySupported;
+ private int mLastDockBatteryStatus;
+ private int mLastDockBatteryHealth;
+ private boolean mLastDockBatteryPresent;
+ private int mLastDockBatteryLevel;
+ private int mLastDockBatteryVoltage;
+ private int mLastDockBatteryTemperature;
+
private int mInvalidCharger;
private int mLastInvalidCharger;
@@ -150,8 +175,11 @@ public final class BatteryService extends SystemService {
private int mPlugType;
private int mLastPlugType = -1; // Extra state so we can detect first run
+ private int mDockPlugType;
+ private int mLastDockPlugType = -1; // Extra state so we can detect first run
private boolean mBatteryLevelLow;
+ private boolean mDockBatteryLevelLow;
private long mDischargeStartTime;
private int mDischargeStartLevel;
@@ -180,6 +208,10 @@ public final class BatteryService extends SystemService {
mLed = new Led(context, getLocalService(LightsManager.class));
mBatteryStats = BatteryStatsService.getService();
+ // By default dock battery are not supported. The first events will refresh
+ // this status from the battery property bag
+ mDockBatterySupported = false;
+
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
@@ -209,7 +241,7 @@ public final class BatteryService extends SystemService {
// Should never happen.
}
- publishBinderService("battery", new BinderService());
+ publishBinderService(Context.BATTERY_SERVICE, new BinderService());
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
@@ -344,21 +376,31 @@ public final class BatteryService extends SystemService {
boolean logOutlier = false;
long dischargeDuration = 0;
+ mDockBatterySupported = mBatteryProps.dockBatterySupported;
+
mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
+ mPlugType = BATTERY_PLUGGED_NONE;
if (mBatteryProps.chargerAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mBatteryProps.chargerUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
} else if (mBatteryProps.chargerWirelessOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
- } else {
- mPlugType = BATTERY_PLUGGED_NONE;
+ }
+ mDockPlugType = BATTERY_PLUGGED_NONE;
+ if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerAcOnline) {
+ mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_AC;
+ } else if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerUsbOnline) {
+ mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_USB;
}
if (DEBUG) {
- Slog.d(TAG, "Processing new values: "
- + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
- + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+ String msg = "Processing new values: "
+ + "chargerAcOnline=" + mBatteryProps.chargerAcOnline;
+ if (mDockBatterySupported) {
+ msg += ", chargerDockAcOnline=" + mBatteryProps.chargerDockAcOnline;
+ }
+ msg += ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+ ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+ ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
+ ", batteryStatus=" + mBatteryProps.batteryStatus
@@ -368,8 +410,22 @@ public final class BatteryService extends SystemService {
+ ", batteryTechnology=" + mBatteryProps.batteryTechnology
+ ", batteryVoltage=" + mBatteryProps.batteryVoltage
+ ", batteryTemperature=" + mBatteryProps.batteryTemperature
- + ", mBatteryLevelCritical=" + mBatteryLevelCritical
- + ", mPlugType=" + mPlugType);
+ + ", mBatteryLevelCritical=" + mBatteryLevelCritical;
+ if (mDockBatterySupported) {
+ msg += ", dockBatteryStatus=" + mBatteryProps.dockBatteryStatus
+ + ", dockBatteryHealth=" + mBatteryProps.dockBatteryHealth
+ + ", dockBatteryPresent=" + mBatteryProps.dockBatteryPresent
+ + ", dockBatteryLevel=" + mBatteryProps.dockBatteryLevel
+ + ", dockBatteryTechnology=" + mBatteryProps.dockBatteryTechnology
+ + ", dockBatteryVoltage=" + mBatteryProps.dockBatteryVoltage
+ + ", dockBatteryTemperature=" + mBatteryProps.dockBatteryTemperature;
+ }
+ msg += ", mPlugType=" + mPlugType;
+ if (mDockBatterySupported) {
+ msg += ", mDockPlugType=" + mDockPlugType;
+ }
+
+ Slog.d(TAG, msg);
}
// Let the battery stats keep track of the current level.
@@ -380,19 +436,40 @@ public final class BatteryService extends SystemService {
} catch (RemoteException e) {
// Should never happen.
}
+ if (mDockBatterySupported) {
+ try {
+ mBatteryStats.setDockBatteryState(mBatteryProps.dockBatteryStatus,
+ mBatteryProps.dockBatteryHealth, mDockPlugType,
+ mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryTemperature,
+ mBatteryProps.dockBatteryVoltage);
+ } catch (RemoteException e) {
+ // Should never happen.
+ }
+ }
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
- if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+ final boolean batteryChanged = mBatteryProps.batteryStatus != mLastBatteryStatus ||
mBatteryProps.batteryHealth != mLastBatteryHealth ||
mBatteryProps.batteryPresent != mLastBatteryPresent ||
mBatteryProps.batteryLevel != mLastBatteryLevel ||
mPlugType != mLastPlugType ||
mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
- mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
- mInvalidCharger != mLastInvalidCharger)) {
+ mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent;
+
+ final boolean dockBatteryChanged = mDockBatterySupported &&
+ (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus ||
+ mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth ||
+ mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent ||
+ mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel ||
+ mDockPlugType != mLastDockPlugType ||
+ mBatteryProps.dockBatteryVoltage != mLastDockBatteryVoltage ||
+ mBatteryProps.dockBatteryTemperature != mLastDockBatteryTemperature);
+
+ if (force || batteryChanged || dockBatteryChanged ||
+ mInvalidCharger != mLastInvalidCharger) {
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -422,12 +499,30 @@ public final class BatteryService extends SystemService {
mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
mPlugType, mBatteryProps.batteryTechnology);
}
+ if (mDockBatterySupported &&
+ (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus ||
+ mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth ||
+ mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent ||
+ mDockPlugType != mLastDockPlugType)) {
+ EventLog.writeEvent(EventLogTags.DOCK_BATTERY_STATUS,
+ mBatteryProps.dockBatteryStatus, mBatteryProps.dockBatteryHealth,
+ mBatteryProps.dockBatteryPresent ? 1 : 0,
+ mDockPlugType, mBatteryProps.dockBatteryTechnology);
+ }
if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
}
+ if (mDockBatterySupported &&
+ (mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel)) {
+ // Don't do this just from voltage or temperature changes, that is
+ // too noisy.
+ EventLog.writeEvent(EventLogTags.DOCK_BATTERY_LEVEL,
+ mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryVoltage,
+ mBatteryProps.dockBatteryTemperature);
+ }
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
// We want to make sure we log discharge cycle outliers
@@ -454,13 +549,34 @@ public final class BatteryService extends SystemService {
mBatteryLevelLow = false;
}
}
+ if (mDockBatterySupported) {
+ if (!mDockBatteryLevelLow) {
+ // Should we now switch in to low battery mode?
+ if (mDockPlugType == BATTERY_PLUGGED_NONE
+ && mBatteryProps.dockBatteryLevel <= mLowBatteryWarningLevel) {
+ mDockBatteryLevelLow = true;
+ }
+ } else {
+ // Should we now switch out of low battery mode?
+ if (mDockPlugType != BATTERY_PLUGGED_NONE) {
+ mDockBatteryLevelLow = false;
+ } else if (mBatteryProps.dockBatteryLevel >= mLowBatteryCloseWarningLevel) {
+ mDockBatteryLevelLow = false;
+ } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
+ // If being forced, the previous state doesn't matter, we will just
+ // absolutely check to see if we are now above the warning level.
+ mDockBatteryLevelLow = false;
+ }
+ }
+ }
sendIntentLocked();
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
- if (mPlugType != 0 && mLastPlugType == 0) {
+ if (mPlugType != 0 && mLastPlugType == 0 ||
+ (mLastPlugType == 0 && mDockPlugType != 0 && mLastDockPlugType == 0)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -470,7 +586,8 @@ public final class BatteryService extends SystemService {
}
});
}
- else if (mPlugType == 0 && mLastPlugType != 0) {
+ else if (mPlugType == 0 && mLastPlugType != 0 ||
+ (mLastPlugType != 0 && mDockPlugType == 0 && mLastDockPlugType != 0)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -526,6 +643,14 @@ public final class BatteryService extends SystemService {
mLastBatteryTemperature = mBatteryProps.batteryTemperature;
mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
mLastBatteryLevelCritical = mBatteryLevelCritical;
+ mLastDockBatteryStatus = mBatteryProps.dockBatteryStatus;
+ mLastDockBatteryHealth = mBatteryProps.dockBatteryHealth;
+ mLastDockBatteryPresent = mBatteryProps.dockBatteryPresent;
+ mLastDockBatteryLevel = mBatteryProps.dockBatteryLevel;
+ mLastDockPlugType = mDockPlugType;
+ mLastDockBatteryVoltage = mBatteryProps.dockBatteryVoltage;
+ mLastDockBatteryTemperature = mBatteryProps.dockBatteryTemperature;
+
mLastInvalidCharger = mInvalidCharger;
}
}
@@ -537,6 +662,7 @@ public final class BatteryService extends SystemService {
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
int icon = getIconLocked(mBatteryProps.batteryLevel);
+ int dockIcon = 0;
intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
@@ -551,19 +677,62 @@ public final class BatteryService extends SystemService {
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
+ if (mDockBatterySupported) {
+ dockIcon = getDockIconLocked(mBatteryProps.dockBatteryLevel);
+
+ intent.putExtra(BatteryManager.EXTRA_DOCK_STATUS, mBatteryProps.dockBatteryStatus);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_HEALTH, mBatteryProps.dockBatteryHealth);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_PRESENT, mBatteryProps.dockBatteryPresent);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_LEVEL, mBatteryProps.dockBatteryLevel);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_SCALE, BATTERY_SCALE);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_ICON_SMALL, dockIcon);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_PLUGGED, mDockPlugType);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, mBatteryProps.dockBatteryVoltage);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE,
+ mBatteryProps.dockBatteryTemperature);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY,
+ mBatteryProps.dockBatteryTechnology);
+
+ // EEPAD legacy data
+ intent.putExtra("usb_wakeup", mBatteryProps.chargerUsbOnline);
+ intent.putExtra("ac_online", mBatteryProps.chargerAcOnline);
+ intent.putExtra("dock_ac_online", mBatteryProps.chargerDockAcOnline);
+ }
+
+
if (DEBUG) {
- Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
- ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
+ String msg = "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
+ ", scale:" + BATTERY_SCALE +
+ ", status:" + mBatteryProps.batteryStatus +
", health:" + mBatteryProps.batteryHealth +
", present:" + mBatteryProps.batteryPresent +
", voltage: " + mBatteryProps.batteryVoltage +
", temperature: " + mBatteryProps.batteryTemperature +
", technology: " + mBatteryProps.batteryTechnology +
- ", AC powered:" + mBatteryProps.chargerAcOnline +
- ", USB powered:" + mBatteryProps.chargerUsbOnline +
- ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
- ", icon:" + icon + ", invalid charger:" + mInvalidCharger +
- ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent);
+ ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent;
+
+ if (mDockBatterySupported) {
+ msg += ", dock_level:" + mBatteryProps.dockBatteryLevel +
+ ", dock_status:" + mBatteryProps.dockBatteryStatus +
+ ", dock_health:" + mBatteryProps.dockBatteryHealth +
+ ", dock_present:" + mBatteryProps.dockBatteryPresent +
+ ", dock_voltage: " + mBatteryProps.dockBatteryVoltage +
+ ", dock_temperature: " + mBatteryProps.dockBatteryTemperature +
+ ", dock_technology: " + mBatteryProps.dockBatteryTechnology;
+ }
+ msg += ", AC powered:" + mBatteryProps.chargerAcOnline;
+ if (mDockBatterySupported) {
+ msg += ", Dock AC powered:" + mBatteryProps.chargerDockAcOnline;
+ }
+ msg += ", USB powered:" + mBatteryProps.chargerUsbOnline +
+ ", Wireless powered:" + mBatteryProps.chargerWirelessOnline;
+ msg += ", icon:" + icon;
+ if (mDockBatterySupported) {
+ msg += ", dock_icon:" + dockIcon;
+ }
+ msg += ", invalid charger:" + mInvalidCharger;
+
+ Slog.d(TAG, msg);
}
mHandler.post(new Runnable() {
@@ -658,6 +827,22 @@ public final class BatteryService extends SystemService {
}
}
+ private int getDockIconLocked(int level) {
+ if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
+ return com.android.internal.R.drawable.stat_sys_battery_charge;
+ } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+ return com.android.internal.R.drawable.stat_sys_battery;
+ } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
+ || mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
+ if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
+ && mBatteryProps.dockBatteryLevel >= 100) {
+ return com.android.internal.R.drawable.stat_sys_battery_charge;
+ }
+ return com.android.internal.R.drawable.stat_sys_battery;
+ }
+ return com.android.internal.R.drawable.stat_sys_battery_unknown;
+ }
+
private void dumpInternal(PrintWriter pw, String[] args) {
synchronized (mLock) {
if (args == null || args.length == 0 || "-a".equals(args[0])) {
@@ -666,6 +851,9 @@ public final class BatteryService extends SystemService {
pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
}
pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
+ if (mDockBatterySupported) {
+ pw.println(" Dock AC powered: " + mBatteryProps.chargerDockAcOnline);
+ }
pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
@@ -677,7 +865,15 @@ public final class BatteryService extends SystemService {
pw.println(" voltage: " + mBatteryProps.batteryVoltage);
pw.println(" temperature: " + mBatteryProps.batteryTemperature);
pw.println(" technology: " + mBatteryProps.batteryTechnology);
-
+ if (mDockBatterySupported) {
+ pw.println(" dock_status: " + mBatteryProps.dockBatteryStatus);
+ pw.println(" dock_health: " + mBatteryProps.dockBatteryHealth);
+ pw.println(" dock_present: " + mBatteryProps.dockBatteryPresent);
+ pw.println(" dock_level: " + mBatteryProps.dockBatteryLevel);
+ pw.println(" dock_voltage: " + mBatteryProps.dockBatteryVoltage);
+ pw.println(" dock_temperature: " + mBatteryProps.dockBatteryTemperature);
+ pw.println(" dock_technology: " + mBatteryProps.dockBatteryTechnology);
+ }
} else if ("unplug".equals(args[0])) {
if (!mUpdatesStopped) {
mLastBatteryProps.set(mBatteryProps);
@@ -703,6 +899,8 @@ public final class BatteryService extends SystemService {
boolean update = true;
if ("ac".equals(key)) {
mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
+ } else if (mDockBatterySupported && "dockac".equals(key)) {
+ mBatteryProps.chargerDockAcOnline = Integer.parseInt(value) != 0;
} else if ("usb".equals(key)) {
mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
} else if ("wireless".equals(key)) {
@@ -711,6 +909,10 @@ public final class BatteryService extends SystemService {
mBatteryProps.batteryStatus = Integer.parseInt(value);
} else if ("level".equals(key)) {
mBatteryProps.batteryLevel = Integer.parseInt(value);
+ } else if (mDockBatterySupported && "dockstatus".equals(key)) {
+ mBatteryProps.dockBatteryStatus = Integer.parseInt(value);
+ } else if (mDockBatterySupported && "docklevel".equals(key)) {
+ mBatteryProps.dockBatteryLevel = Integer.parseInt(value);
} else if ("invalid".equals(key)) {
mInvalidCharger = Integer.parseInt(value);
} else {
@@ -743,7 +945,12 @@ public final class BatteryService extends SystemService {
}
} else {
pw.println("Dump current battery state, or:");
- pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ if (mDockBatterySupported) {
+ pw.println(" set [ac|dockac|usb|wireless|status|level|dockstatus" +
+ "|docklevel|invalid] <value>");
+ } else {
+ pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ }
pw.println(" unplug");
pw.println(" reset");
}
@@ -935,7 +1142,12 @@ public final class BatteryService extends SystemService {
}
}
- private final class BinderService extends Binder {
+ private final class BinderService extends IBatteryService.Stub {
+ @Override
+ public boolean isDockBatterySupported() throws RemoteException {
+ return getLocalService(BatteryManagerInternal.class).isDockBatterySupported();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -981,11 +1193,39 @@ public final class BatteryService extends SystemService {
}
@Override
+ public int getDockPlugType() {
+ synchronized (mLock) {
+ return mDockPlugType;
+ }
+ }
+
+ @Override
+ public int getDockBatteryLevel() {
+ synchronized (mLock) {
+ return mBatteryProps.dockBatteryLevel;
+ }
+ }
+
+ @Override
+ public boolean getDockBatteryLevelLow() {
+ synchronized (mLock) {
+ return mDockBatteryLevelLow;
+ }
+ }
+
+ @Override
public int getInvalidCharger() {
synchronized (mLock) {
return mInvalidCharger;
}
}
+
+ @Override
+ public boolean isDockBatterySupported() {
+ synchronized (mLock) {
+ return mDockBatterySupported;
+ }
+ }
}
class SettingsObserver extends ContentObserver {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index ab2ea8b..cfc123b 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -11,6 +11,10 @@ option java_package com.android.server
# It lets us count the total amount of time between charges and the discharge level
2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
+# dock battery
+2738 dock_battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
+2739 dock_battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
+
# ---------------------------
# PowerManagerService.java
@@ -31,7 +35,8 @@ option java_package com.android.server
2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
#
-# Leave IDs through 2739 for more power logs (2730 used by battery_discharge above)
+# Leave IDs through 2739 for more power logs (2730 used by battery_discharge and
+# 2738-2739 used by dock battery above)
#
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 62768c3..5fd3510 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2007 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,6 +51,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.DockBatteryStatsImpl;
+
import com.android.internal.os.PowerProfile;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -75,6 +78,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
static IBatteryStats sService;
final BatteryStatsImpl mStats;
+ // The dock stats only collect statistics about battery (no wakelocks, no counters, ...),
+ // just the dock battery history
+ final DockBatteryStatsImpl mDockStats;
final BatteryStatsHandler mHandler;
Context mContext;
PowerManagerInternal mPowerManagerInternal;
@@ -167,6 +173,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
// BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
+ mDockStats = new DockBatteryStatsImpl(systemDir, handler, mHandler);
}
public void publish(Context context) {
@@ -196,6 +203,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
synchronized (mStats) {
mStats.shutdownLocked();
}
+ synchronized (mDockStats) {
+ mDockStats.shutdownLocked();
+ }
}
public static IBatteryStats getService() {
@@ -231,6 +241,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
}
+ /**
+ * @return the current dock statistics object, which may be modified
+ * to reflect events that affect battery usage. You must lock the
+ * stats object before doing anything with it.
+ * @hide
+ */
+ public BatteryStatsImpl getActiveDockStatistics() {
+ return mDockStats;
+ }
+
// These are for direct use by the activity manager...
/**
@@ -327,6 +347,48 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ /** @hide */
+ public byte[] getDockStatistics() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ //Slog.i("foo", "SENDING DOCK BATTERY INFO:");
+ //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
+ Parcel out = Parcel.obtain();
+ mDockStats.writeToParcel(out, 0);
+ byte[] data = out.marshall();
+ out.recycle();
+ return data;
+ }
+
+ /** @hide */
+ public ParcelFileDescriptor getDockStatisticsStream() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ //Slog.i("foo", "SENDING DOCK BATTERY INFO:");
+ //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
+ Parcel out = Parcel.obtain();
+ mDockStats.writeToParcel(out, 0);
+ byte[] data = out.marshall();
+ out.recycle();
+ try {
+ return ParcelFileDescriptor.fromData(data, "dock-battery-stats");
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to create shared memory", e);
+ return null;
+ }
+ }
+
+ public void resetStatistics() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.RESET_BATTERY_STATS, null);
+ synchronized (mStats) {
+ mStats.resetAllStatsCmdLocked();
+ }
+ synchronized (mDockStats) {
+ mDockStats.resetAllStatsCmdLocked();
+ }
+ }
+
public long computeBatteryTimeRemaining() {
synchronized (mStats) {
long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
@@ -901,6 +963,31 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return mStats.getAwakeTimePlugged();
}
+ /** @hide */
+ public boolean isOnDockBattery() {
+ return mDockStats.isOnBattery();
+ }
+
+ /** @hide */
+ public void setDockBatteryState(int status, int health, int plugType, int level,
+ int temp, int volt) {
+ enforceCallingPermission();
+ mDockStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+ }
+
+ /** @hide */
+ public long getAwakeTimeDockBattery() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ return mDockStats.getAwakeTimeBattery();
+ }
+
+ public long getAwakeTimeDockPlugged() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ return mDockStats.getAwakeTimePlugged();
+ }
+
public void enforceCallingPermission() {
if (Binder.getCallingPid() == Process.myPid()) {
return;
@@ -1065,6 +1152,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
} else if ("--reset".equals(arg)) {
synchronized (mStats) {
mStats.resetAllStatsCmdLocked();
+ mDockStats.resetAllStatsCmdLocked();
pw.println("Battery stats reset.");
noOutput = true;
}
@@ -1073,6 +1161,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
updateExternalStats("dump", UPDATE_ALL);
synchronized (mStats) {
mStats.writeSyncLocked();
+ mDockStats.writeSyncLocked();
pw.println("Battery stats written.");
noOutput = true;
}
@@ -1176,19 +1265,44 @@ public final class BatteryStatsService extends IBatteryStats.Stub
+ mStats.mCheckinFile.getBaseFile(), e);
}
}
+ if (mDockStats.mCheckinFile.exists()) {
+ try {
+ byte[] raw = mDockStats.mCheckinFile.readFully();
+ if (raw != null) {
+ Parcel in = Parcel.obtain();
+ in.unmarshall(raw, 0, raw.length);
+ in.setDataPosition(0);
+ DockBatteryStatsImpl checkinStats = new DockBatteryStatsImpl(
+ null, mStats.mHandler, null);
+ checkinStats.readSummaryFromParcel(in);
+ in.recycle();
+ checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
+ historyStart);
+ mDockStats.mCheckinFile.delete();
+ return;
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "Failure reading dock checkin file "
+ + mDockStats.mCheckinFile.getBaseFile(), e);
+ }
+ }
}
}
synchronized (mStats) {
mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
+ mDockStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
if (writeData) {
mStats.writeAsyncLocked();
+ mDockStats.writeAsyncLocked();
}
}
} else {
synchronized (mStats) {
mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
+ mDockStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
if (writeData) {
mStats.writeAsyncLocked();
+ mDockStats.writeAsyncLocked();
}
}
}