Loading common/java/com/android/common/OperationScheduler.java +23 −1 Original line number Diff line number Diff line Loading @@ -192,7 +192,6 @@ public class OperationScheduler { /** * Forbid any operations until after a certain (absolute) time. * Commonly used when a server returns a "Retry-After:" type directive. * Limited by {@link #Options.maxMoratoriumMillis}. * * @param millis wall clock time ({@link System#currentTimeMillis()}) to Loading @@ -205,6 +204,29 @@ public class OperationScheduler { .commit(); } /** * Forbid any operations until after a certain time, as specified in * the format used by the HTTP "Retry-After" header. * Limited by {@link #Options.maxMoratoriumMillis}. * * @param retryAfter moratorium time in HTTP format * @return true if a time was successfully parsed */ public boolean setMoratoriumTimeHttp(String retryAfter) { try { long ms = Long.valueOf(retryAfter) * 1000; setMoratoriumTimeMillis(ms + System.currentTimeMillis()); return true; } catch (NumberFormatException nfe) { try { setMoratoriumTimeMillis(HttpDateTime.parse(retryAfter)); return true; } catch (IllegalArgumentException iae) { return false; } } } /** * Enable or disable all operations. When disabled, all calls to * {@link #getNextTimeMillis()} return {@link Long#MAX_VALUE}. Loading common/tests/src/com/android/common/OperationSchedulerTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -113,4 +113,32 @@ public class OperationSchedulerTest extends AndroidTestCase { "OperationScheduler.Options[backoff=10.0+2.5 max=12345.6 min=7.0 period=3800.0]", OperationScheduler.parseOptions("", options).toString()); } public void testMoratoriumWithHttpDate() throws Exception { String name = "OperationSchedulerTest.testMoratoriumWithHttpDate"; SharedPreferences storage = getContext().getSharedPreferences(name, 0); storage.edit().clear().commit(); OperationScheduler scheduler = new OperationScheduler(storage); OperationScheduler.Options options = new OperationScheduler.Options(); long beforeTrigger = System.currentTimeMillis(); scheduler.setTriggerTimeMillis(beforeTrigger + 1000000); assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options)); scheduler.setMoratoriumTimeMillis(beforeTrigger + 2000000); assertEquals(beforeTrigger + 2000000, scheduler.getNextTimeMillis(options)); long beforeMoratorium = System.currentTimeMillis(); assertTrue(scheduler.setMoratoriumTimeHttp("3000")); long afterMoratorium = System.currentTimeMillis(); assertTrue(beforeMoratorium + 3000000 <= scheduler.getNextTimeMillis(options)); assertTrue(afterMoratorium + 3000000 >= scheduler.getNextTimeMillis(options)); options.maxMoratoriumMillis = Long.MAX_VALUE / 2; assertTrue(scheduler.setMoratoriumTimeHttp("Fri, 31 Dec 2030 23:59:59 GMT")); assertEquals(1924991999000L, scheduler.getNextTimeMillis(options)); assertFalse(scheduler.setMoratoriumTimeHttp("not actually a date")); } } Loading
common/java/com/android/common/OperationScheduler.java +23 −1 Original line number Diff line number Diff line Loading @@ -192,7 +192,6 @@ public class OperationScheduler { /** * Forbid any operations until after a certain (absolute) time. * Commonly used when a server returns a "Retry-After:" type directive. * Limited by {@link #Options.maxMoratoriumMillis}. * * @param millis wall clock time ({@link System#currentTimeMillis()}) to Loading @@ -205,6 +204,29 @@ public class OperationScheduler { .commit(); } /** * Forbid any operations until after a certain time, as specified in * the format used by the HTTP "Retry-After" header. * Limited by {@link #Options.maxMoratoriumMillis}. * * @param retryAfter moratorium time in HTTP format * @return true if a time was successfully parsed */ public boolean setMoratoriumTimeHttp(String retryAfter) { try { long ms = Long.valueOf(retryAfter) * 1000; setMoratoriumTimeMillis(ms + System.currentTimeMillis()); return true; } catch (NumberFormatException nfe) { try { setMoratoriumTimeMillis(HttpDateTime.parse(retryAfter)); return true; } catch (IllegalArgumentException iae) { return false; } } } /** * Enable or disable all operations. When disabled, all calls to * {@link #getNextTimeMillis()} return {@link Long#MAX_VALUE}. Loading
common/tests/src/com/android/common/OperationSchedulerTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -113,4 +113,32 @@ public class OperationSchedulerTest extends AndroidTestCase { "OperationScheduler.Options[backoff=10.0+2.5 max=12345.6 min=7.0 period=3800.0]", OperationScheduler.parseOptions("", options).toString()); } public void testMoratoriumWithHttpDate() throws Exception { String name = "OperationSchedulerTest.testMoratoriumWithHttpDate"; SharedPreferences storage = getContext().getSharedPreferences(name, 0); storage.edit().clear().commit(); OperationScheduler scheduler = new OperationScheduler(storage); OperationScheduler.Options options = new OperationScheduler.Options(); long beforeTrigger = System.currentTimeMillis(); scheduler.setTriggerTimeMillis(beforeTrigger + 1000000); assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options)); scheduler.setMoratoriumTimeMillis(beforeTrigger + 2000000); assertEquals(beforeTrigger + 2000000, scheduler.getNextTimeMillis(options)); long beforeMoratorium = System.currentTimeMillis(); assertTrue(scheduler.setMoratoriumTimeHttp("3000")); long afterMoratorium = System.currentTimeMillis(); assertTrue(beforeMoratorium + 3000000 <= scheduler.getNextTimeMillis(options)); assertTrue(afterMoratorium + 3000000 >= scheduler.getNextTimeMillis(options)); options.maxMoratoriumMillis = Long.MAX_VALUE / 2; assertTrue(scheduler.setMoratoriumTimeHttp("Fri, 31 Dec 2030 23:59:59 GMT")); assertEquals(1924991999000L, scheduler.getNextTimeMillis(options)); assertFalse(scheduler.setMoratoriumTimeHttp("not actually a date")); } }