diff options
author | Christopher Tate <ctate@google.com> | 2013-07-20 01:56:17 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-07-20 01:56:17 +0000 |
commit | d55e18eceac46160440054c6725b3461a1ccc1dd (patch) | |
tree | ec8f1dbe3b5e5762d53ee298db87df6f72faf0a7 | |
parent | 37ee2647d4e53da9a621e3116184b3d108c431b9 (diff) | |
parent | 57ceaaa0aa1fece02ff82cd903a26bdf65131c56 (diff) |
Merge "Add AlarmManager.setWindow(...) for supplying an explicit delivery window"
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/AlarmManager.java | 69 | ||||
-rw-r--r-- | core/java/android/app/IAlarmManager.aidl | 4 | ||||
-rw-r--r-- | services/java/com/android/server/AlarmManagerService.java | 46 |
4 files changed, 94 insertions, 26 deletions
diff --git a/api/current.txt b/api/current.txt index e7a518f6447b..ee0c3951909c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3057,6 +3057,7 @@ package android.app { method public void setRepeating(int, long, long, android.app.PendingIntent); method public void setTime(long); method public void setTimeZone(java.lang.String); + method public void setWindow(int, long, long, android.app.PendingIntent); field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 field public static final deprecated long INTERVAL_DAY = 86400000L; // 0x5265c00L diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index dbccbebbd739..d9c377545499 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -84,9 +84,15 @@ public class AlarmManager */ public static final int ELAPSED_REALTIME = 3; + /** @hide */ + public static final long WINDOW_EXACT = 0; + /** @hide */ + public static final long WINDOW_HEURISTIC = -1; + private final IAlarmManager mService; private final boolean mAlwaysExact; + /** * package private on purpose */ @@ -96,9 +102,15 @@ public class AlarmManager final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion; mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KEY_LIME_PIE); } - + + private long legacyExactLength() { + return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC); + } + /** - * Schedule an alarm. <b>Note: for timing operations (ticks, timeouts, + * TBW: discussion of fuzzy nature of alarms in KLP+. + * + * <p>Schedule an alarm. <b>Note: for timing operations (ticks, timeouts, * etc) it is easier and much more efficient to use * {@link android.os.Handler}.</b> If there is already an alarm scheduled * for the same IntentSender, it will first be canceled. @@ -130,7 +142,9 @@ public class AlarmManager * IntentSender.getBroadcast()}. * * @see android.os.Handler + * @see #setExact * @see #setRepeating + * @see #setWindow * @see #cancel * @see android.content.Context#sendBroadcast * @see android.content.Context#registerReceiver @@ -141,7 +155,7 @@ public class AlarmManager * @see #RTC_WAKEUP */ public void set(int type, long triggerAtMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, 0, operation, mAlwaysExact); + setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation); } /** @@ -182,6 +196,8 @@ public class AlarmManager * * @see android.os.Handler * @see #set + * @see #setExact + * @see #setWindow * @see #cancel * @see android.content.Context#sendBroadcast * @see android.content.Context#registerReceiver @@ -193,7 +209,42 @@ public class AlarmManager */ public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, intervalMillis, operation, mAlwaysExact); + setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation); + } + + /** + * Schedule an alarm to be delivered within a given window of time. + * + * TBW: clean up these docs + * + * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or + * RTC_WAKEUP. + * @param windowStartMillis The earliest time, in milliseconds, that the alarm should + * be delivered, expressed in the appropriate clock's units (depending on the alarm + * type). + * @param windowLengthMillis The length of the requested delivery window, + * in milliseconds. The alarm will be delivered no later than this many + * milliseconds after the windowStartMillis time. Note that this parameter + * is a <i>duration,</i> not the timestamp of the end of the window. + * @param operation Action to perform when the alarm goes off; + * typically comes from {@link PendingIntent#getBroadcast + * IntentSender.getBroadcast()}. + * + * @see #set + * @see #setExact + * @see #setRepeating + * @see #cancel + * @see android.content.Context#sendBroadcast + * @see android.content.Context#registerReceiver + * @see android.content.Intent#filterEquals + * @see #ELAPSED_REALTIME + * @see #ELAPSED_REALTIME_WAKEUP + * @see #RTC + * @see #RTC_WAKEUP + */ + public void setWindow(int type, long windowStartMillis, long windowLengthMillis, + PendingIntent operation) { + setImpl(type, windowStartMillis, windowLengthMillis, 0, operation); } /** @@ -201,13 +252,13 @@ public class AlarmManager * to the precise time specified. */ public void setExact(int type, long triggerAtMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, 0, operation, true); + setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation); } - private void setImpl(int type, long triggerAtMillis, long intervalMillis, - PendingIntent operation, boolean isExact) { + private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, + PendingIntent operation) { try { - mService.set(type, triggerAtMillis, intervalMillis, operation, isExact); + mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation); } catch (RemoteException ex) { } } @@ -300,7 +351,7 @@ public class AlarmManager @Deprecated public void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { - setRepeating(type, triggerAtMillis, intervalMillis, operation); + setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation); } /** diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl index 3a2b21518cfa..0a49ddf02ec9 100644 --- a/core/java/android/app/IAlarmManager.aidl +++ b/core/java/android/app/IAlarmManager.aidl @@ -24,7 +24,9 @@ import android.app.PendingIntent; * {@hide} */ interface IAlarmManager { - void set(int type, long triggerAtTime, long interval, in PendingIntent operation, boolean isExact); + /** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */ + void set(int type, long triggerAtTime, long windowLength, + long interval, in PendingIntent operation); void setTime(long millis); void setTimeZone(String zone); void remove(in PendingIntent operation); diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index e78b822d1b77..d7cdb9d4f32a 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import android.app.Activity; import android.app.ActivityManagerNative; +import android.app.AlarmManager; import android.app.IAlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -314,7 +315,7 @@ class AlarmManagerService extends IAlarmManager.Stub { } // minimum recurrence period or alarm futurity for us to be able to fuzz it - private static final long MAX_FUZZABLE_INTERVAL = 10000; + private static final long MIN_FUZZABLE_INTERVAL = 10000; private static final BatchTimeOrder sBatchOrder = new BatchTimeOrder(); private final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>(); @@ -336,7 +337,7 @@ class AlarmManagerService extends IAlarmManager.Stub { long futurity = (interval == 0) ? (triggerAtTime - now) : interval; - if (futurity < MAX_FUZZABLE_INTERVAL) { + if (futurity < MIN_FUZZABLE_INTERVAL) { futurity = 0; } return triggerAtTime + (long)(.75 * futurity); @@ -499,32 +500,45 @@ class AlarmManagerService extends IAlarmManager.Stub { } @Override - public void set(int type, long triggerAtTime, long interval, - PendingIntent operation, boolean isExact) { - set(type, triggerAtTime, interval, operation, isExact, false); + public void set(int type, long triggerAtTime, long windowLength, long interval, + PendingIntent operation) { + set(type, triggerAtTime, windowLength, interval, operation, false); } - public void set(int type, long triggerAtTime, long interval, - PendingIntent operation, boolean isExact, boolean isStandalone) { + public void set(int type, long triggerAtTime, long windowLength, long interval, + PendingIntent operation, boolean isStandalone) { if (operation == null) { Slog.w(TAG, "set/setRepeating ignored because there is no intent"); return; } + // Sanity check the window length. This will catch people mistakenly + // trying to pass an end-of-window timestamp rather than a duration. + if (windowLength > AlarmManager.INTERVAL_HALF_DAY) { + Slog.w(TAG, "Window length " + windowLength + + "ms suspiciously long; limiting to 1 hour"); + windowLength = AlarmManager.INTERVAL_HOUR; + } + if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) { throw new IllegalArgumentException("Invalid alarm type " + type); } - long nowElapsed = SystemClock.elapsedRealtime(); - long triggerElapsed = convertToElapsed(triggerAtTime, type); - long maxElapsed = (isExact) - ? triggerElapsed - : maxTriggerTime(nowElapsed, triggerElapsed, interval); + final long nowElapsed = SystemClock.elapsedRealtime(); + final long triggerElapsed = convertToElapsed(triggerAtTime, type); + final long maxElapsed; + if (windowLength == AlarmManager.WINDOW_EXACT) { + maxElapsed = triggerElapsed; + } else if (windowLength < 0) { + maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval); + } else { + maxElapsed = triggerElapsed + windowLength; + } synchronized (mLock) { if (DEBUG_BATCH) { Slog.v(TAG, "set(" + operation + ") : type=" + type - + " triggerAtTime=" + triggerAtTime + + " triggerAtTime=" + triggerAtTime + " win=" + windowLength + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed + " interval=" + interval + " standalone=" + isStandalone); } @@ -1218,8 +1232,8 @@ class AlarmManagerService extends IAlarmManager.Stub { // the top of the next minute. final long tickEventDelay = nextTime - currentTime; - set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, - 0, mTimeTickSender, true, true); + set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0, + 0, mTimeTickSender, true); } public void scheduleDateChangedEvent() { @@ -1231,7 +1245,7 @@ class AlarmManagerService extends IAlarmManager.Stub { calendar.set(Calendar.MILLISECOND, 0); calendar.add(Calendar.DAY_OF_MONTH, 1); - set(RTC, calendar.getTimeInMillis(), 0, mDateChangeSender, true, true); + set(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true); } } |