Merge "Adding Location Request History Foreground Tracking" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a2b4cc9ea0
@@ -424,7 +424,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
|||||||
Log.d(TAG, "request from uid " + uid + " is now "
|
Log.d(TAG, "request from uid " + uid + " is now "
|
||||||
+ (foreground ? "foreground" : "background)"));
|
+ (foreground ? "foreground" : "background)"));
|
||||||
}
|
}
|
||||||
record.mIsForegroundUid = foreground;
|
record.updateForeground(foreground);
|
||||||
|
|
||||||
if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
|
if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
|
||||||
affectedProviders.add(provider);
|
affectedProviders.add(provider);
|
||||||
@@ -1905,7 +1905,17 @@ public class LocationManagerService extends ILocationManager.Stub {
|
|||||||
|
|
||||||
// Update statistics for historical location requests by package/provider
|
// Update statistics for historical location requests by package/provider
|
||||||
mRequestStatistics.startRequesting(
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ public class LocationRequestStatistics {
|
|||||||
* @param providerName Name of provider that is requested (e.g. "gps").
|
* @param providerName Name of provider that is requested (e.g. "gps").
|
||||||
* @param intervalMs The interval that is requested in ms.
|
* @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);
|
PackageProviderKey key = new PackageProviderKey(packageName, providerName);
|
||||||
PackageStatistics stats = statistics.get(key);
|
PackageStatistics stats = statistics.get(key);
|
||||||
if (stats == null) {
|
if (stats == null) {
|
||||||
@@ -32,6 +33,7 @@ public class LocationRequestStatistics {
|
|||||||
statistics.put(key, stats);
|
statistics.put(key, stats);
|
||||||
}
|
}
|
||||||
stats.startRequesting(intervalMs);
|
stats.startRequesting(intervalMs);
|
||||||
|
stats.updateForeground(isForeground);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,9 +47,20 @@ public class LocationRequestStatistics {
|
|||||||
PackageStatistics stats = statistics.get(key);
|
PackageStatistics stats = statistics.get(key);
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
stats.stopRequesting();
|
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).
|
// The total time this app has requested location (not including currently running requests).
|
||||||
private long mTotalDurationMs;
|
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() {
|
private PackageStatistics() {
|
||||||
mInitialElapsedTimeMs = SystemClock.elapsedRealtime();
|
mInitialElapsedTimeMs = SystemClock.elapsedRealtime();
|
||||||
mNumActiveRequests = 0;
|
mNumActiveRequests = 0;
|
||||||
mTotalDurationMs = 0;
|
mTotalDurationMs = 0;
|
||||||
mFastestIntervalMs = Long.MAX_VALUE;
|
mFastestIntervalMs = Long.MAX_VALUE;
|
||||||
mSlowestIntervalMs = 0;
|
mSlowestIntervalMs = 0;
|
||||||
|
mForegroundDurationMs = 0;
|
||||||
|
mLastForegroundElapsedTimeMs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startRequesting(long intervalMs) {
|
private void startRequesting(long intervalMs) {
|
||||||
@@ -127,6 +149,15 @@ public class LocationRequestStatistics {
|
|||||||
mNumActiveRequests++;
|
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() {
|
private void stopRequesting() {
|
||||||
if (mNumActiveRequests <= 0) {
|
if (mNumActiveRequests <= 0) {
|
||||||
// Shouldn't be a possible code path
|
// Shouldn't be a possible code path
|
||||||
@@ -139,6 +170,7 @@ public class LocationRequestStatistics {
|
|||||||
long lastDurationMs
|
long lastDurationMs
|
||||||
= SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs;
|
= SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs;
|
||||||
mTotalDurationMs += lastDurationMs;
|
mTotalDurationMs += lastDurationMs;
|
||||||
|
updateForeground(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +186,18 @@ public class LocationRequestStatistics {
|
|||||||
return currentDurationMs;
|
return currentDurationMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Returns the time since the initial request in ms.
|
||||||
*/
|
*/
|
||||||
@@ -193,7 +237,9 @@ public class LocationRequestStatistics {
|
|||||||
}
|
}
|
||||||
s.append(": Duration requested ")
|
s.append(": Duration requested ")
|
||||||
.append((getDurationMs() / 1000) / 60)
|
.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((getTimeSinceFirstRequestMs() / 1000) / 60)
|
||||||
.append(" minutes");
|
.append(" minutes");
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class LocationRequestStatisticsTest extends AndroidTestCase {
|
|||||||
* Tests that adding a single package works correctly.
|
* Tests that adding a single package works correctly.
|
||||||
*/
|
*/
|
||||||
public void testSinglePackage() {
|
public void testSinglePackage() {
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
|
|
||||||
assertEquals(1, mStatistics.statistics.size());
|
assertEquals(1, mStatistics.statistics.size());
|
||||||
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
|
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.
|
* Tests that adding a single package works correctly when it is stopped and restarted.
|
||||||
*/
|
*/
|
||||||
public void testSinglePackage_stopAndRestart() {
|
public void testSinglePackage_stopAndRestart() {
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
|
mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
|
|
||||||
assertEquals(1, mStatistics.statistics.size());
|
assertEquals(1, mStatistics.statistics.size());
|
||||||
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
|
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.
|
* Tests that adding a single package works correctly when multiple intervals are used.
|
||||||
*/
|
*/
|
||||||
public void testSinglePackage_multipleIntervals() {
|
public void testSinglePackage_multipleIntervals() {
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL2);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL2, true);
|
||||||
|
|
||||||
assertEquals(1, mStatistics.statistics.size());
|
assertEquals(1, mStatistics.statistics.size());
|
||||||
PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
|
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.
|
* Tests that adding a single package works correctly when multiple providers are used.
|
||||||
*/
|
*/
|
||||||
public void testSinglePackage_multipleProviders() {
|
public void testSinglePackage_multipleProviders() {
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
|
||||||
|
|
||||||
assertEquals(2, mStatistics.statistics.size());
|
assertEquals(2, mStatistics.statistics.size());
|
||||||
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
|
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
|
||||||
@@ -120,10 +120,10 @@ public class LocationRequestStatisticsTest extends AndroidTestCase {
|
|||||||
* Tests that adding multiple packages works correctly.
|
* Tests that adding multiple packages works correctly.
|
||||||
*/
|
*/
|
||||||
public void testMultiplePackages() {
|
public void testMultiplePackages() {
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1, true);
|
||||||
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2);
|
mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
|
||||||
mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1);
|
mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1, true);
|
||||||
|
|
||||||
assertEquals(3, mStatistics.statistics.size());
|
assertEquals(3, mStatistics.statistics.size());
|
||||||
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
|
PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
|
||||||
@@ -165,11 +165,33 @@ public class LocationRequestStatisticsTest extends AndroidTestCase {
|
|||||||
assertFalse(stats3.isActive());
|
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) {
|
private void verifyStatisticsTimes(PackageStatistics stats) {
|
||||||
long durationMs = stats.getDurationMs();
|
long durationMs = stats.getDurationMs();
|
||||||
|
long foregroundDurationMs = stats.getForegroundDurationMs();
|
||||||
long timeSinceFirstRequestMs = stats.getTimeSinceFirstRequestMs();
|
long timeSinceFirstRequestMs = stats.getTimeSinceFirstRequestMs();
|
||||||
long maxDeltaMs = SystemClock.elapsedRealtime() - mStartElapsedRealtimeMs;
|
long maxDeltaMs = SystemClock.elapsedRealtime() - mStartElapsedRealtimeMs;
|
||||||
|
assertTrue("Duration is too small", durationMs >= 0);
|
||||||
assertTrue("Duration is too large", durationMs <= maxDeltaMs);
|
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);
|
assertTrue("Time since first request is too large", timeSinceFirstRequestMs <= maxDeltaMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user