Loading core/java/com/android/internal/os/BatteryStatsImpl.java +100 −75 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 176 + (USE_OLD_HISTORY ? 1000 : 0); private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS; Loading Loading @@ -1551,27 +1551,31 @@ public class BatteryStatsImpl extends BatteryStats { } } @VisibleForTesting public static class LongSamplingCounter extends LongCounter implements TimeBaseObs { final TimeBase mTimeBase; long mCount; long mLoadedCount; long mUnpluggedCount; public long mCount; public long mCurrentCount; public long mLoadedCount; public long mUnpluggedCount; LongSamplingCounter(TimeBase timeBase, Parcel in) { public LongSamplingCounter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; mCount = in.readLong(); mCurrentCount = in.readLong(); mLoadedCount = in.readLong(); mUnpluggedCount = in.readLong(); timeBase.add(this); } LongSamplingCounter(TimeBase timeBase) { public LongSamplingCounter(TimeBase timeBase) { mTimeBase = timeBase; timeBase.add(this); } public void writeToParcel(Parcel out) { out.writeLong(mCount); out.writeLong(mCurrentCount); out.writeLong(mLoadedCount); out.writeLong(mUnpluggedCount); } Loading @@ -1598,24 +1602,37 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void logState(Printer pw, String prefix) { pw.println(prefix + "mCount=" + mCount + " mCurrentCount=" + mCurrentCount + " mLoadedCount=" + mLoadedCount + " mUnpluggedCount=" + mUnpluggedCount); } void addCountLocked(long count) { addCountLocked(count, mTimeBase.isRunning()); public void addCountLocked(long count) { update(mCurrentCount + count, mTimeBase.isRunning()); } public void addCountLocked(long count, boolean isRunning) { update(mCurrentCount + count, isRunning); } public void update(long count) { update(count, mTimeBase.isRunning()); } void addCountLocked(long count, boolean isRunning) { public void update(long count, boolean isRunning) { if (count < mCurrentCount) { mCurrentCount = 0; } if (isRunning) { mCount += count; mCount += count - mCurrentCount; } mCurrentCount = count; } /** * Clear state of this counter. */ void reset(boolean detachIfReset) { public void reset(boolean detachIfReset) { mCount = 0; mLoadedCount = mUnpluggedCount = 0; if (detachIfReset) { Loading @@ -1623,18 +1640,16 @@ public class BatteryStatsImpl extends BatteryStats { } } void detach() { public void detach() { mTimeBase.remove(this); } void writeSummaryFromParcelLocked(Parcel out) { public void writeSummaryFromParcelLocked(Parcel out) { out.writeLong(mCount); } void readSummaryFromParcelLocked(Parcel in) { mLoadedCount = in.readLong(); mCount = mLoadedCount; mUnpluggedCount = mLoadedCount; public void readSummaryFromParcelLocked(Parcel in) { mCount = mUnpluggedCount= mLoadedCount = in.readLong(); } } Loading Loading @@ -11603,10 +11618,6 @@ public class BatteryStatsImpl extends BatteryStats { } } // Cache last value for comparison. private BluetoothActivityEnergyInfo mLastBluetoothActivityEnergyInfo = new BluetoothActivityEnergyInfo(0, 0, 0, 0, 0, 0); /** * Add modem tx power to history * Device is said to be in high cellular transmit power when it has spent most of the transmit Loading Loading @@ -11645,8 +11656,35 @@ public class BatteryStatsImpl extends BatteryStats { return; } private final class BluetoothActivityInfoCache { long idleTimeMs; long rxTimeMs; long txTimeMs; long energy; SparseLongArray uidRxBytes = new SparseLongArray(); SparseLongArray uidTxBytes = new SparseLongArray(); void set(BluetoothActivityEnergyInfo info) { idleTimeMs = info.getControllerIdleTimeMillis(); rxTimeMs = info.getControllerRxTimeMillis(); txTimeMs = info.getControllerTxTimeMillis(); energy = info.getControllerEnergyUsed(); if (info.getUidTraffic() != null) { for (UidTraffic traffic : info.getUidTraffic()) { uidRxBytes.put(traffic.getUid(), traffic.getRxBytes()); uidTxBytes.put(traffic.getUid(), traffic.getTxBytes()); } } } } private final BluetoothActivityInfoCache mLastBluetoothActivityInfo = new BluetoothActivityInfoCache(); /** * Distribute Bluetooth energy info and network traffic to apps. * * @param info The energy information from the bluetooth controller. */ public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) { Loading @@ -11661,12 +11699,13 @@ public class BatteryStatsImpl extends BatteryStats { mHasBluetoothReporting = true; final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final long rxTimeMs = info.getControllerRxTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerRxTimeMillis(); final long txTimeMs = info.getControllerTxTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerTxTimeMillis(); final long idleTimeMs = info.getControllerIdleTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerIdleTimeMillis(); final long rxTimeMs = info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs; final long txTimeMs = info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs; final long idleTimeMs = info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs; if (DEBUG_ENERGY) { Slog.d(TAG, "------ BEGIN BLE power blaming ------"); Slog.d(TAG, " Tx Time: " + txTimeMs + " ms"); Loading Loading @@ -11738,8 +11777,8 @@ public class BatteryStatsImpl extends BatteryStats { } if (DEBUG_ENERGY) { Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX=" + leftOverTxTimeMs); Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX=" + leftOverTxTimeMs); } // Loading @@ -11750,70 +11789,56 @@ public class BatteryStatsImpl extends BatteryStats { long totalRxBytes = 0; final UidTraffic[] uidTraffic = info.getUidTraffic(); final UidTraffic[] lastUidTraffic = mLastBluetoothActivityEnergyInfo.getUidTraffic(); final ArrayList<UidTraffic> deltaTraffic = new ArrayList<>(); int m = 0, n = 0; for (; m < uidTraffic.length && n < lastUidTraffic.length; m++) { final UidTraffic traffic = uidTraffic[m]; final UidTraffic lastTraffic = lastUidTraffic[n]; if (traffic.getUid() == lastTraffic.getUid()) { deltaTraffic.add(new UidTraffic(traffic.getUid(), traffic.getRxBytes() - lastTraffic.getRxBytes(), traffic.getTxBytes() - lastTraffic.getTxBytes())); n++; } } for (; m < uidTraffic.length; m ++) { deltaTraffic.add(uidTraffic[m]); } for (int i = 0, j = 0; i < deltaTraffic.size(); i++) { final UidTraffic traffic = deltaTraffic.get(i); final int numUids = uidTraffic != null ? uidTraffic.length : 0; for (int i = 0; i < numUids; i++) { final UidTraffic traffic = uidTraffic[i]; final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get( traffic.getUid()); final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get( traffic.getUid()); // Add to the global counters. mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked( traffic.getRxBytes()); mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked( traffic.getTxBytes()); mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes); mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes); // Add to the UID counters. final Uid u = getUidStatsLocked(mapUid(traffic.getUid())); u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0); u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0); u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0); u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0); // Calculate the total traffic. totalTxBytes += traffic.getTxBytes(); totalRxBytes += traffic.getRxBytes(); totalRxBytes += rxBytes; totalTxBytes += txBytes; } if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) { for (int i = 0; i < deltaTraffic.size(); i++) { final UidTraffic traffic = deltaTraffic.get(i); final Uid u = getUidStatsLocked(mapUid(traffic.getUid())); if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) { for (int i = 0; i < numUids; i++) { final UidTraffic traffic = uidTraffic[i]; final int uid = traffic.getUid(); final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid); final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid); final Uid u = getUidStatsLocked(mapUid(uid)); final ControllerActivityCounterImpl counter = u.getOrCreateBluetoothControllerActivityLocked(); if (totalRxBytes > 0 && traffic.getRxBytes() > 0) { final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes; if (totalRxBytes > 0 && rxBytes > 0) { final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes; if (DEBUG_ENERGY) { Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes() + " rx_time=" + timeRxMs); Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs); } counter.getRxTimeCounter().addCountLocked(timeRxMs); leftOverRxTimeMs -= timeRxMs; } if (totalTxBytes > 0 && traffic.getTxBytes() > 0) { final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes; if (totalTxBytes > 0 && txBytes > 0) { final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes; if (DEBUG_ENERGY) { Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes() + " tx_time=" + timeTxMs); Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs); } counter.getTxTimeCounters()[0].addCountLocked(timeTxMs); leftOverTxTimeMs -= timeTxMs; } Loading @@ -11830,10 +11855,10 @@ public class BatteryStatsImpl extends BatteryStats { if (opVolt != 0) { // We store the power drain as mAms. mBluetoothActivity.getPowerCounter().addCountLocked( (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityEnergyInfo.getControllerEnergyUsed() )/ opVolt)); (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy) / opVolt)); } mLastBluetoothActivityEnergyInfo = info; mLastBluetoothActivityInfo.set(info); } /** Loading core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import org.junit.runners.Suite; KernelUidCpuActiveTimeReaderTest.class, KernelUidCpuClusterTimeReaderTest.class, KernelWakelockReaderTest.class, LongSamplingCounterTest.class, LongSamplingCounterArrayTest.class, PowerCalculatorTest.class, PowerProfileTest.class Loading core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java 0 → 100644 +194 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import static android.os.BatteryStats.STATS_SINCE_CHARGED; import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounter; import static com.android.internal.os.BatteryStatsImpl.TimeBase; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.os.Parcel; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; /** * Test class for {@link LongSamplingCounter}. * * To run the tests, use * * bit FrameworksCoreTests:com.android.internal.os.LongSamplingCounterTest */ @SmallTest @RunWith(AndroidJUnit4.class) public class LongSamplingCounterTest { private static final long COUNT = 1111; private static final long CURRENT_COUNT = 5555; @Mock private TimeBase mTimeBase; private LongSamplingCounter mCounter; @Before public void setUp() { MockitoAnnotations.initMocks(this); mCounter = new LongSamplingCounter(mTimeBase); Mockito.reset(mTimeBase); } @Test public void testReadWriteParcel() { final Parcel parcel = Parcel.obtain(); updateCounts(COUNT, CURRENT_COUNT); mCounter.writeToParcel(parcel); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. updateCounts(0, 0); mCounter = new LongSamplingCounter(mTimeBase, parcel); assertEquals(COUNT, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); parcel.recycle(); } @Test public void testReadWriteSummaryParcel() { final Parcel parcel = Parcel.obtain(); updateCounts(COUNT, CURRENT_COUNT); mCounter.writeSummaryFromParcelLocked(parcel); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. updateCounts(0, 0); mCounter.readSummaryFromParcelLocked(parcel); assertEquals(COUNT, mCounter.mCount); parcel.recycle(); } @Test public void testOnTimeStarted() { updateCounts(COUNT, CURRENT_COUNT); mCounter.onTimeStarted(0, 0, 0); assertEquals(COUNT, mCounter.mCount); assertEquals(COUNT, mCounter.mUnpluggedCount); } @Test public void testOnTimeStopped() { updateCounts(COUNT, CURRENT_COUNT); mCounter.onTimeStopped(0, 0, 0); assertEquals(COUNT, mCounter.mCount); } @Test public void testAddCountLocked() { updateCounts(0, 0); assertEquals(0, mCounter.getCountLocked(0)); when(mTimeBase.isRunning()).thenReturn(true); mCounter.addCountLocked(111); assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(111, mCounter.mCurrentCount); mCounter.addCountLocked(222); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(333, mCounter.mCurrentCount); when(mTimeBase.isRunning()).thenReturn(false); mCounter.addCountLocked(456); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(789, mCounter.mCurrentCount); mCounter.addCountLocked(444, true); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1233, mCounter.mCurrentCount); mCounter.addCountLocked(567, false); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1800, mCounter.mCurrentCount); } @Test public void testUpdate() { updateCounts(0, 0); assertEquals(0, mCounter.getCountLocked(0)); when(mTimeBase.isRunning()).thenReturn(true); mCounter.update(111); assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(111, mCounter.mCurrentCount); mCounter.update(333); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(333, mCounter.mCurrentCount); when(mTimeBase.isRunning()).thenReturn(false); mCounter.update(789); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(789, mCounter.mCurrentCount); mCounter.update(100); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(100, mCounter.mCurrentCount); mCounter.update(544, true); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(544, mCounter.mCurrentCount); mCounter.update(1544, false); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1544, mCounter.mCurrentCount); } @Test public void testReset() { updateCounts(COUNT, CURRENT_COUNT); // Test with detachIfReset=false mCounter.reset(false /* detachIfReset */); assertEquals(0, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); verifyZeroInteractions(mTimeBase); updateCounts(COUNT, CURRENT_COUNT); // Test with detachIfReset=true mCounter.reset(true /* detachIfReset */); assertEquals(0, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); verify(mTimeBase).remove(mCounter); verifyNoMoreInteractions(mTimeBase); } @Test public void testDetach() { mCounter.detach(); verify(mTimeBase).remove(mCounter); verifyNoMoreInteractions(mTimeBase); } private void updateCounts(long total, long current) { mCounter.mCount = total; mCounter.mCurrentCount = current; } } services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +25 −21 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mUseLatestStates = true; } try { synchronized (mWorkerLock) { if (DEBUG) { Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason); Loading @@ -308,6 +309,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } mStats.clearPendingRemovedUids(); } } catch (Exception e) { Slog.wtf(TAG, "Error updating external stats: ", e); } } }; Loading Loading @@ -398,7 +402,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); } else { Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo); Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo); } } } Loading @@ -410,7 +414,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (wifiInfo.isValid()) { mStats.updateWifiState(extractDeltaLocked(wifiInfo)); } else { Slog.e(TAG, "wifi info is invalid: " + wifiInfo); Slog.w(TAG, "wifi info is invalid: " + wifiInfo); } } Loading @@ -418,7 +422,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (modemInfo.isValid()) { mStats.updateMobileRadioState(modemInfo); } else { Slog.e(TAG, "modem info is invalid: " + modemInfo); Slog.w(TAG, "modem info is invalid: " + modemInfo); } } } Loading Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +100 −75 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 176 + (USE_OLD_HISTORY ? 1000 : 0); private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS; Loading Loading @@ -1551,27 +1551,31 @@ public class BatteryStatsImpl extends BatteryStats { } } @VisibleForTesting public static class LongSamplingCounter extends LongCounter implements TimeBaseObs { final TimeBase mTimeBase; long mCount; long mLoadedCount; long mUnpluggedCount; public long mCount; public long mCurrentCount; public long mLoadedCount; public long mUnpluggedCount; LongSamplingCounter(TimeBase timeBase, Parcel in) { public LongSamplingCounter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; mCount = in.readLong(); mCurrentCount = in.readLong(); mLoadedCount = in.readLong(); mUnpluggedCount = in.readLong(); timeBase.add(this); } LongSamplingCounter(TimeBase timeBase) { public LongSamplingCounter(TimeBase timeBase) { mTimeBase = timeBase; timeBase.add(this); } public void writeToParcel(Parcel out) { out.writeLong(mCount); out.writeLong(mCurrentCount); out.writeLong(mLoadedCount); out.writeLong(mUnpluggedCount); } Loading @@ -1598,24 +1602,37 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void logState(Printer pw, String prefix) { pw.println(prefix + "mCount=" + mCount + " mCurrentCount=" + mCurrentCount + " mLoadedCount=" + mLoadedCount + " mUnpluggedCount=" + mUnpluggedCount); } void addCountLocked(long count) { addCountLocked(count, mTimeBase.isRunning()); public void addCountLocked(long count) { update(mCurrentCount + count, mTimeBase.isRunning()); } public void addCountLocked(long count, boolean isRunning) { update(mCurrentCount + count, isRunning); } public void update(long count) { update(count, mTimeBase.isRunning()); } void addCountLocked(long count, boolean isRunning) { public void update(long count, boolean isRunning) { if (count < mCurrentCount) { mCurrentCount = 0; } if (isRunning) { mCount += count; mCount += count - mCurrentCount; } mCurrentCount = count; } /** * Clear state of this counter. */ void reset(boolean detachIfReset) { public void reset(boolean detachIfReset) { mCount = 0; mLoadedCount = mUnpluggedCount = 0; if (detachIfReset) { Loading @@ -1623,18 +1640,16 @@ public class BatteryStatsImpl extends BatteryStats { } } void detach() { public void detach() { mTimeBase.remove(this); } void writeSummaryFromParcelLocked(Parcel out) { public void writeSummaryFromParcelLocked(Parcel out) { out.writeLong(mCount); } void readSummaryFromParcelLocked(Parcel in) { mLoadedCount = in.readLong(); mCount = mLoadedCount; mUnpluggedCount = mLoadedCount; public void readSummaryFromParcelLocked(Parcel in) { mCount = mUnpluggedCount= mLoadedCount = in.readLong(); } } Loading Loading @@ -11603,10 +11618,6 @@ public class BatteryStatsImpl extends BatteryStats { } } // Cache last value for comparison. private BluetoothActivityEnergyInfo mLastBluetoothActivityEnergyInfo = new BluetoothActivityEnergyInfo(0, 0, 0, 0, 0, 0); /** * Add modem tx power to history * Device is said to be in high cellular transmit power when it has spent most of the transmit Loading Loading @@ -11645,8 +11656,35 @@ public class BatteryStatsImpl extends BatteryStats { return; } private final class BluetoothActivityInfoCache { long idleTimeMs; long rxTimeMs; long txTimeMs; long energy; SparseLongArray uidRxBytes = new SparseLongArray(); SparseLongArray uidTxBytes = new SparseLongArray(); void set(BluetoothActivityEnergyInfo info) { idleTimeMs = info.getControllerIdleTimeMillis(); rxTimeMs = info.getControllerRxTimeMillis(); txTimeMs = info.getControllerTxTimeMillis(); energy = info.getControllerEnergyUsed(); if (info.getUidTraffic() != null) { for (UidTraffic traffic : info.getUidTraffic()) { uidRxBytes.put(traffic.getUid(), traffic.getRxBytes()); uidTxBytes.put(traffic.getUid(), traffic.getTxBytes()); } } } } private final BluetoothActivityInfoCache mLastBluetoothActivityInfo = new BluetoothActivityInfoCache(); /** * Distribute Bluetooth energy info and network traffic to apps. * * @param info The energy information from the bluetooth controller. */ public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) { Loading @@ -11661,12 +11699,13 @@ public class BatteryStatsImpl extends BatteryStats { mHasBluetoothReporting = true; final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final long rxTimeMs = info.getControllerRxTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerRxTimeMillis(); final long txTimeMs = info.getControllerTxTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerTxTimeMillis(); final long idleTimeMs = info.getControllerIdleTimeMillis() - mLastBluetoothActivityEnergyInfo.getControllerIdleTimeMillis(); final long rxTimeMs = info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs; final long txTimeMs = info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs; final long idleTimeMs = info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs; if (DEBUG_ENERGY) { Slog.d(TAG, "------ BEGIN BLE power blaming ------"); Slog.d(TAG, " Tx Time: " + txTimeMs + " ms"); Loading Loading @@ -11738,8 +11777,8 @@ public class BatteryStatsImpl extends BatteryStats { } if (DEBUG_ENERGY) { Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX=" + leftOverTxTimeMs); Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX=" + leftOverTxTimeMs); } // Loading @@ -11750,70 +11789,56 @@ public class BatteryStatsImpl extends BatteryStats { long totalRxBytes = 0; final UidTraffic[] uidTraffic = info.getUidTraffic(); final UidTraffic[] lastUidTraffic = mLastBluetoothActivityEnergyInfo.getUidTraffic(); final ArrayList<UidTraffic> deltaTraffic = new ArrayList<>(); int m = 0, n = 0; for (; m < uidTraffic.length && n < lastUidTraffic.length; m++) { final UidTraffic traffic = uidTraffic[m]; final UidTraffic lastTraffic = lastUidTraffic[n]; if (traffic.getUid() == lastTraffic.getUid()) { deltaTraffic.add(new UidTraffic(traffic.getUid(), traffic.getRxBytes() - lastTraffic.getRxBytes(), traffic.getTxBytes() - lastTraffic.getTxBytes())); n++; } } for (; m < uidTraffic.length; m ++) { deltaTraffic.add(uidTraffic[m]); } for (int i = 0, j = 0; i < deltaTraffic.size(); i++) { final UidTraffic traffic = deltaTraffic.get(i); final int numUids = uidTraffic != null ? uidTraffic.length : 0; for (int i = 0; i < numUids; i++) { final UidTraffic traffic = uidTraffic[i]; final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get( traffic.getUid()); final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get( traffic.getUid()); // Add to the global counters. mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked( traffic.getRxBytes()); mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked( traffic.getTxBytes()); mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes); mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes); // Add to the UID counters. final Uid u = getUidStatsLocked(mapUid(traffic.getUid())); u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0); u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0); u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0); u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0); // Calculate the total traffic. totalTxBytes += traffic.getTxBytes(); totalRxBytes += traffic.getRxBytes(); totalRxBytes += rxBytes; totalTxBytes += txBytes; } if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) { for (int i = 0; i < deltaTraffic.size(); i++) { final UidTraffic traffic = deltaTraffic.get(i); final Uid u = getUidStatsLocked(mapUid(traffic.getUid())); if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) { for (int i = 0; i < numUids; i++) { final UidTraffic traffic = uidTraffic[i]; final int uid = traffic.getUid(); final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid); final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid); final Uid u = getUidStatsLocked(mapUid(uid)); final ControllerActivityCounterImpl counter = u.getOrCreateBluetoothControllerActivityLocked(); if (totalRxBytes > 0 && traffic.getRxBytes() > 0) { final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes; if (totalRxBytes > 0 && rxBytes > 0) { final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes; if (DEBUG_ENERGY) { Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes() + " rx_time=" + timeRxMs); Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs); } counter.getRxTimeCounter().addCountLocked(timeRxMs); leftOverRxTimeMs -= timeRxMs; } if (totalTxBytes > 0 && traffic.getTxBytes() > 0) { final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes; if (totalTxBytes > 0 && txBytes > 0) { final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes; if (DEBUG_ENERGY) { Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes() + " tx_time=" + timeTxMs); Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs); } counter.getTxTimeCounters()[0].addCountLocked(timeTxMs); leftOverTxTimeMs -= timeTxMs; } Loading @@ -11830,10 +11855,10 @@ public class BatteryStatsImpl extends BatteryStats { if (opVolt != 0) { // We store the power drain as mAms. mBluetoothActivity.getPowerCounter().addCountLocked( (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityEnergyInfo.getControllerEnergyUsed() )/ opVolt)); (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy) / opVolt)); } mLastBluetoothActivityEnergyInfo = info; mLastBluetoothActivityInfo.set(info); } /** Loading
core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import org.junit.runners.Suite; KernelUidCpuActiveTimeReaderTest.class, KernelUidCpuClusterTimeReaderTest.class, KernelWakelockReaderTest.class, LongSamplingCounterTest.class, LongSamplingCounterArrayTest.class, PowerCalculatorTest.class, PowerProfileTest.class Loading
core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java 0 → 100644 +194 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import static android.os.BatteryStats.STATS_SINCE_CHARGED; import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounter; import static com.android.internal.os.BatteryStatsImpl.TimeBase; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.os.Parcel; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; /** * Test class for {@link LongSamplingCounter}. * * To run the tests, use * * bit FrameworksCoreTests:com.android.internal.os.LongSamplingCounterTest */ @SmallTest @RunWith(AndroidJUnit4.class) public class LongSamplingCounterTest { private static final long COUNT = 1111; private static final long CURRENT_COUNT = 5555; @Mock private TimeBase mTimeBase; private LongSamplingCounter mCounter; @Before public void setUp() { MockitoAnnotations.initMocks(this); mCounter = new LongSamplingCounter(mTimeBase); Mockito.reset(mTimeBase); } @Test public void testReadWriteParcel() { final Parcel parcel = Parcel.obtain(); updateCounts(COUNT, CURRENT_COUNT); mCounter.writeToParcel(parcel); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. updateCounts(0, 0); mCounter = new LongSamplingCounter(mTimeBase, parcel); assertEquals(COUNT, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); parcel.recycle(); } @Test public void testReadWriteSummaryParcel() { final Parcel parcel = Parcel.obtain(); updateCounts(COUNT, CURRENT_COUNT); mCounter.writeSummaryFromParcelLocked(parcel); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. updateCounts(0, 0); mCounter.readSummaryFromParcelLocked(parcel); assertEquals(COUNT, mCounter.mCount); parcel.recycle(); } @Test public void testOnTimeStarted() { updateCounts(COUNT, CURRENT_COUNT); mCounter.onTimeStarted(0, 0, 0); assertEquals(COUNT, mCounter.mCount); assertEquals(COUNT, mCounter.mUnpluggedCount); } @Test public void testOnTimeStopped() { updateCounts(COUNT, CURRENT_COUNT); mCounter.onTimeStopped(0, 0, 0); assertEquals(COUNT, mCounter.mCount); } @Test public void testAddCountLocked() { updateCounts(0, 0); assertEquals(0, mCounter.getCountLocked(0)); when(mTimeBase.isRunning()).thenReturn(true); mCounter.addCountLocked(111); assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(111, mCounter.mCurrentCount); mCounter.addCountLocked(222); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(333, mCounter.mCurrentCount); when(mTimeBase.isRunning()).thenReturn(false); mCounter.addCountLocked(456); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(789, mCounter.mCurrentCount); mCounter.addCountLocked(444, true); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1233, mCounter.mCurrentCount); mCounter.addCountLocked(567, false); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1800, mCounter.mCurrentCount); } @Test public void testUpdate() { updateCounts(0, 0); assertEquals(0, mCounter.getCountLocked(0)); when(mTimeBase.isRunning()).thenReturn(true); mCounter.update(111); assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(111, mCounter.mCurrentCount); mCounter.update(333); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(333, mCounter.mCurrentCount); when(mTimeBase.isRunning()).thenReturn(false); mCounter.update(789); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(789, mCounter.mCurrentCount); mCounter.update(100); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(100, mCounter.mCurrentCount); mCounter.update(544, true); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(544, mCounter.mCurrentCount); mCounter.update(1544, false); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1544, mCounter.mCurrentCount); } @Test public void testReset() { updateCounts(COUNT, CURRENT_COUNT); // Test with detachIfReset=false mCounter.reset(false /* detachIfReset */); assertEquals(0, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); verifyZeroInteractions(mTimeBase); updateCounts(COUNT, CURRENT_COUNT); // Test with detachIfReset=true mCounter.reset(true /* detachIfReset */); assertEquals(0, mCounter.mCount); assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); verify(mTimeBase).remove(mCounter); verifyNoMoreInteractions(mTimeBase); } @Test public void testDetach() { mCounter.detach(); verify(mTimeBase).remove(mCounter); verifyNoMoreInteractions(mTimeBase); } private void updateCounts(long total, long current) { mCounter.mCount = total; mCounter.mCurrentCount = current; } }
services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +25 −21 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mUseLatestStates = true; } try { synchronized (mWorkerLock) { if (DEBUG) { Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason); Loading @@ -308,6 +309,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } mStats.clearPendingRemovedUids(); } } catch (Exception e) { Slog.wtf(TAG, "Error updating external stats: ", e); } } }; Loading Loading @@ -398,7 +402,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); } else { Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo); Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo); } } } Loading @@ -410,7 +414,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (wifiInfo.isValid()) { mStats.updateWifiState(extractDeltaLocked(wifiInfo)); } else { Slog.e(TAG, "wifi info is invalid: " + wifiInfo); Slog.w(TAG, "wifi info is invalid: " + wifiInfo); } } Loading @@ -418,7 +422,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (modemInfo.isValid()) { mStats.updateMobileRadioState(modemInfo); } else { Slog.e(TAG, "modem info is invalid: " + modemInfo); Slog.w(TAG, "modem info is invalid: " + modemInfo); } } } Loading