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

Commit b03474b4 authored by Wyatt Riley's avatar Wyatt Riley Committed by android-build-merger
Browse files

Merge "Adding Location Request History Foreground Tracking" into pi-dev

am: a2b4cc9e

Change-Id: I723aecfec8dfdbd9af09b58c009f05ccdb904378
parents 8566a544 a2b4cc9e
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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);
        }

        /**
+51 −5
Original line number Diff line number Diff line
@@ -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);
            }
        }

@@ -154,6 +186,18 @@ public class LocationRequestStatistics {
            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.
         */
@@ -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()) {
+33 −11
Original line number Diff line number Diff line
@@ -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);
    }
}