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

Commit f2bead51 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Switch network cycle calculation to use Calendar.

The older Time class is deprecated and doesn't handle edge cases
very well.  So migrate the cycle calculation logic to use the
long-standing and well-supported Calendar API.

Bug: 28689087
Change-Id: Ic1802b3f8556402f99bfea4cd625c35dfed81ac0
parent 400960a4
Loading
Loading
Loading
Loading
+31 −50
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package android.net;

import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.text.format.Time.MONTH_DAY;

import android.content.Context;
import android.content.Intent;
@@ -27,12 +26,13 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.format.Time;
import android.util.DebugUtils;

import com.google.android.collect.Sets;

import java.util.Calendar;
import java.util.HashSet;
import java.util.TimeZone;

/**
 * Manager for creating and modifying network policy rules.
@@ -253,28 +253,18 @@ public class NetworkPolicyManager {
            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
        }

        final Time now = new Time(policy.cycleTimezone);
        now.set(currentTime);
        final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone));
        cal.setTimeInMillis(currentTime);
        snapToCycleDay(cal, policy.cycleDay);

        // first, find cycle boundary for current month
        final Time cycle = new Time(now);
        cycle.hour = cycle.minute = cycle.second = 0;
        snapToCycleDay(cycle, policy.cycleDay);

        if (Time.compare(cycle, now) >= 0) {
            // cycle boundary is beyond now, use last cycle boundary; start by
            // pushing ourselves squarely into last month.
            final Time lastMonth = new Time(now);
            lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
            lastMonth.monthDay = 1;
            lastMonth.month -= 1;
            lastMonth.normalize(true);

            cycle.set(lastMonth);
            snapToCycleDay(cycle, policy.cycleDay);
        if (cal.getTimeInMillis() >= currentTime) {
            // Cycle boundary is beyond now, use last cycle boundary
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.add(Calendar.MONTH, -1);
            snapToCycleDay(cal, policy.cycleDay);
        }

        return cycle.toMillis(true);
        return cal.getTimeInMillis();
    }

    /** {@hide} */
@@ -283,28 +273,18 @@ public class NetworkPolicyManager {
            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
        }

        final Time now = new Time(policy.cycleTimezone);
        now.set(currentTime);

        // first, find cycle boundary for current month
        final Time cycle = new Time(now);
        cycle.hour = cycle.minute = cycle.second = 0;
        snapToCycleDay(cycle, policy.cycleDay);

        if (Time.compare(cycle, now) <= 0) {
            // cycle boundary is before now, use next cycle boundary; start by
            // pushing ourselves squarely into next month.
            final Time nextMonth = new Time(now);
            nextMonth.hour = nextMonth.minute = nextMonth.second = 0;
            nextMonth.monthDay = 1;
            nextMonth.month += 1;
            nextMonth.normalize(true);
        final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone));
        cal.setTimeInMillis(currentTime);
        snapToCycleDay(cal, policy.cycleDay);

            cycle.set(nextMonth);
            snapToCycleDay(cycle, policy.cycleDay);
        if (cal.getTimeInMillis() <= currentTime) {
            // Cycle boundary is before now, use next cycle boundary
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.add(Calendar.MONTH, 1);
            snapToCycleDay(cal, policy.cycleDay);
        }

        return cycle.toMillis(true);
        return cal.getTimeInMillis();
    }

    /**
@@ -313,16 +293,17 @@ public class NetworkPolicyManager {
     *
     * @hide
     */
    public static void snapToCycleDay(Time time, int cycleDay) {
        if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
            // cycle day isn't valid this month; snap to last second of month
            time.month += 1;
            time.monthDay = 1;
            time.second = -1;
    public static void snapToCycleDay(Calendar cal, int cycleDay) {
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        if (cycleDay > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.add(Calendar.MONTH, 1);
            cal.add(Calendar.SECOND, -1);
        } else {
            time.monthDay = cycleDay;
            cal.set(Calendar.DAY_OF_MONTH, cycleDay);
        }
        time.normalize(true);
    }

    /**
+24 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
@@ -86,7 +87,9 @@ import org.easymock.EasyMock;
import org.easymock.IAnswer;

import java.io.File;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -141,8 +144,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
    private static final int PID_2 = 401;
    private static final int PID_3 = 402;

    @Override
    public void setUp() throws Exception {
    public void _setUp() throws Exception {
        super.setUp();

        setCurrentTimeMillis(TEST_START);
@@ -229,8 +231,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {

    }

    @Override
    public void tearDown() throws Exception {
    public void _tearDown() throws Exception {
        for (File file : mPolicyDir.listFiles()) {
            file.delete();
        }
@@ -263,6 +264,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        backgroundChanged.get();
    }

    @Suppress
    public void testPidForegroundCombined() throws Exception {
        IdleFuture idle;

@@ -310,6 +312,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        assertFalse(mService.isUidForeground(UID_A));
    }

    @Suppress
    public void testScreenChangesRules() throws Exception {
        Future<Void> future;

@@ -351,6 +354,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        verifyAndReset();
    }

    @Suppress
    public void testPolicyNone() throws Exception {
        Future<Void> future;

@@ -381,6 +385,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        verifyAndReset();
    }

    @Suppress
    public void testPolicyReject() throws Exception {
        Future<Void> future;

@@ -412,6 +417,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        verifyAndReset();
    }

    @Suppress
    public void testPolicyRejectAddRemove() throws Exception {
        Future<Void> future;

@@ -576,6 +582,17 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
                computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
    }

    public void testLastCycleBoundaryDST() throws Exception {
        final long currentTime = parseTime("1989-01-02T07:30:00.000");
        final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");

        final NetworkPolicy policy = new NetworkPolicy(
                sTemplateWifi, 3, "America/Argentina/Buenos_Aires", 1024L, 1024L, false);
        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
        assertTimeEquals(expectedCycle, actualCycle);
    }

    @Suppress
    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
        NetworkState[] state = null;
        NetworkStats stats = null;
@@ -628,6 +645,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        verifyAndReset();
    }

    @Suppress
    public void testUidRemovedPolicyCleared() throws Exception {
        Future<Void> future;

@@ -652,6 +670,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        verifyAndReset();
    }

    @Suppress
    public void testOverWarningLimitNotification() throws Exception {
        NetworkState[] state = null;
        NetworkStats stats = null;
@@ -783,6 +802,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
        }
    }

    @Suppress
    public void testMeteredNetworkWithoutLimit() throws Exception {
        NetworkState[] state = null;
        NetworkStats stats = null;