Merge "BatteryStats: Acquire network stats without BatteryStatsImpl lock" into oc-dev

This commit is contained in:
Adam Lesinski
2017-05-31 22:36:55 +00:00
committed by Android (Google) Code Review
2 changed files with 452 additions and 427 deletions

View File

@@ -56,6 +56,7 @@ import android.util.LogWriter;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.util.LongSparseLongArray; import android.util.LongSparseLongArray;
import android.util.MutableInt; import android.util.MutableInt;
import android.util.Pools;
import android.util.PrintWriterPrinter; import android.util.PrintWriterPrinter;
import android.util.Printer; import android.util.Printer;
import android.util.Slog; import android.util.Slog;
@@ -66,6 +67,7 @@ import android.util.TimeUtils;
import android.util.Xml; import android.util.Xml;
import android.view.Display; import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.NetworkStatsFactory; import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
@@ -173,7 +175,6 @@ public class BatteryStatsImpl extends BatteryStats {
private final PlatformIdleStateCallback mPlatformIdleStateCallback; private final PlatformIdleStateCallback mPlatformIdleStateCallback;
final class MyHandler extends Handler { final class MyHandler extends Handler {
public MyHandler(Looper looper) { public MyHandler(Looper looper) {
super(looper, null, true); super(looper, null, true);
@@ -228,11 +229,11 @@ public class BatteryStatsImpl extends BatteryStats {
} }
public interface ExternalStatsSync { public interface ExternalStatsSync {
public static final int UPDATE_CPU = 0x01; int UPDATE_CPU = 0x01;
public static final int UPDATE_WIFI = 0x02; int UPDATE_WIFI = 0x02;
public static final int UPDATE_RADIO = 0x04; int UPDATE_RADIO = 0x04;
public static final int UPDATE_BT = 0x08; int UPDATE_BT = 0x08;
public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
void scheduleSync(String reason, int flags); void scheduleSync(String reason, int flags);
void scheduleCpuSyncDueToRemovedUid(int uid); void scheduleCpuSyncDueToRemovedUid(int uid);
@@ -572,8 +573,6 @@ public class BatteryStatsImpl extends BatteryStats {
private int mMinLearnedBatteryCapacity = -1; private int mMinLearnedBatteryCapacity = -1;
private int mMaxLearnedBatteryCapacity = -1; private int mMaxLearnedBatteryCapacity = -1;
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
private long[] mCpuFreqs; private long[] mCpuFreqs;
private PowerProfile mPowerProfile; private PowerProfile mPowerProfile;
@@ -637,19 +636,9 @@ public class BatteryStatsImpl extends BatteryStats {
private void init(Clocks clocks) { private void init(Clocks clocks) {
mClocks = clocks; mClocks = clocks;
mMobileNetworkStats = new NetworkStats[] {
new NetworkStats(mClocks.elapsedRealtime(), 50),
new NetworkStats(mClocks.elapsedRealtime(), 50),
new NetworkStats(mClocks.elapsedRealtime(), 50)
};
mWifiNetworkStats = new NetworkStats[] {
new NetworkStats(mClocks.elapsedRealtime(), 50),
new NetworkStats(mClocks.elapsedRealtime(), 50),
new NetworkStats(mClocks.elapsedRealtime(), 50)
};
} }
public static interface TimeBaseObs { public interface TimeBaseObs {
void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime); void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime); void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
} }
@@ -4200,7 +4189,10 @@ public class BatteryStatsImpl extends BatteryStats {
getUidStatsLocked(uid).noteMobileRadioApWakeupLocked(); getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
} }
public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { /**
* Updates the radio power state and returns true if an external stats collection should occur.
*/
public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
final long elapsedRealtime = mClocks.elapsedRealtime(); final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis(); final long uptime = mClocks.uptimeMillis();
if (mMobileRadioPowerState != powerState) { if (mMobileRadioPowerState != powerState) {
@@ -4237,13 +4229,15 @@ public class BatteryStatsImpl extends BatteryStats {
mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
} else { } else {
mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
// Tell the caller to collect radio network/power stats.
return true;
} }
} }
return false;
} }
public void notePowerSaveMode(boolean enabled) { public void notePowerSaveModeLocked(boolean enabled) {
if (mPowerSaveModeEnabled != enabled) { if (mPowerSaveModeEnabled != enabled) {
int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0; int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState; mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
@@ -5243,28 +5237,26 @@ public class BatteryStatsImpl extends BatteryStats {
public void noteNetworkInterfaceTypeLocked(String iface, int networkType) { public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
if (TextUtils.isEmpty(iface)) return; if (TextUtils.isEmpty(iface)) return;
if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
} else {
mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
}
if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
} else {
mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
}
}
public void noteNetworkStatsEnabledLocked() { synchronized (mModemNetworkLock) {
// During device boot, qtaguid isn't enabled until after the inital if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
// loading of battery stats. Now that they're enabled, take our initial mModemIfaces = includeInStringArray(mModemIfaces, iface);
// snapshot for future delta calculation. if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null); } else {
updateWifiStateLocked(null); mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
}
}
synchronized (mWifiNetworkLock) {
if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
} else {
mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
}
}
} }
@Override public long getScreenOnTime(long elapsedRealtimeUs, int which) { @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
@@ -8713,27 +8705,25 @@ public class BatteryStatsImpl extends BatteryStats {
mPlatformIdleStateCallback = null; mPlatformIdleStateCallback = null;
} }
public void setPowerProfile(PowerProfile profile) { public void setPowerProfileLocked(PowerProfile profile) {
synchronized (this) { mPowerProfile = profile;
mPowerProfile = profile;
// We need to initialize the KernelCpuSpeedReaders to read from // We need to initialize the KernelCpuSpeedReaders to read from
// the first cpu of each core. Once we have the PowerProfile, we have access to this // the first cpu of each core. Once we have the PowerProfile, we have access to this
// information. // information.
final int numClusters = mPowerProfile.getNumCpuClusters(); final int numClusters = mPowerProfile.getNumCpuClusters();
mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters]; mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
int firstCpuOfCluster = 0; int firstCpuOfCluster = 0;
for (int i = 0; i < numClusters; i++) { for (int i = 0; i < numClusters; i++) {
final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i); final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster, mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
numSpeedSteps); numSpeedSteps);
firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
} }
if (mEstimatedBatteryCapacity == -1) { if (mEstimatedBatteryCapacity == -1) {
// Initialize the estimated battery capacity to a known preset one. // Initialize the estimated battery capacity to a known preset one.
mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity(); mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
}
} }
} }
@@ -8741,7 +8731,7 @@ public class BatteryStatsImpl extends BatteryStats {
mCallback = cb; mCallback = cb;
} }
public void setRadioScanningTimeout(long timeout) { public void setRadioScanningTimeoutLocked(long timeout) {
if (mPhoneSignalScanningTimer != null) { if (mPhoneSignalScanningTimer != null) {
mPhoneSignalScanningTimer.setTimeout(timeout); mPhoneSignalScanningTimer.setTimeout(timeout);
} }
@@ -9433,277 +9423,293 @@ public class BatteryStatsImpl extends BatteryStats {
} }
} }
private String[] mMobileIfaces = EmptyArray.STRING; private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
private final Object mWifiNetworkLock = new Object();
@GuardedBy("mWifiNetworkLock")
private String[] mWifiIfaces = EmptyArray.STRING; private String[] mWifiIfaces = EmptyArray.STRING;
private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); @GuardedBy("mWifiNetworkLock")
private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
private static final int NETWORK_STATS_LAST = 0; private final Object mModemNetworkLock = new Object();
private static final int NETWORK_STATS_NEXT = 1;
private static final int NETWORK_STATS_DELTA = 2;
private NetworkStats[] mMobileNetworkStats; @GuardedBy("mModemNetworkLock")
private NetworkStats[] mWifiNetworkStats; private String[] mModemIfaces = EmptyArray.STRING;
/** @GuardedBy("mModemNetworkLock")
* Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
* as a buffer of NetworkStats objects to cycle through when computing deltas.
*/ private NetworkStats readNetworkStatsLocked(String[] ifaces) {
private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces, try {
NetworkStats[] networkStatsBuffer) if (!ArrayUtils.isEmpty(ifaces)) {
throws IOException { return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
false)) { }
return null; } catch (IOException e) {
Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
} }
return null;
final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
networkStatsBuffer[NETWORK_STATS_LAST], null, null,
networkStatsBuffer[NETWORK_STATS_DELTA]);
networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
networkStatsBuffer[NETWORK_STATS_LAST] = stats;
return networkStatsBuffer[NETWORK_STATS_DELTA];
} }
/** /**
* Distribute WiFi energy info and network traffic to apps. * Distribute WiFi energy info and network traffic to apps.
* @param info The energy information from the WiFi controller. * @param info The energy information from the WiFi controller.
*/ */
public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) { public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
if (DEBUG_ENERGY) { if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating wifi stats"); Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
} }
final long elapsedRealtimeMs = mClocks.elapsedRealtime(); // Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null; NetworkStats delta = null;
try { synchronized (mWifiNetworkLock) {
if (!ArrayUtils.isEmpty(mWifiIfaces)) { final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats); if (latestStats != null) {
delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
mNetworkStatsPool.acquire());
mNetworkStatsPool.release(mLastWifiNetworkStats);
mLastWifiNetworkStats = latestStats;
} }
} catch (IOException e) {
Slog.wtf(TAG, "Failed to get wifi network stats", e);
return;
} }
if (!mOnBatteryInternal) { synchronized (this) {
return; if (!mOnBatteryInternal) {
} if (delta != null) {
mNetworkStatsPool.release(delta);
SparseLongArray rxPackets = new SparseLongArray();
SparseLongArray txPackets = new SparseLongArray();
long totalTxPackets = 0;
long totalRxPackets = 0;
if (delta != null) {
final int size = delta.size();
for (int i = 0; i < size; i++) {
final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
if (DEBUG_ENERGY) {
Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
+ " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+ " txPackets=" + entry.txPackets);
} }
return;
}
if (entry.rxBytes == 0 && entry.txBytes == 0) { final long elapsedRealtimeMs = mClocks.elapsedRealtime();
// Skip the lookup below since there is no work to do. SparseLongArray rxPackets = new SparseLongArray();
continue; SparseLongArray txPackets = new SparseLongArray();
} long totalTxPackets = 0;
long totalRxPackets = 0;
if (delta != null) {
NetworkStats.Entry entry = new NetworkStats.Entry();
final int size = delta.size();
for (int i = 0; i < size; i++) {
entry = delta.getValues(i, entry);
final Uid u = getUidStatsLocked(mapUid(entry.uid)); if (DEBUG_ENERGY) {
if (entry.rxBytes != 0) { Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
entry.rxPackets); + " txPackets=" + entry.txPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers }
u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
if (entry.rxBytes == 0 && entry.txBytes == 0) {
// Skip the lookup below since there is no work to do.
continue;
}
final Uid u = getUidStatsLocked(mapUid(entry.uid));
if (entry.rxBytes != 0) {
u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
entry.rxPackets); entry.rxPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
entry.rxPackets);
}
mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
entry.rxBytes);
mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
entry.rxPackets);
rxPackets.put(u.getUid(), entry.rxPackets);
// Sum the total number of packets so that the Rx Power can
// be evenly distributed amongst the apps.
totalRxPackets += entry.rxPackets;
} }
mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
entry.rxBytes);
mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
entry.rxPackets);
rxPackets.put(u.getUid(), entry.rxPackets); if (entry.txBytes != 0) {
u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
// Sum the total number of packets so that the Rx Power can
// be evenly distributed amongst the apps.
totalRxPackets += entry.rxPackets;
}
if (entry.txBytes != 0) {
u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
entry.txPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
entry.txPackets); entry.txPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
entry.txPackets);
}
mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
entry.txBytes);
mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
entry.txPackets);
txPackets.put(u.getUid(), entry.txPackets);
// Sum the total number of packets so that the Tx Power can
// be evenly distributed amongst the apps.
totalTxPackets += entry.txPackets;
} }
mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
entry.txBytes);
mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
entry.txPackets);
txPackets.put(u.getUid(), entry.txPackets);
// Sum the total number of packets so that the Tx Power can
// be evenly distributed amongst the apps.
totalTxPackets += entry.txPackets;
} }
} mNetworkStatsPool.release(delta);
} delta = null;
if (info != null) {
mHasWifiReporting = true;
// Measured in mAms
final long txTimeMs = info.getControllerTxTimeMillis();
final long rxTimeMs = info.getControllerRxTimeMillis();
final long idleTimeMs = info.getControllerIdleTimeMillis();
final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
long leftOverRxTimeMs = rxTimeMs;
long leftOverTxTimeMs = txTimeMs;
if (DEBUG_ENERGY) {
Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
Slog.d(TAG, " Tx Time: " + txTimeMs + " ms");
Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms");
Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
Slog.d(TAG, " Total Time: " + totalTimeMs + " ms");
} }
long totalWifiLockTimeMs = 0; if (info != null) {
long totalScanTimeMs = 0; mHasWifiReporting = true;
// On the first pass, collect some totals so that we can normalize power // Measured in mAms
// calculations if we need to. final long txTimeMs = info.getControllerTxTimeMillis();
final int uidStatsSize = mUidStats.size(); final long rxTimeMs = info.getControllerRxTimeMillis();
for (int i = 0; i < uidStatsSize; i++) { final long idleTimeMs = info.getControllerIdleTimeMillis();
final Uid uid = mUidStats.valueAt(i); final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
// Sum the total scan power for all apps. long leftOverRxTimeMs = rxTimeMs;
totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked( long leftOverTxTimeMs = txTimeMs;
elapsedRealtimeMs * 1000) / 1000;
// Sum the total time holding wifi lock for all apps.
totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
}
if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
Slog.d(TAG, " !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
+ rxTimeMs + " ms). Normalizing scan time.");
}
if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
Slog.d(TAG, " !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
+ txTimeMs + " ms). Normalizing scan time.");
}
// Actually assign and distribute power usage to apps.
for (int i = 0; i < uidStatsSize; i++) {
final Uid uid = mUidStats.valueAt(i);
long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
if (scanTimeSinceMarkMs > 0) {
// Set the new mark so that next time we get new data since this point.
uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
// Our total scan time is more than the reported Tx/Rx time.
// This is possible because the cost of a scan is approximate.
// Let's normalize the result so that we evenly blame each app
// scanning.
//
// This means that we may have apps that transmitted/received packets not be
// blamed for this, but this is fine as scans are relatively more expensive.
if (totalScanTimeMs > rxTimeMs) {
scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
totalScanTimeMs;
}
if (totalScanTimeMs > txTimeMs) {
scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
totalScanTimeMs;
}
if (DEBUG_ENERGY) {
Slog.d(TAG, " ScanTime for UID " + uid.getUid() + ": Rx:"
+ scanRxTimeSinceMarkMs + " ms Tx:"
+ scanTxTimeSinceMarkMs + " ms)");
}
ControllerActivityCounterImpl activityCounter =
uid.getOrCreateWifiControllerActivityLocked();
activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
}
// Distribute evenly the power consumed while Idle to each app holding a WiFi
// lock.
final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
if (wifiLockTimeSinceMarkMs > 0) {
// Set the new mark so that next time we get new data since this point.
uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
/ totalWifiLockTimeMs;
if (DEBUG_ENERGY) {
Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
+ myIdleTimeMs + " ms");
}
uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
.addCountLocked(myIdleTimeMs);
}
}
if (DEBUG_ENERGY) {
Slog.d(TAG, " New RxPower: " + leftOverRxTimeMs + " ms");
Slog.d(TAG, " New TxPower: " + leftOverTxTimeMs + " ms");
}
// Distribute the remaining Tx power appropriately between all apps that transmitted
// packets.
for (int i = 0; i < txPackets.size(); i++) {
final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
if (DEBUG_ENERGY) { if (DEBUG_ENERGY) {
Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms"); Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
Slog.d(TAG, " Tx Time: " + txTimeMs + " ms");
Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms");
Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
Slog.d(TAG, " Total Time: " + totalTimeMs + " ms");
}
long totalWifiLockTimeMs = 0;
long totalScanTimeMs = 0;
// On the first pass, collect some totals so that we can normalize power
// calculations if we need to.
final int uidStatsSize = mUidStats.size();
for (int i = 0; i < uidStatsSize; i++) {
final Uid uid = mUidStats.valueAt(i);
// Sum the total scan power for all apps.
totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
// Sum the total time holding wifi lock for all apps.
totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
}
if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
Slog.d(TAG,
" !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
+ rxTimeMs + " ms). Normalizing scan time.");
}
if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
Slog.d(TAG,
" !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
+ txTimeMs + " ms). Normalizing scan time.");
}
// Actually assign and distribute power usage to apps.
for (int i = 0; i < uidStatsSize; i++) {
final Uid uid = mUidStats.valueAt(i);
long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
if (scanTimeSinceMarkMs > 0) {
// Set the new mark so that next time we get new data since this point.
uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
// Our total scan time is more than the reported Tx/Rx time.
// This is possible because the cost of a scan is approximate.
// Let's normalize the result so that we evenly blame each app
// scanning.
//
// This means that we may have apps that transmitted/received packets not be
// blamed for this, but this is fine as scans are relatively more expensive.
if (totalScanTimeMs > rxTimeMs) {
scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
totalScanTimeMs;
}
if (totalScanTimeMs > txTimeMs) {
scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
totalScanTimeMs;
}
if (DEBUG_ENERGY) {
Slog.d(TAG, " ScanTime for UID " + uid.getUid() + ": Rx:"
+ scanRxTimeSinceMarkMs + " ms Tx:"
+ scanTxTimeSinceMarkMs + " ms)");
}
ControllerActivityCounterImpl activityCounter =
uid.getOrCreateWifiControllerActivityLocked();
activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
activityCounter.getTxTimeCounters()[0].addCountLocked(
scanTxTimeSinceMarkMs);
leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
}
// Distribute evenly the power consumed while Idle to each app holding a WiFi
// lock.
final long wifiLockTimeSinceMarkMs =
uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
if (wifiLockTimeSinceMarkMs > 0) {
// Set the new mark so that next time we get new data since this point.
uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
/ totalWifiLockTimeMs;
if (DEBUG_ENERGY) {
Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
+ myIdleTimeMs + " ms");
}
uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
.addCountLocked(myIdleTimeMs);
}
} }
uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
.addCountLocked(myTxTimeMs);
}
// Distribute the remaining Rx power appropriately between all apps that received
// packets.
for (int i = 0; i < rxPackets.size(); i++) {
final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
if (DEBUG_ENERGY) { if (DEBUG_ENERGY) {
Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms"); Slog.d(TAG, " New RxPower: " + leftOverRxTimeMs + " ms");
Slog.d(TAG, " New TxPower: " + leftOverTxTimeMs + " ms");
} }
uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
.addCountLocked(myRxTimeMs);
}
// Any left over power use will be picked up by the WiFi category in BatteryStatsHelper. // Distribute the remaining Tx power appropriately between all apps that transmitted
// packets.
for (int i = 0; i < txPackets.size(); i++) {
final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
/ totalTxPackets;
if (DEBUG_ENERGY) {
Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
}
uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
.addCountLocked(myTxTimeMs);
}
// Update WiFi controller stats. // Distribute the remaining Rx power appropriately between all apps that received
mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis()); // packets.
mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis()); for (int i = 0; i < rxPackets.size(); i++) {
mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis()); final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
/ totalRxPackets;
if (DEBUG_ENERGY) {
Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
}
uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
.addCountLocked(myRxTimeMs);
}
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) { // Update WiFi controller stats.
// We store the power drain as mAms. mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
mWifiActivity.getPowerCounter().addCountLocked( mWifiActivity.getTxTimeCounters()[0].addCountLocked(
(long)(info.getControllerEnergyUsed() / opVolt)); info.getControllerTxTimeMillis());
mWifiActivity.getIdleTimeCounter().addCountLocked(
info.getControllerIdleTimeMillis());
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) {
// We store the power drain as mAms.
mWifiActivity.getPowerCounter().addCountLocked(
(long) (info.getControllerEnergyUsed() / opVolt));
}
} }
} }
} }
@@ -9711,133 +9717,148 @@ public class BatteryStatsImpl extends BatteryStats {
/** /**
* Distribute Cell radio energy info and network traffic to apps. * Distribute Cell radio energy info and network traffic to apps.
*/ */
public void updateMobileRadioStateLocked(final long elapsedRealtimeMs, public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
final ModemActivityInfo activityInfo) {
if (DEBUG_ENERGY) { if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
} }
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null; NetworkStats delta = null;
try { synchronized (mModemNetworkLock) {
if (!ArrayUtils.isEmpty(mMobileIfaces)) { final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats); if (latestStats != null) {
delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
mNetworkStatsPool.acquire());
mNetworkStatsPool.release(mLastModemNetworkStats);
mLastModemNetworkStats = latestStats;
} }
} catch (IOException e) {
Slog.wtf(TAG, "Failed to get mobile network stats", e);
return;
} }
if (!mOnBatteryInternal) { synchronized (this) {
return; if (!mOnBatteryInternal) {
} if (delta != null) {
mNetworkStatsPool.release(delta);
long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
long totalRxPackets = 0;
long totalTxPackets = 0;
if (delta != null) {
final int size = delta.size();
for (int i = 0; i < size; i++) {
final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
if (entry.rxPackets == 0 && entry.txPackets == 0) {
continue;
} }
return;
if (DEBUG_ENERGY) {
Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+ " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+ " txPackets=" + entry.txPackets);
}
totalRxPackets += entry.rxPackets;
totalTxPackets += entry.txPackets;
final Uid u = getUidStatsLocked(mapUid(entry.uid));
u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
entry.rxBytes, entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
entry.txBytes, entry.txPackets);
}
mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
entry.rxBytes);
mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
entry.txBytes);
mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
entry.rxPackets);
mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
entry.txPackets);
} }
// Now distribute proportional blame to the apps that did networking. final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
long totalPackets = totalRxPackets + totalTxPackets; long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
if (totalPackets > 0) { elapsedRealtimeMs * 1000);
mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
long totalRxPackets = 0;
long totalTxPackets = 0;
if (delta != null) {
NetworkStats.Entry entry = new NetworkStats.Entry();
final int size = delta.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); entry = delta.getValues(i, entry);
if (entry.rxPackets == 0 && entry.txPackets == 0) { if (entry.rxPackets == 0 && entry.txPackets == 0) {
continue; continue;
} }
if (DEBUG_ENERGY) {
Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+ " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+ " txPackets=" + entry.txPackets);
}
totalRxPackets += entry.rxPackets;
totalTxPackets += entry.txPackets;
final Uid u = getUidStatsLocked(mapUid(entry.uid)); final Uid u = getUidStatsLocked(mapUid(entry.uid));
u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
entry.txPackets);
if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
entry.rxBytes, entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
entry.txBytes, entry.txPackets);
}
// Distribute total radio active time in to this app. mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
final long appPackets = entry.rxPackets + entry.txPackets; entry.rxBytes);
final long appRadioTime = (radioTime * appPackets) / totalPackets; mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
u.noteMobileRadioActiveTimeLocked(appRadioTime); entry.txBytes);
mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
entry.rxPackets);
mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
entry.txPackets);
}
// Remove this app from the totals, so that we don't lose any time // Now distribute proportional blame to the apps that did networking.
// due to rounding. long totalPackets = totalRxPackets + totalTxPackets;
radioTime -= appRadioTime; if (totalPackets > 0) {
totalPackets -= appPackets; for (int i = 0; i < size; i++) {
entry = delta.getValues(i, entry);
if (activityInfo != null) { if (entry.rxPackets == 0 && entry.txPackets == 0) {
ControllerActivityCounterImpl activityCounter = continue;
u.getOrCreateModemControllerActivityLocked();
if (totalRxPackets > 0 && entry.rxPackets > 0) {
final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
/ totalRxPackets;
activityCounter.getRxTimeCounter().addCountLocked(rxMs);
} }
if (totalTxPackets > 0 && entry.txPackets > 0) { final Uid u = getUidStatsLocked(mapUid(entry.uid));
for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl]; // Distribute total radio active time in to this app.
txMs /= totalTxPackets; final long appPackets = entry.rxPackets + entry.txPackets;
activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs); final long appRadioTime = (radioTime * appPackets) / totalPackets;
u.noteMobileRadioActiveTimeLocked(appRadioTime);
// Remove this app from the totals, so that we don't lose any time
// due to rounding.
radioTime -= appRadioTime;
totalPackets -= appPackets;
if (activityInfo != null) {
ControllerActivityCounterImpl activityCounter =
u.getOrCreateModemControllerActivityLocked();
if (totalRxPackets > 0 && entry.rxPackets > 0) {
final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
/ totalRxPackets;
activityCounter.getRxTimeCounter().addCountLocked(rxMs);
}
if (totalTxPackets > 0 && entry.txPackets > 0) {
for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
long txMs =
entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
txMs /= totalTxPackets;
activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
}
} }
} }
} }
} }
if (radioTime > 0) {
// Whoops, there is some radio time we can't blame on an app!
mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
mMobileRadioActiveUnknownCount.addCountLocked(1);
}
mNetworkStatsPool.release(delta);
delta = null;
} }
if (radioTime > 0) { if (activityInfo != null) {
// Whoops, there is some radio time we can't blame on an app! mHasModemReporting = true;
mMobileRadioActiveUnknownTime.addCountLocked(radioTime); mModemActivity.getIdleTimeCounter().addCountLocked(
mMobileRadioActiveUnknownCount.addCountLocked(1); activityInfo.getIdleTimeMillis());
} mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
} for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
mModemActivity.getTxTimeCounters()[lvl]
.addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
}
if (activityInfo != null) { // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
mHasModemReporting = true; final double opVolt = mPowerProfile.getAveragePower(
mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis()); PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis()); if (opVolt != 0) {
for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { // We store the power drain as mAms.
mModemActivity.getTxTimeCounters()[lvl] mModemActivity.getPowerCounter().addCountLocked(
.addCountLocked(activityInfo.getTxTimeMillis()[lvl]); (long) (activityInfo.getEnergyUsed() / opVolt));
} }
// POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) {
// We store the power drain as mAms.
mModemActivity.getPowerCounter().addCountLocked(
(long) (activityInfo.getEnergyUsed() / opVolt));
} }
} }
} }

