import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Display;
+
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
*
* New in version 19:
* - Wakelock data (wl) gets current and max times.
+ * New in version 20:
+ * - Sensor gets a background counter.
*/
static final String CHECKIN_VERSION = "20";
*/
// Magic sensor number for the GPS.
public static final int GPS = -10000;
-
+
public abstract int getHandle();
-
+
public abstract Timer getSensorTime();
+
+ /** Returns a counter for usage count when in the background. */
+ public abstract Counter getSensorBgCount();
}
public class Pid {
final Uid.Sensor se = sensors.valueAt(ise);
final int sensorNumber = sensors.keyAt(ise);
final Timer timer = se.getSensorTime();
+ final Counter bgCounter = se.getSensorBgCount();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
/ 1000;
final int count = timer.getCountLocked(which);
+ final int bgCount = bgCounter != null ? bgCounter.getCountLocked(which) : 0;
if (totalTime != 0) {
- dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
+ dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count,
+ bgCount);
}
}
}
sb.append(": ");
final Timer timer = se.getSensorTime();
+ final Counter bgCounter = se.getSensorBgCount();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(
rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
+ final int bgCount = bgCounter != null ? bgCounter.getCountLocked(which) : 0;
//timer.logState();
if (totalTime != 0) {
formatTimeMs(sb, totalTime);
sb.append("realtime (");
sb.append(count);
- sb.append(" times)");
+ sb.append(" times");
+ if (bgCount > 0) {
+ sb.append(", ");
+ sb.append(bgCount);
+ sb.append(" bg");
+ }
+ sb.append(")");
} else {
sb.append("(not used)");
}
final int mHandle;
StopwatchTimer mTimer;
+ Counter mBgCounter;
+
public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
mBsi = bsi;
mUid = uid;
return new StopwatchTimer(mBsi.mClocks, mUid, 0, pool, timeBase, in);
}
+ private Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
+ if (in.readInt() == 0) {
+ return null;
+ }
+ return new Counter(timeBase, in);
+ }
+
boolean reset() {
+ if (mBgCounter != null) {
+ mBgCounter.reset(true);
+ }
if (mTimer.reset(true)) {
mTimer = null;
return true;
void readFromParcelLocked(TimeBase timeBase, Parcel in) {
mTimer = readTimerFromParcel(timeBase, in);
+ mBgCounter = readCounterFromParcel(timeBase, in);
}
void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
+ Counter.writeCounterToParcel(out, mBgCounter);
}
@Override
}
@Override
+ public Counter getSensorBgCount() {
+ return mBgCounter;
+ }
+
+ @Override
public int getHandle() {
return mHandle;
}
return t;
}
+ public Counter getSensorBgCounterLocked(int sensor, boolean create) {
+ Sensor se = mSensorStats.get(sensor);
+ if (se == null) {
+ if (!create) {
+ return null;
+ }
+ se = new Sensor(mBsi, this, sensor);
+ mSensorStats.put(sensor, se);
+ }
+ Counter c = se.mBgCounter;
+ if (c != null) return c;
+ c = new Counter(mBsi.mOnBatteryTimeBase);
+ se.mBgCounter = c;
+ return c;
+ }
+
public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
StopwatchTimer t = mSyncStats.startObject(name);
if (t != null) {
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
+ Counter c = getSensorBgCounterLocked(sensor, true);
+ if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+ c.stepAtomic();
+ }
}
public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
+ Counter c = getSensorBgCounterLocked(Sensor.GPS, true);
+ if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+ c.stepAtomic();
+ }
}
public void noteStopGps(long elapsedRealtimeMs) {
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.internal.os;
+
+import android.app.ActivityManager;
+import android.os.BatteryStats;
+import android.os.Debug;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+/**
+ * Test BatteryStatsImpl Sensor Timers.
+ */
+public class BatteryStatsSensorTest extends TestCase {
+
+ private static final int UID = 10500;
+ private static final int SENSOR_ID = -10000;
+
+ @SmallTest
+ public void testSensorStartStop() throws Exception {
+ final MockClocks clocks = new MockClocks();
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+ bi.mForceOnBattery = true;
+ clocks.realtime = 100;
+ clocks.uptime = 100;
+ bi.getOnBatteryTimeBase().setRunning(true, 100, 100);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ bi.noteStartSensorLocked(UID, SENSOR_ID);
+ clocks.realtime = 200;
+ clocks.uptime = 200;
+ bi.noteStopSensorLocked(UID, SENSOR_ID);
+
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_RECEIVER);
+ bi.noteStartSensorLocked(UID, SENSOR_ID);
+ clocks.realtime = 400;
+ clocks.uptime = 400;
+ bi.noteStopSensorLocked(UID, SENSOR_ID);
+
+ BatteryStats.Timer sensorTimer = bi.getUidStats().get(UID).getSensorStats()
+ .get(SENSOR_ID).getSensorTime();
+ BatteryStats.Counter sensorBgCounter = bi.getUidStats().get(UID).getSensorStats()
+ .get(SENSOR_ID).getSensorBgCount();
+
+ assertEquals(2, sensorTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(300000,
+ sensorTimer.getTotalTimeLocked(clocks.realtime, BatteryStats.STATS_SINCE_CHARGED));
+
+ assertEquals(1, sensorBgCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ }
+}
BatteryStatsTimeBaseTest.class,
BatteryStatsTimerTest.class,
BatteryStatsUidTest.class,
+ BatteryStatsSensorTest.class,
})
public class BatteryStatsTests {
}
package com.android.internal.os;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-
-import android.os.BatteryStats;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import com.android.internal.os.BatteryStatsImpl;
-
-import org.mockito.Mockito;
-
/**
* Mocks a BatteryStatsImpl object.
*/
public class MockBatteryStatsImpl extends BatteryStatsImpl {
public BatteryStatsImpl.Clocks clocks;
+ public boolean mForceOnBattery;
- MockBatteryStatsImpl() {
- super(new MockClocks());
+ MockBatteryStatsImpl(Clocks clocks) {
+ super(clocks);
this.clocks = mClocks;
}
+ MockBatteryStatsImpl() {
+ this(new MockClocks());
+ }
+
public TimeBase getOnBatteryTimeBase() {
return mOnBatteryTimeBase;
}
+ public boolean isOnBattery() {
+ return mForceOnBattery ? true : super.isOnBattery();
+ }
}