Loading Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ LOCAL_SRC_FILES += \ core/java/android/app/IActivityContainerCallback.aidl \ core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IAlarmCompleteListener.aidl \ core/java/android/app/IAlarmListener.aidl \ core/java/android/app/IAlarmManager.aidl \ core/java/android/app/IAppTask.aidl \ core/java/android/app/ITaskStackListener.aidl \ Loading api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -3764,17 +3764,21 @@ package android.app { public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void cancel(android.app.AlarmManager.OnAlarmListener); method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock(); method public void set(int, long, android.app.PendingIntent); method public void set(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent); method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setExact(int, long, android.app.PendingIntent); method public void setExact(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setInexactRepeating(int, long, long, android.app.PendingIntent); 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); method public void setWindow(int, long, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); field public static final java.lang.String ACTION_NEXT_ALARM_CLOCK_CHANGED = "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 Loading @@ -3796,6 +3800,10 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AlarmManager.AlarmClockInfo> CREATOR; } public static abstract interface AlarmManager.OnAlarmListener { method public abstract void onAlarm(); } public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface { ctor protected AlertDialog(android.content.Context); ctor protected AlertDialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener); api/system-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -3873,18 +3873,22 @@ package android.app { public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void cancel(android.app.AlarmManager.OnAlarmListener); method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock(); method public void set(int, long, android.app.PendingIntent); method public void set(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void set(int, long, long, long, android.app.PendingIntent, android.os.WorkSource); method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent); method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setExact(int, long, android.app.PendingIntent); method public void setExact(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setInexactRepeating(int, long, long, android.app.PendingIntent); 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); method public void setWindow(int, long, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); field public static final java.lang.String ACTION_NEXT_ALARM_CLOCK_CHANGED = "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 Loading @@ -3906,6 +3910,10 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AlarmManager.AlarmClockInfo> CREATOR; } public static abstract interface AlarmManager.OnAlarmListener { method public abstract void onAlarm(); } public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface { ctor protected AlertDialog(android.content.Context); ctor protected AlertDialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener); core/java/android/app/ActivityManagerNative.java +4 −3 Original line number Diff line number Diff line Loading @@ -116,21 +116,22 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg, String tag) { try { getDefault().noteWakeupAlarm(ps.getTarget(), sourceUid, sourcePkg, tag); getDefault().noteWakeupAlarm((ps != null) ? ps.getTarget() : null, sourceUid, sourcePkg, tag); } catch (RemoteException ex) { } } static public void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) { try { getDefault().noteAlarmStart(ps.getTarget(), sourceUid, tag); getDefault().noteAlarmStart((ps != null) ? ps.getTarget() : null, sourceUid, tag); } catch (RemoteException ex) { } } static public void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) { try { getDefault().noteAlarmFinish(ps.getTarget(), sourceUid, tag); getDefault().noteAlarmFinish((ps != null) ? ps.getTarget() : null, sourceUid, tag); } catch (RemoteException ex) { } } Loading core/java/android/app/AlarmManager.java +242 −17 Original line number Diff line number Diff line Loading @@ -21,15 +21,21 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.text.TextUtils; import android.util.Log; import libcore.util.ZoneInfoDB; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.WeakHashMap; /** * This class provides access to the system alarm services. These allow you Loading Loading @@ -72,6 +78,8 @@ import java.io.IOException; * Context.getSystemService(Context.ALARM_SERVICE)}. */ public class AlarmManager { private static final String TAG = "AlarmManager"; /** * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} * (wall clock time in UTC), which will wake up the device when Loading Loading @@ -160,9 +168,89 @@ public class AlarmManager { public static final int FLAG_IDLE_UNTIL = 1<<4; private final IAlarmManager mService; private final String mPackageName; private final boolean mAlwaysExact; private final int mTargetSdkVersion; private final Handler mMainThreadHandler; /** * Direct-notification alarms: the requester must be running continuously from the * time the alarm is set to the time it is delivered, or delivery will fail. Only * one-shot alarms can be set using this mechanism, not repeating alarms. */ public interface OnAlarmListener { /** * Callback method that is invoked by the system when the alarm time is reached. */ public void onAlarm(); } final class ListenerWrapper extends IAlarmListener.Stub implements Runnable { final OnAlarmListener mListener; Handler mHandler; IAlarmCompleteListener mCompletion; public ListenerWrapper(OnAlarmListener listener) { mListener = listener; } public void setHandler(Handler h) { mHandler = h; } public void cancel() { try { mService.remove(null, this); } catch (RemoteException ex) { } synchronized (AlarmManager.class) { if (sWrappers != null) { sWrappers.remove(mListener); } } } @Override public void doAlarm(IAlarmCompleteListener alarmManager) { mCompletion = alarmManager; mHandler.post(this); } @Override public void run() { // Remove this listener from the wrapper cache first; the server side // already considers it gone synchronized (AlarmManager.class) { if (sWrappers != null) { sWrappers.remove(mListener); } } // Now deliver it to the app try { mListener.onAlarm(); } finally { // No catch -- make sure to report completion to the system process, // but continue to allow the exception to crash the app. try { mCompletion.alarmComplete(this); } catch (Exception e) { Log.e(TAG, "Unable to report completion to Alarm Manager!", e); } } } } // Tracking of the OnAlarmListener -> wrapper mapping, for cancel() support. // Access is synchronized on the AlarmManager class object. // // These are weak references so that we don't leak listener references if, for // example, the pending-alarm messages are posted to a HandlerThread that is // disposed of prior to alarm delivery. The underlying messages will be GC'd // but this static reference would still persist, orphaned, never deallocated. private static WeakHashMap<OnAlarmListener, WeakReference<ListenerWrapper>> sWrappers; /** * package private on purpose Loading @@ -170,8 +258,10 @@ public class AlarmManager { AlarmManager(IAlarmManager service, Context ctx) { mService = service; mPackageName = ctx.getPackageName(); mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion; mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT); mMainThreadHandler = new Handler(ctx.getMainLooper()); } private long legacyExactLength() { Loading Loading @@ -249,7 +339,37 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void set(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null); setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #set(int, long, PendingIntent)}. Rather than * supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, * {@link #RTC}, or {@link #RTC_WAKEUP}. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param tag string describing the alarm, used for logging and battery-use * attribution * @param listener {@link OnAlarmListener} instance whose * {@link OnAlarmListener#onAlarm() onAlarm()} method will be * called when the alarm time is reached. A given OnAlarmListener instance can * only be the target of a single pending alarm, just as a given PendingIntent * can only be used with one alarm at a time. * @param targetHandler {@link Handler} on which to execute the listener's onAlarm() * callback, or {@code null} to run that callback on the main looper. */ public void set(int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading Loading @@ -310,8 +430,8 @@ public class AlarmManager { */ public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null); setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null, null, null, null); } /** Loading Loading @@ -361,7 +481,23 @@ public class AlarmManager { */ public void setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null); setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #setWindow(int, long, long, PendingIntent)}. Rather * than supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ public void setWindow(int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading Loading @@ -399,7 +535,23 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void setExact(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #setExact(int, long, PendingIntent)}. Rather * than supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ public void setExact(int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading @@ -408,7 +560,8 @@ public class AlarmManager { * @hide */ public void setIdleUntil(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, operation, null, null, null, null, null); } /** Loading Loading @@ -436,19 +589,38 @@ public class AlarmManager { * @see android.content.Intent#filterEquals */ public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) { setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation, null, info); setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation, null, null, null, null, info); } /** @hide */ @SystemApi public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, PendingIntent operation, WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, workSource, null); setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null, null, workSource, null); } /** * Direct callback version of {@link #set(int, long, long, long, PendingIntent, WorkSource)}. * Note that repeating alarms must use the PendingIntent variant, not an OnAlarmListener. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * @hide */ //@SystemApi public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, OnAlarmListener listener, Handler targetHandler, WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener, null, targetHandler, workSource, null); } private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, int flags, PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) { int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag, Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) { if (triggerAtMillis < 0) { /* NOTYET if (mAlwaysExact) { Loading @@ -460,9 +632,30 @@ public class AlarmManager { triggerAtMillis = 0; } ListenerWrapper recipientWrapper = null; if (listener != null) { synchronized (AlarmManager.class) { if (sWrappers == null) { sWrappers = new WeakHashMap<OnAlarmListener, WeakReference<ListenerWrapper>>(); } WeakReference<ListenerWrapper> wrapperRef = sWrappers.get(listener); // no existing wrapper *or* we've lost our weak ref to it => build a new one if (wrapperRef == null || (recipientWrapper = wrapperRef.get()) == null) { recipientWrapper = new ListenerWrapper(listener); wrapperRef = new WeakReference<ListenerWrapper>(recipientWrapper); sWrappers.put(listener, wrapperRef); } } final Handler handler = (targetHandler != null) ? targetHandler : mMainThreadHandler; recipientWrapper.setHandler(handler); } try { mService.set(type, triggerAtMillis, windowMillis, intervalMillis, flags, operation, workSource, alarmClock); mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags, operation, recipientWrapper, listenerTag, workSource, alarmClock); } catch (RemoteException ex) { } } Loading Loading @@ -562,7 +755,8 @@ public class AlarmManager { */ public void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null, null, null, null); } /** Loading Loading @@ -611,8 +805,8 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null, null, null, null); } /** Loading Loading @@ -666,7 +860,7 @@ public class AlarmManager { */ public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null); null, null, null, null, null); } /** Loading @@ -680,12 +874,43 @@ public class AlarmManager { * @see #set */ public void cancel(PendingIntent operation) { if (operation == null) { throw new NullPointerException("operation"); } try { mService.remove(operation); mService.remove(operation, null); } catch (RemoteException ex) { } } /** * Remove any alarm scheduled to be delivered to the given {@link OnAlarmListener}. * * @param listener OnAlarmListener instance that is the target of a currently-set alarm. */ public void cancel(OnAlarmListener listener) { if (listener == null) { throw new NullPointerException("listener"); } ListenerWrapper wrapper = null; synchronized (AlarmManager.class) { final WeakReference<ListenerWrapper> wrapperRef; wrapperRef = sWrappers.get(listener); if (wrapperRef != null) { wrapper = wrapperRef.get(); } } if (wrapper == null) { Log.w(TAG, "Unrecognized alarm listener " + listener); return; } wrapper.cancel(); } /** * Set the system wall clock time. * Requires the permission android.permission.SET_TIME. Loading Loading
Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ LOCAL_SRC_FILES += \ core/java/android/app/IActivityContainerCallback.aidl \ core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IAlarmCompleteListener.aidl \ core/java/android/app/IAlarmListener.aidl \ core/java/android/app/IAlarmManager.aidl \ core/java/android/app/IAppTask.aidl \ core/java/android/app/ITaskStackListener.aidl \ Loading
api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -3764,17 +3764,21 @@ package android.app { public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void cancel(android.app.AlarmManager.OnAlarmListener); method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock(); method public void set(int, long, android.app.PendingIntent); method public void set(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent); method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setExact(int, long, android.app.PendingIntent); method public void setExact(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setInexactRepeating(int, long, long, android.app.PendingIntent); 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); method public void setWindow(int, long, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); field public static final java.lang.String ACTION_NEXT_ALARM_CLOCK_CHANGED = "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 Loading @@ -3796,6 +3800,10 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AlarmManager.AlarmClockInfo> CREATOR; } public static abstract interface AlarmManager.OnAlarmListener { method public abstract void onAlarm(); } public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface { ctor protected AlertDialog(android.content.Context); ctor protected AlertDialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener);
api/system-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -3873,18 +3873,22 @@ package android.app { public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void cancel(android.app.AlarmManager.OnAlarmListener); method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock(); method public void set(int, long, android.app.PendingIntent); method public void set(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void set(int, long, long, long, android.app.PendingIntent, android.os.WorkSource); method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent); method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setExact(int, long, android.app.PendingIntent); method public void setExact(int, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent); method public void setInexactRepeating(int, long, long, android.app.PendingIntent); 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); method public void setWindow(int, long, long, java.lang.String, android.app.AlarmManager.OnAlarmListener, android.os.Handler); field public static final java.lang.String ACTION_NEXT_ALARM_CLOCK_CHANGED = "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 Loading @@ -3906,6 +3910,10 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AlarmManager.AlarmClockInfo> CREATOR; } public static abstract interface AlarmManager.OnAlarmListener { method public abstract void onAlarm(); } public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface { ctor protected AlertDialog(android.content.Context); ctor protected AlertDialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener);
core/java/android/app/ActivityManagerNative.java +4 −3 Original line number Diff line number Diff line Loading @@ -116,21 +116,22 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg, String tag) { try { getDefault().noteWakeupAlarm(ps.getTarget(), sourceUid, sourcePkg, tag); getDefault().noteWakeupAlarm((ps != null) ? ps.getTarget() : null, sourceUid, sourcePkg, tag); } catch (RemoteException ex) { } } static public void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) { try { getDefault().noteAlarmStart(ps.getTarget(), sourceUid, tag); getDefault().noteAlarmStart((ps != null) ? ps.getTarget() : null, sourceUid, tag); } catch (RemoteException ex) { } } static public void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) { try { getDefault().noteAlarmFinish(ps.getTarget(), sourceUid, tag); getDefault().noteAlarmFinish((ps != null) ? ps.getTarget() : null, sourceUid, tag); } catch (RemoteException ex) { } } Loading
core/java/android/app/AlarmManager.java +242 −17 Original line number Diff line number Diff line Loading @@ -21,15 +21,21 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.text.TextUtils; import android.util.Log; import libcore.util.ZoneInfoDB; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.WeakHashMap; /** * This class provides access to the system alarm services. These allow you Loading Loading @@ -72,6 +78,8 @@ import java.io.IOException; * Context.getSystemService(Context.ALARM_SERVICE)}. */ public class AlarmManager { private static final String TAG = "AlarmManager"; /** * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} * (wall clock time in UTC), which will wake up the device when Loading Loading @@ -160,9 +168,89 @@ public class AlarmManager { public static final int FLAG_IDLE_UNTIL = 1<<4; private final IAlarmManager mService; private final String mPackageName; private final boolean mAlwaysExact; private final int mTargetSdkVersion; private final Handler mMainThreadHandler; /** * Direct-notification alarms: the requester must be running continuously from the * time the alarm is set to the time it is delivered, or delivery will fail. Only * one-shot alarms can be set using this mechanism, not repeating alarms. */ public interface OnAlarmListener { /** * Callback method that is invoked by the system when the alarm time is reached. */ public void onAlarm(); } final class ListenerWrapper extends IAlarmListener.Stub implements Runnable { final OnAlarmListener mListener; Handler mHandler; IAlarmCompleteListener mCompletion; public ListenerWrapper(OnAlarmListener listener) { mListener = listener; } public void setHandler(Handler h) { mHandler = h; } public void cancel() { try { mService.remove(null, this); } catch (RemoteException ex) { } synchronized (AlarmManager.class) { if (sWrappers != null) { sWrappers.remove(mListener); } } } @Override public void doAlarm(IAlarmCompleteListener alarmManager) { mCompletion = alarmManager; mHandler.post(this); } @Override public void run() { // Remove this listener from the wrapper cache first; the server side // already considers it gone synchronized (AlarmManager.class) { if (sWrappers != null) { sWrappers.remove(mListener); } } // Now deliver it to the app try { mListener.onAlarm(); } finally { // No catch -- make sure to report completion to the system process, // but continue to allow the exception to crash the app. try { mCompletion.alarmComplete(this); } catch (Exception e) { Log.e(TAG, "Unable to report completion to Alarm Manager!", e); } } } } // Tracking of the OnAlarmListener -> wrapper mapping, for cancel() support. // Access is synchronized on the AlarmManager class object. // // These are weak references so that we don't leak listener references if, for // example, the pending-alarm messages are posted to a HandlerThread that is // disposed of prior to alarm delivery. The underlying messages will be GC'd // but this static reference would still persist, orphaned, never deallocated. private static WeakHashMap<OnAlarmListener, WeakReference<ListenerWrapper>> sWrappers; /** * package private on purpose Loading @@ -170,8 +258,10 @@ public class AlarmManager { AlarmManager(IAlarmManager service, Context ctx) { mService = service; mPackageName = ctx.getPackageName(); mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion; mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT); mMainThreadHandler = new Handler(ctx.getMainLooper()); } private long legacyExactLength() { Loading Loading @@ -249,7 +339,37 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void set(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null); setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #set(int, long, PendingIntent)}. Rather than * supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, * {@link #RTC}, or {@link #RTC_WAKEUP}. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param tag string describing the alarm, used for logging and battery-use * attribution * @param listener {@link OnAlarmListener} instance whose * {@link OnAlarmListener#onAlarm() onAlarm()} method will be * called when the alarm time is reached. A given OnAlarmListener instance can * only be the target of a single pending alarm, just as a given PendingIntent * can only be used with one alarm at a time. * @param targetHandler {@link Handler} on which to execute the listener's onAlarm() * callback, or {@code null} to run that callback on the main looper. */ public void set(int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading Loading @@ -310,8 +430,8 @@ public class AlarmManager { */ public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null); setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null, null, null, null); } /** Loading Loading @@ -361,7 +481,23 @@ public class AlarmManager { */ public void setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null); setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #setWindow(int, long, long, PendingIntent)}. Rather * than supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ public void setWindow(int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading Loading @@ -399,7 +535,23 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void setExact(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null, null, null, null); } /** * Direct callback version of {@link #setExact(int, long, PendingIntent)}. Rather * than supplying a PendingIntent to be sent when the alarm time is reached, this variant * supplies an {@link OnAlarmListener} instance that will be invoked at that time. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ public void setExact(int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, null, listener, tag, targetHandler, null, null); } /** Loading @@ -408,7 +560,8 @@ public class AlarmManager { * @hide */ public void setIdleUntil(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, operation, null, null, null, null, null); } /** Loading Loading @@ -436,19 +589,38 @@ public class AlarmManager { * @see android.content.Intent#filterEquals */ public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) { setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation, null, info); setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation, null, null, null, null, info); } /** @hide */ @SystemApi public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, PendingIntent operation, WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, workSource, null); setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null, null, workSource, null); } /** * Direct callback version of {@link #set(int, long, long, long, PendingIntent, WorkSource)}. * Note that repeating alarms must use the PendingIntent variant, not an OnAlarmListener. * <p> * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * @hide */ //@SystemApi public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, OnAlarmListener listener, Handler targetHandler, WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener, null, targetHandler, workSource, null); } private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, int flags, PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) { int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag, Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) { if (triggerAtMillis < 0) { /* NOTYET if (mAlwaysExact) { Loading @@ -460,9 +632,30 @@ public class AlarmManager { triggerAtMillis = 0; } ListenerWrapper recipientWrapper = null; if (listener != null) { synchronized (AlarmManager.class) { if (sWrappers == null) { sWrappers = new WeakHashMap<OnAlarmListener, WeakReference<ListenerWrapper>>(); } WeakReference<ListenerWrapper> wrapperRef = sWrappers.get(listener); // no existing wrapper *or* we've lost our weak ref to it => build a new one if (wrapperRef == null || (recipientWrapper = wrapperRef.get()) == null) { recipientWrapper = new ListenerWrapper(listener); wrapperRef = new WeakReference<ListenerWrapper>(recipientWrapper); sWrappers.put(listener, wrapperRef); } } final Handler handler = (targetHandler != null) ? targetHandler : mMainThreadHandler; recipientWrapper.setHandler(handler); } try { mService.set(type, triggerAtMillis, windowMillis, intervalMillis, flags, operation, workSource, alarmClock); mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags, operation, recipientWrapper, listenerTag, workSource, alarmClock); } catch (RemoteException ex) { } } Loading Loading @@ -562,7 +755,8 @@ public class AlarmManager { */ public void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null, null, null, null); } /** Loading Loading @@ -611,8 +805,8 @@ public class AlarmManager { * @see #RTC_WAKEUP */ public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null); setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null, null, null, null); } /** Loading Loading @@ -666,7 +860,7 @@ public class AlarmManager { */ public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null); null, null, null, null, null); } /** Loading @@ -680,12 +874,43 @@ public class AlarmManager { * @see #set */ public void cancel(PendingIntent operation) { if (operation == null) { throw new NullPointerException("operation"); } try { mService.remove(operation); mService.remove(operation, null); } catch (RemoteException ex) { } } /** * Remove any alarm scheduled to be delivered to the given {@link OnAlarmListener}. * * @param listener OnAlarmListener instance that is the target of a currently-set alarm. */ public void cancel(OnAlarmListener listener) { if (listener == null) { throw new NullPointerException("listener"); } ListenerWrapper wrapper = null; synchronized (AlarmManager.class) { final WeakReference<ListenerWrapper> wrapperRef; wrapperRef = sWrappers.get(listener); if (wrapperRef != null) { wrapper = wrapperRef.get(); } } if (wrapper == null) { Log.w(TAG, "Unrecognized alarm listener " + listener); return; } wrapper.cancel(); } /** * Set the system wall clock time. * Requires the permission android.permission.SET_TIME. Loading