Loading core/java/android/os/WorkSource.java +30 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,29 @@ public class WorkSource implements Parcelable { return mChains; } /** * DO NOT USE: Hacky API provided solely for {@code GnssLocationProvider}. See * {@code setReturningDiffs} as well. * * @hide */ public void transferWorkChains(WorkSource other) { if (mChains != null) { mChains.clear(); } if (other.mChains == null || other.mChains.isEmpty()) { return; } if (mChains == null) { mChains = new ArrayList<>(4); } mChains.addAll(other.mChains); other.mChains.clear(); } private boolean removeUids(WorkSource other) { int N1 = mNum; final int[] uids1 = mUids; Loading Loading @@ -880,6 +903,13 @@ public class WorkSource implements Parcelable { return mUids[0]; } /** * Return the tag associated with the attribution UID. See (@link #getAttributionUid}. */ public String getAttributionTag() { return mTags[0]; } // TODO: The following three trivial getters are purely for testing and will be removed // once we have higher level logic in place, e.g for serializing this WorkChain to a proto, // diffing it etc. Loading core/java/com/android/internal/app/IBatteryStats.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -91,8 +91,7 @@ interface IBatteryStats { void noteVibratorOn(int uid, long durationMillis); void noteVibratorOff(int uid); void noteStartGps(int uid); void noteStopGps(int uid); void noteGpsChanged(in WorkSource oldSource, in WorkSource newSource); void noteGpsSignalQuality(int signalLevel); void noteScreenState(int state); void noteScreenBrightness(int brightness); Loading core/java/com/android/internal/os/BatteryStatsImpl.java +51 −15 Original line number Diff line number Diff line Loading @@ -4587,8 +4587,35 @@ public class BatteryStatsImpl extends BatteryStats { int mGpsNesting; public void noteStartGpsLocked(int uid) { uid = mapUid(uid); public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) { for (int i = 0; i < newWs.size(); ++i) { noteStartGpsLocked(newWs.get(i), null); } for (int i = 0; i < oldWs.size(); ++i) { noteStopGpsLocked((oldWs.get(i)), null); } List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs); if (wcs != null) { if (wcs[0] != null) { final List<WorkChain> newChains = wcs[0]; for (int i = 0; i < newChains.size(); ++i) { noteStartGpsLocked(-1, newChains.get(i)); } } if (wcs[1] != null) { final List<WorkChain> goneChains = wcs[1]; for (int i = 0; i < goneChains.size(); ++i) { noteStopGpsLocked(-1, goneChains.get(i)); } } } } private void noteStartGpsLocked(int uid, WorkChain workChain) { uid = getAttributionUid(uid, workChain); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); if (mGpsNesting == 0) { Loading @@ -4598,11 +4625,19 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); } mGpsNesting++; if (workChain == null) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 1); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), 1); } getUidStatsLocked(uid).noteStartGps(elapsedRealtime); } public void noteStopGpsLocked(int uid) { uid = mapUid(uid); private void noteStopGpsLocked(int uid, WorkChain workChain) { uid = getAttributionUid(uid, workChain); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); mGpsNesting--; Loading @@ -4614,6 +4649,14 @@ public class BatteryStatsImpl extends BatteryStats { stopAllGpsSignalQualityTimersLocked(-1); mGpsSignalQualityBin = -1; } if (workChain == null) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 0); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), 0); } getUidStatsLocked(uid).noteStopGps(elapsedRealtime); } Loading Loading @@ -9842,9 +9885,7 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStartSensor(int sensor, long elapsedRealtimeMs) { DualTimer t = getSensorTimerLocked(sensor, /* create= */ true); t.startRunningLocked(elapsedRealtimeMs); if (sensor == Sensor.GPS) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null, 1); } else { if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor, 1); } Loading @@ -9855,17 +9896,12 @@ public class BatteryStatsImpl extends BatteryStats { DualTimer t = getSensorTimerLocked(sensor, false); if (t != null) { t.stopRunningLocked(elapsedRealtimeMs); if (!t.isRunningLocked()) { // only tell statsd if truly stopped if (sensor == Sensor.GPS) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null, 0); } else { if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor, 0); } } } } public void noteStartGps(long elapsedRealtimeMs) { noteStartSensor(Sensor.GPS, elapsedRealtimeMs); Loading core/tests/coretests/src/android/os/WorkSourceTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,15 @@ public class WorkSourceTest extends TestCase { assertEquals(100, wc.getAttributionUid()); } public void testGetAttributionTag() { WorkSource ws1 = new WorkSource(); WorkChain wc = ws1.createWorkChain(); wc.addNode(100, "tag"); assertEquals("tag", wc.getAttributionTag()); wc.addNode(200, "tag2"); assertEquals("tag", wc.getAttributionTag()); } public void testRemove_fromChainedWorkSource() { WorkSource ws1 = new WorkSource(); ws1.createWorkChain().addNode(50, "foo"); Loading @@ -368,4 +377,25 @@ public class WorkSourceTest extends TestCase { assertEquals(1, ws1.getWorkChains().size()); assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid()); } public void testTransferWorkChains() { WorkSource ws1 = new WorkSource(); WorkChain wc1 = ws1.createWorkChain().addNode(100, "tag"); WorkChain wc2 = ws1.createWorkChain().addNode(200, "tag2"); WorkSource ws2 = new WorkSource(); ws2.transferWorkChains(ws1); assertEquals(0, ws1.getWorkChains().size()); assertEquals(2, ws2.getWorkChains().size()); assertSame(wc1, ws2.getWorkChains().get(0)); assertSame(wc2, ws2.getWorkChains().get(1)); ws1.clear(); ws1.createWorkChain().addNode(300, "tag3"); ws1.transferWorkChains(ws2); assertEquals(0, ws2.getWorkChains().size()); assertSame(wc1, ws1.getWorkChains().get(0)); assertSame(wc2, ws1.getWorkChains().get(1)); } } core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ import android.app.ActivityManager; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.Uid.Sensor; import android.os.WorkSource; import android.support.test.filters.SmallTest; import android.view.Display; import com.android.internal.os.BatteryStatsImpl.DualTimer; import com.android.internal.os.BatteryStatsImpl.Uid; import junit.framework.TestCase; Loading Loading @@ -446,4 +448,52 @@ public class BatteryStatsNoteTest extends TestCase { pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate"); assertEquals(0, pkg.getWakeupAlarmStats().size()); } @SmallTest public void testNoteGpsChanged() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.setRecordAllHistoryLocked(true); bi.forceRecordAllHistory(); bi.mForceOnBattery = true; bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); WorkSource ws = new WorkSource(); ws.add(UID); bi.noteGpsChangedLocked(new WorkSource(), ws); DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertNotNull(t); assertTrue(t.isRunningLocked()); bi.noteGpsChangedLocked(ws, new WorkSource()); t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertFalse(t.isRunningLocked()); } @SmallTest public void testNoteGpsChanged_workSource() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.setRecordAllHistoryLocked(true); bi.forceRecordAllHistory(); bi.mForceOnBattery = true; bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); WorkSource ws = new WorkSource(); ws.createWorkChain().addNode(UID, "com.foo"); bi.noteGpsChangedLocked(new WorkSource(), ws); DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertNotNull(t); assertTrue(t.isRunningLocked()); bi.noteGpsChangedLocked(ws, new WorkSource()); t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertFalse(t.isRunningLocked()); } } Loading
core/java/android/os/WorkSource.java +30 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,29 @@ public class WorkSource implements Parcelable { return mChains; } /** * DO NOT USE: Hacky API provided solely for {@code GnssLocationProvider}. See * {@code setReturningDiffs} as well. * * @hide */ public void transferWorkChains(WorkSource other) { if (mChains != null) { mChains.clear(); } if (other.mChains == null || other.mChains.isEmpty()) { return; } if (mChains == null) { mChains = new ArrayList<>(4); } mChains.addAll(other.mChains); other.mChains.clear(); } private boolean removeUids(WorkSource other) { int N1 = mNum; final int[] uids1 = mUids; Loading Loading @@ -880,6 +903,13 @@ public class WorkSource implements Parcelable { return mUids[0]; } /** * Return the tag associated with the attribution UID. See (@link #getAttributionUid}. */ public String getAttributionTag() { return mTags[0]; } // TODO: The following three trivial getters are purely for testing and will be removed // once we have higher level logic in place, e.g for serializing this WorkChain to a proto, // diffing it etc. Loading
core/java/com/android/internal/app/IBatteryStats.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -91,8 +91,7 @@ interface IBatteryStats { void noteVibratorOn(int uid, long durationMillis); void noteVibratorOff(int uid); void noteStartGps(int uid); void noteStopGps(int uid); void noteGpsChanged(in WorkSource oldSource, in WorkSource newSource); void noteGpsSignalQuality(int signalLevel); void noteScreenState(int state); void noteScreenBrightness(int brightness); Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +51 −15 Original line number Diff line number Diff line Loading @@ -4587,8 +4587,35 @@ public class BatteryStatsImpl extends BatteryStats { int mGpsNesting; public void noteStartGpsLocked(int uid) { uid = mapUid(uid); public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) { for (int i = 0; i < newWs.size(); ++i) { noteStartGpsLocked(newWs.get(i), null); } for (int i = 0; i < oldWs.size(); ++i) { noteStopGpsLocked((oldWs.get(i)), null); } List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs); if (wcs != null) { if (wcs[0] != null) { final List<WorkChain> newChains = wcs[0]; for (int i = 0; i < newChains.size(); ++i) { noteStartGpsLocked(-1, newChains.get(i)); } } if (wcs[1] != null) { final List<WorkChain> goneChains = wcs[1]; for (int i = 0; i < goneChains.size(); ++i) { noteStopGpsLocked(-1, goneChains.get(i)); } } } } private void noteStartGpsLocked(int uid, WorkChain workChain) { uid = getAttributionUid(uid, workChain); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); if (mGpsNesting == 0) { Loading @@ -4598,11 +4625,19 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); } mGpsNesting++; if (workChain == null) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 1); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), 1); } getUidStatsLocked(uid).noteStartGps(elapsedRealtime); } public void noteStopGpsLocked(int uid) { uid = mapUid(uid); private void noteStopGpsLocked(int uid, WorkChain workChain) { uid = getAttributionUid(uid, workChain); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); mGpsNesting--; Loading @@ -4614,6 +4649,14 @@ public class BatteryStatsImpl extends BatteryStats { stopAllGpsSignalQualityTimersLocked(-1); mGpsSignalQualityBin = -1; } if (workChain == null) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 0); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), 0); } getUidStatsLocked(uid).noteStopGps(elapsedRealtime); } Loading Loading @@ -9842,9 +9885,7 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStartSensor(int sensor, long elapsedRealtimeMs) { DualTimer t = getSensorTimerLocked(sensor, /* create= */ true); t.startRunningLocked(elapsedRealtimeMs); if (sensor == Sensor.GPS) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null, 1); } else { if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor, 1); } Loading @@ -9855,17 +9896,12 @@ public class BatteryStatsImpl extends BatteryStats { DualTimer t = getSensorTimerLocked(sensor, false); if (t != null) { t.stopRunningLocked(elapsedRealtimeMs); if (!t.isRunningLocked()) { // only tell statsd if truly stopped if (sensor == Sensor.GPS) { StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null, 0); } else { if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor, 0); } } } } public void noteStartGps(long elapsedRealtimeMs) { noteStartSensor(Sensor.GPS, elapsedRealtimeMs); Loading
core/tests/coretests/src/android/os/WorkSourceTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,15 @@ public class WorkSourceTest extends TestCase { assertEquals(100, wc.getAttributionUid()); } public void testGetAttributionTag() { WorkSource ws1 = new WorkSource(); WorkChain wc = ws1.createWorkChain(); wc.addNode(100, "tag"); assertEquals("tag", wc.getAttributionTag()); wc.addNode(200, "tag2"); assertEquals("tag", wc.getAttributionTag()); } public void testRemove_fromChainedWorkSource() { WorkSource ws1 = new WorkSource(); ws1.createWorkChain().addNode(50, "foo"); Loading @@ -368,4 +377,25 @@ public class WorkSourceTest extends TestCase { assertEquals(1, ws1.getWorkChains().size()); assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid()); } public void testTransferWorkChains() { WorkSource ws1 = new WorkSource(); WorkChain wc1 = ws1.createWorkChain().addNode(100, "tag"); WorkChain wc2 = ws1.createWorkChain().addNode(200, "tag2"); WorkSource ws2 = new WorkSource(); ws2.transferWorkChains(ws1); assertEquals(0, ws1.getWorkChains().size()); assertEquals(2, ws2.getWorkChains().size()); assertSame(wc1, ws2.getWorkChains().get(0)); assertSame(wc2, ws2.getWorkChains().get(1)); ws1.clear(); ws1.createWorkChain().addNode(300, "tag3"); ws1.transferWorkChains(ws2); assertEquals(0, ws2.getWorkChains().size()); assertSame(wc1, ws1.getWorkChains().get(0)); assertSame(wc2, ws1.getWorkChains().get(1)); } }
core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ import android.app.ActivityManager; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.Uid.Sensor; import android.os.WorkSource; import android.support.test.filters.SmallTest; import android.view.Display; import com.android.internal.os.BatteryStatsImpl.DualTimer; import com.android.internal.os.BatteryStatsImpl.Uid; import junit.framework.TestCase; Loading Loading @@ -446,4 +448,52 @@ public class BatteryStatsNoteTest extends TestCase { pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate"); assertEquals(0, pkg.getWakeupAlarmStats().size()); } @SmallTest public void testNoteGpsChanged() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.setRecordAllHistoryLocked(true); bi.forceRecordAllHistory(); bi.mForceOnBattery = true; bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); WorkSource ws = new WorkSource(); ws.add(UID); bi.noteGpsChangedLocked(new WorkSource(), ws); DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertNotNull(t); assertTrue(t.isRunningLocked()); bi.noteGpsChangedLocked(ws, new WorkSource()); t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertFalse(t.isRunningLocked()); } @SmallTest public void testNoteGpsChanged_workSource() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.setRecordAllHistoryLocked(true); bi.forceRecordAllHistory(); bi.mForceOnBattery = true; bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); WorkSource ws = new WorkSource(); ws.createWorkChain().addNode(UID, "com.foo"); bi.noteGpsChangedLocked(new WorkSource(), ws); DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertNotNull(t); assertTrue(t.isRunningLocked()); bi.noteGpsChangedLocked(ws, new WorkSource()); t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false); assertFalse(t.isRunningLocked()); } }