Fix deadlock issue in BatteryStatsHelper.
It was assumed that BatteryStatsHelper could safely call into system services.
Because it is used when dumping information from the BatteryStatsService,
this assumption was incorrect.
Now the BatteryStats object carries around the state of the energy reporting
for Bluetooth and WiFi, so BatteryStatsHelper avoids a query into WiFiManager.
b/19729960
Change-Id: I8745cf6aafeea8e862e34fe63b20056f6ba54b40
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1566985..c7edb1a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1947,6 +1947,13 @@
public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1;
/**
+ * Returns true if the BatteryStats object has detailed bluetooth power reports.
+ * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the
+ * actual power data.
+ */
+ public abstract boolean hasBluetoothActivityReporting();
+
+ /**
* For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
* {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
* respective state.
@@ -1956,6 +1963,13 @@
public abstract long getBluetoothControllerActivity(int type, int which);
/**
+ * Returns true if the BatteryStats object has detailed WiFi power reports.
+ * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the
+ * actual power data.
+ */
+ public abstract boolean hasWifiActivityReporting();
+
+ /**
* For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
* {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
* respective state.
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 024b7c5..59dbec6 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -21,7 +21,6 @@
import android.content.IntentFilter;
import android.hardware.SensorManager;
import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
import android.os.BatteryStats;
import android.os.BatteryStats.Uid;
import android.os.Bundle;
@@ -130,16 +129,11 @@
return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
}
- public static boolean checkHasWifiPowerReporting(Context context, PowerProfile profile) {
- WifiManager manager = context.getSystemService(WifiManager.class);
- if (manager.isEnhancedPowerReportingSupported()) {
- if (profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE) != 0 &&
- profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX) != 0 &&
- profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX) != 0) {
- return true;
- }
- }
- return false;
+ public static boolean checkHasWifiPowerReporting(BatteryStats stats, PowerProfile profile) {
+ return stats.hasWifiActivityReporting() &&
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE) != 0 &&
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX) != 0 &&
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX) != 0;
}
public BatteryStatsHelper(Context context) {
@@ -339,7 +333,7 @@
mMobileRadioPowerCalculator.reset(mStats);
if (mWifiPowerCalculator == null) {
- if (checkHasWifiPowerReporting(mContext, mPowerProfile)) {
+ if (checkHasWifiPowerReporting(mStats, mPowerProfile)) {
mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
} else {
mWifiPowerCalculator = new WifiPowerEstimator(mPowerProfile);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c5c0ba6..fbb2dfc 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -472,6 +472,8 @@
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
private PowerProfile mPowerProfile;
+ private boolean mHasWifiEnergyReporting = false;
+ private boolean mHasBluetoothEnergyReporting = false;
/*
* Holds a SamplingTimer associated with each kernel wakelock name being tracked.
@@ -4298,6 +4300,10 @@
return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
}
+ @Override public boolean hasBluetoothActivityReporting() {
+ return mHasBluetoothEnergyReporting;
+ }
+
@Override public long getBluetoothControllerActivity(int type, int which) {
if (type >= 0 && type < mBluetoothActivityCounters.length) {
return mBluetoothActivityCounters[type].getCountLocked(which);
@@ -4305,6 +4311,10 @@
return 0;
}
+ @Override public boolean hasWifiActivityReporting() {
+ return mHasWifiEnergyReporting;
+ }
+
@Override public long getWifiControllerActivity(int type, int which) {
if (type >= 0 && type < mWifiActivityCounters.length) {
return mWifiActivityCounters[type].getCountLocked(which);
@@ -7567,6 +7577,8 @@
}
if (info != null) {
+ mHasWifiEnergyReporting = true;
+
// Measured in mAms
final long txTimeMs = info.getControllerTxTimeMillis();
final long rxTimeMs = info.getControllerRxTimeMillis();
@@ -7778,6 +7790,7 @@
*/
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
if (info != null && mOnBatteryInternal && false) {
+ mHasBluetoothEnergyReporting = true;
mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
info.getControllerRxTimeMillis());
mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
@@ -9533,6 +9546,8 @@
mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
}
+ mHasWifiEnergyReporting = in.readInt() != 0;
+ mHasBluetoothEnergyReporting = in.readInt() != 0;
mNumConnectivityChange = in.readInt();
mLoadedNumConnectivityChange = in.readInt();
mUnpluggedNumConnectivityChange = in.readInt();
@@ -9686,6 +9701,8 @@
for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
mWifiActivityCounters[i].writeToParcel(out);
}
+ out.writeInt(mHasWifiEnergyReporting ? 1 : 0);
+ out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0);
out.writeInt(mNumConnectivityChange);
out.writeInt(mLoadedNumConnectivityChange);
out.writeInt(mUnpluggedNumConnectivityChange);
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 4e77f6b..4fb8b55 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -16,12 +16,15 @@
package com.android.internal.os;
import android.os.BatteryStats;
+import android.util.Log;
/**
* WiFi power calculator for when BatteryStats supports energy reporting
* from the WiFi controller.
*/
public class WifiPowerCalculator extends PowerCalculator {
+ private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
+ private static final String TAG = "WifiPowerCalculator";
private final double mIdleCurrentMa;
private final double mTxCurrentMa;
private final double mRxCurrentMa;
@@ -75,6 +78,10 @@
+ (rxTimeMs * mRxCurrentMa)) / (1000*60*60);
}
app.wifiPowerMah = Math.max(0, powerDrain - mTotalAppPowerDrain);
+
+ if (DEBUG) {
+ Log.d(TAG, "left over WiFi power: " + BatteryStatsHelper.makemAh(app.wifiPowerMah));
+ }
}
@Override