* @param providerName Name of provider that is requested (e.g. "gps").
* @param intervalMs The interval that is requested in ms.
*/
- public void startRequesting(String packageName, String providerName, long intervalMs) {
+ public void startRequesting(String packageName, String providerName, long intervalMs,
+ boolean isForeground) {
PackageProviderKey key = new PackageProviderKey(packageName, providerName);
PackageStatistics stats = statistics.get(key);
if (stats == null) {
statistics.put(key, stats);
}
stats.startRequesting(intervalMs);
+ stats.updateForeground(isForeground);
}
/**
PackageStatistics stats = statistics.get(key);
if (stats != null) {
stats.stopRequesting();
- } else {
- // This shouldn't be a possible code path.
- Log.e(TAG, "Couldn't find package statistics when removing location request.");
+ }
+ }
+
+ /**
+ * Signals that a package possibly switched background/foreground.
+ *
+ * @param packageName Name of package that has stopped requesting locations.
+ * @param providerName Provider that is no longer being requested.
+ */
+ public void updateForeground(String packageName, String providerName, boolean isForeground) {
+ PackageProviderKey key = new PackageProviderKey(packageName, providerName);
+ PackageStatistics stats = statistics.get(key);
+ if (stats != null) {
+ stats.updateForeground(isForeground);
}
}
// The total time this app has requested location (not including currently running requests).
private long mTotalDurationMs;
+ // Time when this package most recently went to foreground, requesting location. 0 means
+ // not currently in foreground.
+ private long mLastForegroundElapsedTimeMs;
+ // The time this app has requested location (not including currently running requests), while
+ // in foreground.
+ private long mForegroundDurationMs;
+
private PackageStatistics() {
mInitialElapsedTimeMs = SystemClock.elapsedRealtime();
mNumActiveRequests = 0;
mTotalDurationMs = 0;
mFastestIntervalMs = Long.MAX_VALUE;
mSlowestIntervalMs = 0;
+ mForegroundDurationMs = 0;
+ mLastForegroundElapsedTimeMs = 0;
}
private void startRequesting(long intervalMs) {
mNumActiveRequests++;
}
+ private void updateForeground(boolean isForeground) {
+ long nowElapsedTimeMs = SystemClock.elapsedRealtime();
+ // if previous interval was foreground, accumulate before resetting start
+ if (mLastForegroundElapsedTimeMs != 0) {
+ mForegroundDurationMs += (nowElapsedTimeMs - mLastForegroundElapsedTimeMs);
+ }
+ mLastForegroundElapsedTimeMs = isForeground ? nowElapsedTimeMs : 0;
+ }
+
private void stopRequesting() {
if (mNumActiveRequests <= 0) {
// Shouldn't be a possible code path
long lastDurationMs
= SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs;
mTotalDurationMs += lastDurationMs;
+ updateForeground(false);
}
}
}
/**
+ * Returns the duration that this request has been active.
+ */
+ public long getForegroundDurationMs() {
+ long currentDurationMs = mForegroundDurationMs;
+ if (mLastForegroundElapsedTimeMs != 0 ) {
+ currentDurationMs
+ += SystemClock.elapsedRealtime() - mLastForegroundElapsedTimeMs;
+ }
+ return currentDurationMs;
+ }
+
+ /**
* Returns the time since the initial request in ms.
*/
public long getTimeSinceFirstRequestMs() {
}
s.append(": Duration requested ")
.append((getDurationMs() / 1000) / 60)
- .append(" out of the last ")
+ .append(" total, ")
+ .append((getForegroundDurationMs() / 1000) / 60)
+ .append(" foreground, out of the last ")
.append((getTimeSinceFirstRequestMs() / 1000) / 60)
.append(" minutes");
if (isActive()) {
* Tests that adding a single package works correctly.
*/
public void testSinglePackage() {
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
assertEquals(1, mStatistics.statistics.size());
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
* Tests that adding a single package works correctly when it is stopped and restarted.
*/
public void testSinglePackage_stopAndRestart() {
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
assertEquals(1, mStatistics.statistics.size());
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
* Tests that adding a single package works correctly when multiple intervals are used.
*/
public void testSinglePackage_multipleIntervals() {
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL2);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL2, true);
assertEquals(1, mStatistics.statistics.size());
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
* Tests that adding a single package works correctly when multiple providers are used.
*/
public void testSinglePackage_multipleProviders() {
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
- mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
assertEquals(2, mStatistics.statistics.size());
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
* Tests that adding multiple packages works correctly.
*/
public void testMultiplePackages() {
- mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
- mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1);
- mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2);
- mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
+ mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1, true);
assertEquals(3, mStatistics.statistics.size());
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
assertFalse(stats3.isActive());
}
+ /**
+ * Tests that switching foreground & background states accmulates time reasonably.
+ */
+ public void testForegroundBackground() {
+ mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1, true);
+ mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1, false);
+
+ mStatistics.updateForeground(PACKAGE1, PROVIDER2, false);
+ mStatistics.updateForeground(PACKAGE2, PROVIDER1, true);
+
+ mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
+
+ for (PackageStatistics stats : mStatistics.statistics.values()) {
+ verifyStatisticsTimes(stats);
+ }
+ }
+
private void verifyStatisticsTimes(PackageStatistics stats) {
long durationMs = stats.getDurationMs();
+ long foregroundDurationMs = stats.getForegroundDurationMs();
long timeSinceFirstRequestMs = stats.getTimeSinceFirstRequestMs();
long maxDeltaMs = SystemClock.elapsedRealtime() - mStartElapsedRealtimeMs;
+ assertTrue("Duration is too small", durationMs >= 0);
assertTrue("Duration is too large", durationMs <= maxDeltaMs);
+ assertTrue("Foreground Duration is too small", foregroundDurationMs >= 0);
+ assertTrue("Foreground Duration is too large", foregroundDurationMs <= maxDeltaMs);
assertTrue("Time since first request is too large", timeSinceFirstRequestMs <= maxDeltaMs);
}
}