Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b657dc5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add feature id to location dumpsys."

parents 2a180f11 9e33ab41
Loading
Loading
Loading
Loading
+12 −6
Original line number Original line Diff line number Diff line
@@ -1830,8 +1830,8 @@ 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.mCallerIdentity.mPackageName, provider, request.getInterval(),
                    mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
                    mIsForegroundUid);
                    provider, request.getInterval(), mIsForegroundUid);
        }
        }


        /**
        /**
@@ -1840,7 +1840,8 @@ public class LocationManagerService extends ILocationManager.Stub {
        private void updateForeground(boolean isForeground) {
        private void updateForeground(boolean isForeground) {
            mIsForegroundUid = isForeground;
            mIsForegroundUid = isForeground;
            mRequestStatistics.updateForeground(
            mRequestStatistics.updateForeground(
                    mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
                    mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
                    mProvider, isForeground);
        }
        }


        /**
        /**
@@ -1848,7 +1849,8 @@ public class LocationManagerService extends ILocationManager.Stub {
         */
         */
        private void disposeLocked(boolean removeReceiver) {
        private void disposeLocked(boolean removeReceiver) {
            String packageName = mReceiver.mCallerIdentity.mPackageName;
            String packageName = mReceiver.mCallerIdentity.mPackageName;
            mRequestStatistics.stopRequesting(packageName, mProvider);
            mRequestStatistics.stopRequesting(packageName, mReceiver.mCallerIdentity.mFeatureId,
                    mProvider);


            mLocationUsageLogger.logLocationApiUsage(
            mLocationUsageLogger.logLocationApiUsage(
                    LocationStatsEnums.USAGE_ENDED,
                    LocationStatsEnums.USAGE_ENDED,
@@ -1883,6 +1885,10 @@ public class LocationManagerService extends ILocationManager.Stub {
            StringBuilder b = new StringBuilder("UpdateRecord[");
            StringBuilder b = new StringBuilder("UpdateRecord[");
            b.append(mProvider).append(" ");
            b.append(mProvider).append(" ");
            b.append(mReceiver.mCallerIdentity.mPackageName);
            b.append(mReceiver.mCallerIdentity.mPackageName);
            String featureId = mReceiver.mCallerIdentity.mFeatureId;
            if (featureId != null) {
                b.append(" ").append(featureId).append(" ");
            }
            b.append("(").append(mReceiver.mCallerIdentity.mUid);
            b.append("(").append(mReceiver.mCallerIdentity.mUid);
            if (mIsForegroundUid) {
            if (mIsForegroundUid) {
                b.append(" foreground");
                b.append(" foreground");
@@ -2886,7 +2892,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            for (Map.Entry<PackageProviderKey, PackageStatistics> entry
            for (Map.Entry<PackageProviderKey, PackageStatistics> entry
                    : sorted.entrySet()) {
                    : sorted.entrySet()) {
                PackageProviderKey key = entry.getKey();
                PackageProviderKey key = entry.getKey();
                ipw.println(key.providerName + ": " + key.packageName + ": " + entry.getValue());
                ipw.println(key.mPackageName + ": " + key.mProviderName + ": " + entry.getValue());
            }
            }
            ipw.decreaseIndent();
            ipw.decreaseIndent();


+65 −33
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.location;
package com.android.server.location;


import android.annotation.Nullable;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.util.TimeUtils;
import android.util.TimeUtils;
@@ -25,6 +26,7 @@ import com.android.internal.util.IndentingPrintWriter;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.Objects;


/**
/**
 * Holds statistics for location requests (active requests by provider).
 * Holds statistics for location requests (active requests by provider).
@@ -44,12 +46,13 @@ public class LocationRequestStatistics {
     * Signals that a package has started requesting locations.
     * Signals that a package has started requesting locations.
     *
     *
     * @param packageName  Name of package that has requested locations.
     * @param packageName  Name of package that has requested locations.
     * @param featureId    Feature id associated with the request.
     * @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, @Nullable String featureId, String providerName,
            boolean isForeground) {
            long intervalMs, boolean isForeground) {
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
        PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
        PackageStatistics stats = statistics.get(key);
        PackageStatistics stats = statistics.get(key);
        if (stats == null) {
        if (stats == null) {
            stats = new PackageStatistics();
            stats = new PackageStatistics();
@@ -57,32 +60,36 @@ public class LocationRequestStatistics {
        }
        }
        stats.startRequesting(intervalMs);
        stats.startRequesting(intervalMs);
        stats.updateForeground(isForeground);
        stats.updateForeground(isForeground);
        history.addRequest(packageName, providerName, intervalMs);
        history.addRequest(packageName, featureId, providerName, intervalMs);
    }
    }


    /**
    /**
     * Signals that a package has stopped requesting locations.
     * Signals that a package has stopped requesting locations.
     *
     *
     * @param packageName  Name of package that has stopped requesting locations.
     * @param packageName  Name of package that has stopped requesting locations.
     * @param featureId    Feature id associated with the request.
     * @param providerName Provider that is no longer being requested.
     * @param providerName Provider that is no longer being requested.
     */
     */
    public void stopRequesting(String packageName, String providerName) {
    public void stopRequesting(String packageName, @Nullable String featureId,
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
            String providerName) {
        PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
        PackageStatistics stats = statistics.get(key);
        PackageStatistics stats = statistics.get(key);
        if (stats != null) {
        if (stats != null) {
            stats.stopRequesting();
            stats.stopRequesting();
        }
        }
        history.removeRequest(packageName, providerName);
        history.removeRequest(packageName, featureId, providerName);
    }
    }


    /**
    /**
     * Signals that a package possibly switched background/foreground.
     * Signals that a package possibly switched background/foreground.
     *
     *
     * @param packageName  Name of package that has stopped requesting locations.
     * @param packageName  Name of package that has stopped requesting locations.
     * @param featureId    Feature id associated with the request.
     * @param providerName Provider that is no longer being requested.
     * @param providerName Provider that is no longer being requested.
     */
     */
    public void updateForeground(String packageName, String providerName, boolean isForeground) {
    public void updateForeground(String packageName, @Nullable String featureId,
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
            String providerName, boolean isForeground) {
        PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
        PackageStatistics stats = statistics.get(key);
        PackageStatistics stats = statistics.get(key);
        if (stats != null) {
        if (stats != null) {
            stats.updateForeground(isForeground);
            stats.updateForeground(isForeground);
@@ -90,30 +97,37 @@ public class LocationRequestStatistics {
    }
    }


    /**
    /**
     * A key that holds both package and provider names.
     * A key that holds package, feature id, and provider names.
     */
     */
    public static class PackageProviderKey implements Comparable<PackageProviderKey> {
    public static class PackageProviderKey implements Comparable<PackageProviderKey> {
        /**
        /**
         * Name of package requesting location.
         * Name of package requesting location.
         */
         */
        public final String packageName;
        public final String mPackageName;
        /**
         * Feature id associated with the request, which can be used to attribute location access to
         * different parts of the application.
         */
        @Nullable
        public final String mFeatureId;
        /**
        /**
         * Name of provider being requested (e.g. "gps").
         * Name of provider being requested (e.g. "gps").
         */
         */
        public final String providerName;
        public final String mProviderName;


        PackageProviderKey(String packageName, String providerName) {
        PackageProviderKey(String packageName, @Nullable String featureId, String providerName) {
            this.packageName = packageName;
            this.mPackageName = packageName;
            this.providerName = providerName;
            this.mFeatureId = featureId;
            this.mProviderName = providerName;
        }
        }


        @Override
        @Override
        public int compareTo(PackageProviderKey other) {
        public int compareTo(PackageProviderKey other) {
            final int providerCompare = providerName.compareTo(other.providerName);
            final int providerCompare = mProviderName.compareTo(other.mProviderName);
            if (providerCompare != 0) {
            if (providerCompare != 0) {
                return providerCompare;
                return providerCompare;
            } else {
            } else {
                return packageName.compareTo(other.packageName);
                return mProviderName.compareTo(other.mProviderName);
            }
            }
        }
        }


@@ -124,13 +138,18 @@ public class LocationRequestStatistics {
            }
            }


            PackageProviderKey otherKey = (PackageProviderKey) other;
            PackageProviderKey otherKey = (PackageProviderKey) other;
            return packageName.equals(otherKey.packageName)
            return mPackageName.equals(otherKey.mPackageName)
                    && providerName.equals(otherKey.providerName);
                    && mProviderName.equals(otherKey.mProviderName)
                    && Objects.equals(mFeatureId, otherKey.mFeatureId);
        }
        }


        @Override
        @Override
        public int hashCode() {
        public int hashCode() {
            return packageName.hashCode() + 31 * providerName.hashCode();
            int hash = mPackageName.hashCode() + 31 * mProviderName.hashCode();
            if (mFeatureId != null) {
                hash += mFeatureId.hashCode() + 31 * hash;
            }
            return hash;
        }
        }
    }
    }


@@ -147,17 +166,18 @@ public class LocationRequestStatistics {
         * Append an added location request to the history
         * Append an added location request to the history
         */
         */
        @VisibleForTesting
        @VisibleForTesting
        void addRequest(String packageName, String providerName, long intervalMs) {
        void addRequest(String packageName, @Nullable String featureId, String providerName,
            addRequestSummary(new RequestSummary(packageName, providerName, intervalMs));
                long intervalMs) {
            addRequestSummary(new RequestSummary(packageName, featureId, providerName, intervalMs));
        }
        }


        /**
        /**
         * Append a removed location request to the history
         * Append a removed location request to the history
         */
         */
        @VisibleForTesting
        @VisibleForTesting
        void removeRequest(String packageName, String providerName) {
        void removeRequest(String packageName, @Nullable String featureId, String providerName) {
            addRequestSummary(new RequestSummary(
            addRequestSummary(new RequestSummary(
                    packageName, providerName, RequestSummary.REQUEST_ENDED_INTERVAL));
                    packageName, featureId, providerName, RequestSummary.REQUEST_ENDED_INTERVAL));
        }
        }


        private void addRequestSummary(RequestSummary summary) {
        private void addRequestSummary(RequestSummary summary) {
@@ -193,6 +213,12 @@ public class LocationRequestStatistics {
         * Name of package requesting location.
         * Name of package requesting location.
         */
         */
        private final String mPackageName;
        private final String mPackageName;

        /**
         * Feature id associated with the request for identifying subsystem of an application.
         */
        @Nullable
        private final String mFeatureId;
        /**
        /**
         * Name of provider being requested (e.g. "gps").
         * Name of provider being requested (e.g. "gps").
         */
         */
@@ -211,8 +237,10 @@ public class LocationRequestStatistics {
         */
         */
        static final long REQUEST_ENDED_INTERVAL = -1;
        static final long REQUEST_ENDED_INTERVAL = -1;


        RequestSummary(String packageName, String providerName, long intervalMillis) {
        RequestSummary(String packageName, @Nullable String featureId, String providerName,
                long intervalMillis) {
            this.mPackageName = packageName;
            this.mPackageName = packageName;
            this.mFeatureId = featureId;
            this.mProviderName = providerName;
            this.mProviderName = providerName;
            this.mIntervalMillis = intervalMillis;
            this.mIntervalMillis = intervalMillis;
            this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
            this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
@@ -225,6 +253,9 @@ public class LocationRequestStatistics {
                    .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ")
                    .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ")
                    .append(String.format("%7s", mProviderName)).append(" request from ")
                    .append(String.format("%7s", mProviderName)).append(" request from ")
                    .append(mPackageName);
                    .append(mPackageName);
            if (mFeatureId != null) {
                s.append(" with feature ").append(mFeatureId);
            }
            if (mIntervalMillis != REQUEST_ENDED_INTERVAL) {
            if (mIntervalMillis != REQUEST_ENDED_INTERVAL) {
                s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds");
                s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds");
            }
            }
@@ -246,14 +277,15 @@ public class LocationRequestStatistics {
        private long mFastestIntervalMs;
        private long mFastestIntervalMs;
        // The slowest interval this package has ever requested.
        // The slowest interval this package has ever requested.
        private long mSlowestIntervalMs;
        private long mSlowestIntervalMs;
        // 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
        // Time when this package most recently went to foreground, requesting location. 0 means
        // not currently in foreground.
        // not currently in foreground.
        private long mLastForegroundElapsedTimeMs;
        private long mLastForegroundElapsedTimeMs;
        // The time this app has requested location (not including currently running requests), while
        // The time this app has requested location (not including currently running requests),
        // in foreground.
        // while in foreground.
        private long mForegroundDurationMs;
        private long mForegroundDurationMs;


        // Time when package last went dormant (stopped requesting location)
        // Time when package last went dormant (stopped requesting location)
+6 −4
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import java.io.StringWriter;
@RunWith(RobolectricTestRunner.class)
@RunWith(RobolectricTestRunner.class)
@Presubmit
@Presubmit
public class LocationRequestStatisticsTest {
public class LocationRequestStatisticsTest {
    private static final String FEATURE_ID = "featureId";


    /**
    /**
     * Check adding and removing requests & strings
     * Check adding and removing requests & strings
@@ -43,17 +44,18 @@ public class LocationRequestStatisticsTest {
    public void testRequestSummary() {
    public void testRequestSummary() {
        LocationRequestStatistics.RequestSummary summary =
        LocationRequestStatistics.RequestSummary summary =
                new LocationRequestStatistics.RequestSummary(
                new LocationRequestStatistics.RequestSummary(
                "com.example", "gps", 1000);
                        "com.example", FEATURE_ID, "gps", 1000);
        StringWriter stringWriter = new StringWriter();
        StringWriter stringWriter = new StringWriter();
        summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriter), "  "), 1234);
        summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriter), "  "), 1234);
        assertThat(stringWriter.toString()).startsWith("At");
        assertThat(stringWriter.toString()).startsWith("At");


        StringWriter stringWriterRemove = new StringWriter();
        StringWriter stringWriterRemove = new StringWriter();
        summary = new LocationRequestStatistics.RequestSummary(
        summary = new LocationRequestStatistics.RequestSummary(
                "com.example", "gps",
                "com.example", "gps", FEATURE_ID,
                LocationRequestStatistics.RequestSummary.REQUEST_ENDED_INTERVAL);
                LocationRequestStatistics.RequestSummary.REQUEST_ENDED_INTERVAL);
        summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriterRemove), "  "), 2345);
        summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriterRemove), "  "), 2345);
        assertThat(stringWriterRemove.toString()).contains("-");
        assertThat(stringWriterRemove.toString()).contains("-");
        assertThat(stringWriterRemove.toString()).contains(FEATURE_ID);
    }
    }


    /**
    /**
@@ -62,11 +64,11 @@ public class LocationRequestStatisticsTest {
    @Test
    @Test
    public void testSummaryList() {
    public void testSummaryList() {
        LocationRequestStatistics statistics = new LocationRequestStatistics();
        LocationRequestStatistics statistics = new LocationRequestStatistics();
        statistics.history.addRequest("com.example", "gps", 1000);
        statistics.history.addRequest("com.example", FEATURE_ID, "gps", 1000);
        assertThat(statistics.history.mList.size()).isEqualTo(1);
        assertThat(statistics.history.mList.size()).isEqualTo(1);
        // Try (not) to overflow
        // Try (not) to overflow
        for (int i = 0; i < LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE; i++) {
        for (int i = 0; i < LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE; i++) {
            statistics.history.addRequest("com.example", "gps", 1000);
            statistics.history.addRequest("com.example", FEATURE_ID, "gps", 1000);
        }
        }
        assertThat(statistics.history.mList.size()).isEqualTo(
        assertThat(statistics.history.mList.size()).isEqualTo(
                LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE);
                LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE);
+45 −41
Original line number Original line Diff line number Diff line
package com.android.server.location;
package com.android.server.location;


import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;

import android.os.SystemClock;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.AndroidTestCase;


import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;

/**
/**
 * Unit tests for {@link LocationRequestStatistics}.
 * Unit tests for {@link LocationRequestStatistics}.
 */
 */
public class LocationRequestStatisticsTest extends AndroidTestCase {
public class LocationRequestStatisticsTest extends AndroidTestCase {
    private static final String PACKAGE1 = "package1";
    private static final String PACKAGE1 = "package1";
    private static final String PACKAGE2 = "package2";
    private static final String PACKAGE2 = "package2";
    private static final String FEATURE_ID = "featureId";
    private static final String PROVIDER1 = "provider1";
    private static final String PROVIDER1 = "provider1";
    private static final String PROVIDER2 = "provider2";
    private static final String PROVIDER2 = "provider2";
    private static final long INTERVAL1 = 5000;
    private static final long INTERVAL1 = 5000;
@@ -30,12 +31,13 @@ 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, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, 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();
        assertEquals(PACKAGE1, key.packageName);
        assertEquals(PACKAGE1, key.mPackageName);
        assertEquals(PROVIDER1, key.providerName);
        assertEquals(PROVIDER1, key.mProviderName);
        assertEquals(FEATURE_ID, key.mFeatureId);
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        verifyStatisticsTimes(stats);
        verifyStatisticsTimes(stats);
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
@@ -47,21 +49,22 @@ 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, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, 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();
        assertEquals(PACKAGE1, key.packageName);
        assertEquals(PACKAGE1, key.mPackageName);
        assertEquals(PROVIDER1, key.providerName);
        assertEquals(FEATURE_ID, key.mFeatureId);
        assertEquals(PROVIDER1, key.mProviderName);
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        verifyStatisticsTimes(stats);
        verifyStatisticsTimes(stats);
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats.getSlowestIntervalMs());
        assertTrue(stats.isActive());
        assertTrue(stats.isActive());


        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        assertFalse(stats.isActive());
        assertFalse(stats.isActive());
    }
    }


@@ -69,21 +72,22 @@ 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, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL2, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, 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();
        assertEquals(PACKAGE1, key.packageName);
        assertEquals(PACKAGE1, key.mPackageName);
        assertEquals(PROVIDER1, key.providerName);
        assertEquals(PROVIDER1, key.mProviderName);
        assertEquals(FEATURE_ID, key.mFeatureId);
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        PackageStatistics stats = mStatistics.statistics.values().iterator().next();
        verifyStatisticsTimes(stats);
        verifyStatisticsTimes(stats);
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats.getFastestIntervalMs());
        assertTrue(stats.isActive());
        assertTrue(stats.isActive());


        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        assertTrue(stats.isActive());
        assertTrue(stats.isActive());
        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        assertFalse(stats.isActive());
        assertFalse(stats.isActive());
    }
    }


@@ -91,27 +95,27 @@ 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, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL2, true);


        assertEquals(2, mStatistics.statistics.size());
        assertEquals(2, mStatistics.statistics.size());
        PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
        PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER1);
        PackageStatistics stats1 = mStatistics.statistics.get(key1);
        PackageStatistics stats1 = mStatistics.statistics.get(key1);
        verifyStatisticsTimes(stats1);
        verifyStatisticsTimes(stats1);
        assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
        assertTrue(stats1.isActive());
        assertTrue(stats1.isActive());
        PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, PROVIDER2);
        PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER2);
        PackageStatistics stats2 = mStatistics.statistics.get(key2);
        PackageStatistics stats2 = mStatistics.statistics.get(key2);
        verifyStatisticsTimes(stats2);
        verifyStatisticsTimes(stats2);
        assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
        assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
        assertEquals(INTERVAL2, stats2.getFastestIntervalMs());
        assertEquals(INTERVAL2, stats2.getFastestIntervalMs());
        assertTrue(stats2.isActive());
        assertTrue(stats2.isActive());


        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        assertFalse(stats1.isActive());
        assertFalse(stats1.isActive());
        assertTrue(stats2.isActive());
        assertTrue(stats2.isActive());
        mStatistics.stopRequesting(PACKAGE1, PROVIDER2);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
        assertFalse(stats1.isActive());
        assertFalse(stats1.isActive());
        assertFalse(stats2.isActive());
        assertFalse(stats2.isActive());
    }
    }
@@ -120,46 +124,46 @@ 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, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL2, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL2, true);
        mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE2, FEATURE_ID, PROVIDER1, INTERVAL1, true);


        assertEquals(3, mStatistics.statistics.size());
        assertEquals(3, mStatistics.statistics.size());
        PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, PROVIDER1);
        PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER1);
        PackageStatistics stats1 = mStatistics.statistics.get(key1);
        PackageStatistics stats1 = mStatistics.statistics.get(key1);
        verifyStatisticsTimes(stats1);
        verifyStatisticsTimes(stats1);
        assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
        assertTrue(stats1.isActive());
        assertTrue(stats1.isActive());


        PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, PROVIDER2);
        PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER2);
        PackageStatistics stats2 = mStatistics.statistics.get(key2);
        PackageStatistics stats2 = mStatistics.statistics.get(key2);
        verifyStatisticsTimes(stats2);
        verifyStatisticsTimes(stats2);
        assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
        assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats2.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats2.getFastestIntervalMs());
        assertTrue(stats2.isActive());
        assertTrue(stats2.isActive());


        PackageProviderKey key3 = new PackageProviderKey(PACKAGE2, PROVIDER1);
        PackageProviderKey key3 = new PackageProviderKey(PACKAGE2, FEATURE_ID, PROVIDER1);
        PackageStatistics stats3 = mStatistics.statistics.get(key3);
        PackageStatistics stats3 = mStatistics.statistics.get(key3);
        verifyStatisticsTimes(stats3);
        verifyStatisticsTimes(stats3);
        assertEquals(INTERVAL1, stats3.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats3.getSlowestIntervalMs());
        assertEquals(INTERVAL1, stats3.getFastestIntervalMs());
        assertEquals(INTERVAL1, stats3.getFastestIntervalMs());
        assertTrue(stats3.isActive());
        assertTrue(stats3.isActive());


        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
        assertFalse(stats1.isActive());
        assertFalse(stats1.isActive());
        assertTrue(stats2.isActive());
        assertTrue(stats2.isActive());
        assertTrue(stats3.isActive());
        assertTrue(stats3.isActive());


        mStatistics.stopRequesting(PACKAGE1, PROVIDER2);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
        assertFalse(stats1.isActive());
        assertFalse(stats1.isActive());
        assertTrue(stats2.isActive());
        assertTrue(stats2.isActive());
        assertTrue(stats3.isActive());
        assertTrue(stats3.isActive());
        mStatistics.stopRequesting(PACKAGE1, PROVIDER2);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
        assertFalse(stats2.isActive());
        assertFalse(stats2.isActive());


        mStatistics.stopRequesting(PACKAGE2, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE2, FEATURE_ID, PROVIDER1);
        assertFalse(stats1.isActive());
        assertFalse(stats1.isActive());
        assertFalse(stats2.isActive());
        assertFalse(stats2.isActive());
        assertFalse(stats3.isActive());
        assertFalse(stats3.isActive());
@@ -169,14 +173,14 @@ public class LocationRequestStatisticsTest extends AndroidTestCase {
     * Tests that switching foreground & background states accmulates time reasonably.
     * Tests that switching foreground & background states accmulates time reasonably.
     */
     */
    public void testForegroundBackground() {
    public void testForegroundBackground() {
        mStatistics.startRequesting(PACKAGE1, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, PROVIDER2, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL1, true);
        mStatistics.startRequesting(PACKAGE2, PROVIDER1, INTERVAL1, false);
        mStatistics.startRequesting(PACKAGE2, FEATURE_ID, PROVIDER1, INTERVAL1, false);


        mStatistics.updateForeground(PACKAGE1, PROVIDER2, false);
        mStatistics.updateForeground(PACKAGE1, FEATURE_ID, PROVIDER2, false);
        mStatistics.updateForeground(PACKAGE2, PROVIDER1, true);
        mStatistics.updateForeground(PACKAGE2, FEATURE_ID, PROVIDER1, true);


        mStatistics.stopRequesting(PACKAGE1, PROVIDER1);
        mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);


        for (PackageStatistics stats : mStatistics.statistics.values()) {
        for (PackageStatistics stats : mStatistics.statistics.values()) {
            verifyStatisticsTimes(stats);
            verifyStatisticsTimes(stats);