View File

@@ -17,6 +17,8 @@
package com.android.server.am; package com.android.server.am;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -231,10 +233,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void publish(Context context) { public void publish(Context context) {
mContext = context; mContext = context;
mStats.setRadioScanningTimeout(mContext.getResources().getInteger( synchronized (mStats) {
com.android.internal.R.integer.config_radioScanningTimeout) mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
* 1000L); com.android.internal.R.integer.config_radioScanningTimeout)
mStats.setPowerProfile(new PowerProfile(context)); * 1000L);
mStats.setPowerProfileLocked(new PowerProfile(context));
}
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
} }
@@ -245,9 +249,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void initPowerManagement() { public void initPowerManagement() {
final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class); final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
powerMgr.registerLowPowerModeObserver(this); powerMgr.registerLowPowerModeObserver(this);
mStats.notePowerSaveMode( synchronized (mStats) {
powerMgr.getLowPowerState(ServiceType.BATTERY_STATS) mStats.notePowerSaveModeLocked(
.batterySaverEnabled); powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
.batterySaverEnabled);
}
(new WakeupReasonThread()).start(); (new WakeupReasonThread()).start();
} }
@@ -280,7 +286,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override @Override
public void onLowPowerModeChanged(PowerSaveState result) { public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mStats) { synchronized (mStats) {
mStats.notePowerSaveMode(result.batterySaverEnabled); mStats.notePowerSaveModeLocked(result.batterySaverEnabled);
} }
} }
@@ -606,8 +612,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
enforceCallingPermission(); enforceCallingPermission();
boolean update;
synchronized (mStats) { synchronized (mStats) {
mStats.noteMobileRadioPowerState(powerState, timestampNs, uid); update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid);
}
if (update) {
mHandler.scheduleSync("modem-data", UPDATE_RADIO);
} }
} }
@@ -759,7 +770,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active" powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
: "inactive"; : "inactive";
mHandler.scheduleSync("wifi-data: " + type, mHandler.scheduleSync("wifi-data: " + type,
BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI); UPDATE_WIFI);
} }
mStats.noteWifiRadioPowerState(powerState, tsNanos, uid); mStats.noteWifiRadioPowerState(powerState, tsNanos, uid);
} }
@@ -917,9 +928,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override @Override
public void noteNetworkStatsEnabled() { public void noteNetworkStatsEnabled() {
enforceCallingPermission(); enforceCallingPermission();
synchronized (mStats) { mHandler.scheduleSync("network-stats-enabled", UPDATE_RADIO | UPDATE_WIFI);
mStats.noteNetworkStatsEnabledLocked();
}
} }
@Override @Override
@@ -985,9 +994,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return; return;
} }
synchronized (mStats) { mStats.updateWifiState(info);
mStats.updateWifiStateLocked(info);
}
} }
@Override @Override
@@ -1012,9 +1019,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return; return;
} }
synchronized (mStats) { mStats.updateMobileRadioState(info);
mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), info);
}
} }
public boolean isOnBattery() { public boolean isOnBattery() {
@@ -1489,7 +1494,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return; return;
} }
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) { if ((updateFlags & UPDATE_WIFI) != 0) {
if (mWifiManager == null) { if (mWifiManager == null) {
mWifiManager = IWifiManager.Stub.asInterface( mWifiManager = IWifiManager.Stub.asInterface(
ServiceManager.getService(Context.WIFI_SERVICE)); ServiceManager.getService(Context.WIFI_SERVICE));
@@ -1558,14 +1563,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mStats.updateKernelWakelocksLocked(); mStats.updateKernelWakelocksLocked();
mStats.updateKernelMemoryBandwidthLocked(); mStats.updateKernelMemoryBandwidthLocked();
if (wifiInfo != null) {
if (wifiInfo.isValid()) {
mStats.updateWifiStateLocked(extractDelta(wifiInfo));
} else {
Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
}
}
if (bluetoothInfo != null) { if (bluetoothInfo != null) {
if (bluetoothInfo.isValid()) { if (bluetoothInfo.isValid()) {
mStats.updateBluetoothStateLocked(bluetoothInfo); mStats.updateBluetoothStateLocked(bluetoothInfo);
@@ -1573,14 +1570,21 @@ public final class BatteryStatsService extends IBatteryStats.Stub
Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo); Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo);
} }
} }
}
if (modemInfo != null) { if (wifiInfo != null) {
if (modemInfo.isValid()) { if (wifiInfo.isValid()) {
mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), mStats.updateWifiState(extractDelta(wifiInfo));
modemInfo); } else {
} else { Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
Slog.e(TAG, "modem info is invalid: " + modemInfo); }
} }
if (modemInfo != null) {
if (modemInfo.isValid()) {
mStats.updateMobileRadioState(modemInfo);
} else {
Slog.e(TAG, "modem info is invalid: " + modemInfo);
} }
} }
} }