diff options
3 files changed, 96 insertions, 18 deletions
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index d4290ee615c0..309a75a6a6de 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -424,7 +424,7 @@ public class LocationManagerService extends ILocationManager.Stub { Log.d(TAG, "request from uid " + uid + " is now " + (foreground ? "foreground" : "background)")); } - record.mIsForegroundUid = foreground; + record.updateForeground(foreground); if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) { affectedProviders.add(provider); @@ -1905,7 +1905,17 @@ public class LocationManagerService extends ILocationManager.Stub { // Update statistics for historical location requests by package/provider mRequestStatistics.startRequesting( - mReceiver.mIdentity.mPackageName, provider, request.getInterval()); + mReceiver.mIdentity.mPackageName, provider, request.getInterval(), + mIsForegroundUid); + } + + /** + * Method to be called when record changes foreground/background + */ + void updateForeground(boolean isForeground){ + mIsForegroundUid = isForeground; + mRequestStatistics.updateForeground( + mReceiver.mIdentity.mPackageName, mProvider, isForeground); } /** diff --git a/services/core/java/com/android/server/location/LocationRequestStatistics.java b/services/core/java/com/android/server/location/LocationRequestStatistics.java index 264026eeb0f5..b7934d978bac 100644 --- a/services/core/java/com/android/server/location/LocationRequestStatistics.java +++ b/services/core/java/com/android/server/location/LocationRequestStatistics.java @@ -24,7 +24,8 @@ public class LocationRequestStatistics { * @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) { @@ -32,6 +33,7 @@ public class LocationRequestStatistics { statistics.put(key, stats); } stats.startRequesting(intervalMs); + stats.updateForeground(isForeground); } /** @@ -45,9 +47,20 @@ public class LocationRequestStatistics { 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); } } @@ -103,12 +116,21 @@ public class LocationRequestStatistics { // 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) { @@ -127,6 +149,15 @@ public class LocationRequestStatistics { 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 @@ -139,6 +170,7 @@ public class LocationRequestStatistics { long lastDurationMs = SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs; mTotalDurationMs += lastDurationMs; + updateForeground(false); } } @@ -155,6 +187,18 @@ public class LocationRequestStatistics { } /** + * 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() { @@ -193,7 +237,9 @@ public class LocationRequestStatistics { } 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()) { diff --git a/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java b/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java index 33f604d99141..c45820e6ec9d 100644 --- a/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java +++ b/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java @@ -30,7 +30,7 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { * 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(); @@ -47,9 +47,9 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { * 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(); @@ -69,8 +69,8 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { * 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(); @@ -91,8 +91,8 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { * 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); @@ -120,10 +120,10 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { * 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); @@ -165,11 +165,33 @@ public class LocationRequestStatisticsTest extends AndroidTestCase { 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); } } |