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

Commit d07752e1 authored by Kweku Adams's avatar Kweku Adams
Browse files

Check opportunistic quota on metered networks.

Check that a job's total estimated data transfer will fit in the
opportunistic quota before allowing it to run on the unmetered network.

Bug: 189104483
Test: atest FrameworksMockingServicesTests:ConnectivityControllerTest
Test: atest CtsJobSchedulerTestCases:ConnectivityConstraintTest
Change-Id: I6d7e83d87dc3d1522c934e7441f4975418d571e7
parent 7bec4b30
Loading
Loading
Loading
Loading
+17 −6
Original line number Original line Diff line number Diff line
@@ -633,23 +633,34 @@ public final class ConnectivityController extends RestrictingController implemen
        }
        }
    }
    }


    private static boolean isRelaxedSatisfied(JobStatus jobStatus, Network network,
    private boolean isRelaxedSatisfied(JobStatus jobStatus, Network network,
            NetworkCapabilities capabilities, Constants constants) {
            NetworkCapabilities capabilities, Constants constants) {
        // Only consider doing this for unrestricted prefetching jobs
        // Only consider doing this for unrestricted prefetching jobs
        if (!jobStatus.getJob().isPrefetch() || jobStatus.getStandbyBucket() == RESTRICTED_INDEX) {
        if (!jobStatus.getJob().isPrefetch() || jobStatus.getStandbyBucket() == RESTRICTED_INDEX) {
            return false;
            return false;
        }
        }
        final long estDownloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
        if (estDownloadBytes <= 0) {
            // Need to at least know the estimated download bytes for a prefetch job.
            return false;
        }


        // See if we match after relaxing any unmetered request
        // See if we match after relaxing any unmetered request
        final NetworkCapabilities.Builder builder =
        final NetworkCapabilities.Builder builder =
                copyCapabilities(jobStatus.getJob().getRequiredNetwork());
                copyCapabilities(jobStatus.getJob().getRequiredNetwork());
        builder.removeCapability(NET_CAPABILITY_NOT_METERED);
        builder.removeCapability(NET_CAPABILITY_NOT_METERED);
        if (builder.build().satisfiedByNetworkCapabilities(capabilities)) {
        if (builder.build().satisfiedByNetworkCapabilities(capabilities)
            // TODO: treat this as "maybe" response; need to check quotas
                && jobStatus.getFractionRunTime() > constants.CONN_PREFETCH_RELAX_FRAC) {
            return jobStatus.getFractionRunTime() > constants.CONN_PREFETCH_RELAX_FRAC;
            final long opportunisticQuotaBytes =
        } else {
                    mNetPolicyManagerInternal.getSubscriptionOpportunisticQuota(
            return false;
                            network, NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS);
            final long estUploadBytes = jobStatus.getEstimatedNetworkUploadBytes();
            final long estimatedBytes = estDownloadBytes
                    + (estUploadBytes == JobInfo.NETWORK_BYTES_UNKNOWN ? 0 : estUploadBytes);
            return opportunisticQuotaBytes >= estimatedBytes;
        }
        }

        return false;
    }
    }


    @VisibleForTesting
    @VisibleForTesting
+22 −1
Original line number Original line Diff line number Diff line
@@ -299,8 +299,17 @@ public class ConnectivityControllerTest {
        final JobStatus earlyPrefetch = createJobStatus(job, now - 1000, now + 2000);
        final JobStatus earlyPrefetch = createJobStatus(job, now - 1000, now + 2000);
        final JobStatus latePrefetch = createJobStatus(job, now - 2000, now + 1000);
        final JobStatus latePrefetch = createJobStatus(job, now - 2000, now + 1000);


        job.setEstimatedNetworkBytes(JobInfo.NETWORK_BYTES_UNKNOWN, DataUnit.MEBIBYTES.toBytes(1));
        final JobStatus latePrefetchUnknownDown = createJobStatus(job, now - 2000, now + 1000);
        job.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), JobInfo.NETWORK_BYTES_UNKNOWN);
        final JobStatus latePrefetchUnknownUp = createJobStatus(job, now - 2000, now + 1000);

        final ConnectivityController controller = new ConnectivityController(mService);
        final ConnectivityController controller = new ConnectivityController(mService);


        when(mNetPolicyManagerInternal.getSubscriptionOpportunisticQuota(
                any(), eq(NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS)))
                .thenReturn(0L);

        // Unmetered network is whenever
        // Unmetered network is whenever
        {
        {
            final Network net = mock(Network.class);
            final Network net = mock(Network.class);
@@ -312,9 +321,11 @@ public class ConnectivityControllerTest {
            assertTrue(controller.isSatisfied(late, net, caps, mConstants));
            assertTrue(controller.isSatisfied(late, net, caps, mConstants));
            assertTrue(controller.isSatisfied(earlyPrefetch, net, caps, mConstants));
            assertTrue(controller.isSatisfied(earlyPrefetch, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetch, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetch, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
        }
        }


        // Metered network is only when prefetching and late
        // Metered network is only when prefetching, late, and in opportunistic quota
        {
        {
            final Network net = mock(Network.class);
            final Network net = mock(Network.class);
            final NetworkCapabilities caps = createCapabilitiesBuilder()
            final NetworkCapabilities caps = createCapabilitiesBuilder()
@@ -323,7 +334,17 @@ public class ConnectivityControllerTest {
            assertFalse(controller.isSatisfied(early, net, caps, mConstants));
            assertFalse(controller.isSatisfied(early, net, caps, mConstants));
            assertFalse(controller.isSatisfied(late, net, caps, mConstants));
            assertFalse(controller.isSatisfied(late, net, caps, mConstants));
            assertFalse(controller.isSatisfied(earlyPrefetch, net, caps, mConstants));
            assertFalse(controller.isSatisfied(earlyPrefetch, net, caps, mConstants));
            assertFalse(controller.isSatisfied(latePrefetch, net, caps, mConstants));
            assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
            assertFalse(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));

            when(mNetPolicyManagerInternal.getSubscriptionOpportunisticQuota(
                    any(), eq(NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS)))
                    .thenReturn(9876543210L);
            assertTrue(controller.isSatisfied(latePrefetch, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetch, net, caps, mConstants));
            // Only relax restrictions when we at least know the estimated download bytes.
            assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
            assertTrue(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
        }
        }
    }
    }