1e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti/* 2e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * Copyright (C) 2015 The Android Open Source Project 3e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * 4e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License"); 5e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * you may not use this file except in compliance with the License. 6e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * You may obtain a copy of the License at 7e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * 8e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * http://www.apache.org/licenses/LICENSE-2.0 9e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * 10e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software 11e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS, 12e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * See the License for the specific language governing permissions and 14e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * limitations under the License. 15e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti */ 16e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 17e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittipackage com.android.internal.util; 18e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 19e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittiimport android.app.AlarmManager; 20e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittiimport android.content.Context; 21e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittiimport android.os.Handler; 22e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittiimport android.os.Message; 23e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 24e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colittiimport com.android.internal.annotations.VisibleForTesting; 25e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti 26e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti /** 27e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * An AlarmListener that sends the specified message to a Handler and keeps the system awake until 28e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * the message is processed. 29e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * 30e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * This is useful when using the AlarmManager direct callback interface to wake up the system and 31e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * request that an object whose API consists of messages (such as a StateMachine) perform some 32e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * action. 33e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * 34e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * In this situation, using AlarmManager.onAlarmListener by itself will wake up the system to send 35e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * the message, but does not guarantee that the system will be awake until the target object has 36e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * processed it. This is because as soon as the onAlarmListener sends the message and returns, the 37e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti * AlarmManager releases its wakelock and the system is free to go to sleep again. 38e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti */ 39e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colittipublic class WakeupMessage implements AlarmManager.OnAlarmListener { 40634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills private final AlarmManager mAlarmManager; 41e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti 42e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti @VisibleForTesting 43e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti protected final Handler mHandler; 44e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti @VisibleForTesting 45e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti protected final String mCmdName; 46e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti @VisibleForTesting 47e7636e47504034c048872f251a0a7cb240017b31Lorenzo Colitti protected final int mCmd, mArg1, mArg2; 48eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti @VisibleForTesting 49eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti protected final Object mObj; 50634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills private boolean mScheduled; 51e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 52e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti public WakeupMessage(Context context, Handler handler, 53eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti String cmdName, int cmd, int arg1, int arg2, Object obj) { 54634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 55e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti mHandler = handler; 56e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti mCmdName = cmdName; 57e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti mCmd = cmd; 58e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti mArg1 = arg1; 59e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti mArg2 = arg2; 60eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti mObj = obj; 61e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 62e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 63e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) { 64eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti this(context, handler, cmdName, cmd, arg1, 0, null); 65eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti } 66eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti 67eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti public WakeupMessage(Context context, Handler handler, 68eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti String cmdName, int cmd, int arg1, int arg2) { 69eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti this(context, handler, cmdName, cmd, arg1, arg2, null); 70e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 71e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 72e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) { 73eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti this(context, handler, cmdName, cmd, 0, 0, null); 74e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 75e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 76634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills /** 77634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * Schedule the message to be delivered at the time in milliseconds of the 78634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()} clock and wakeup 79634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * the device when it goes off. If schedule is called multiple times without the message being 80634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * dispatched then the alarm is rescheduled to the new time. 81634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills */ 82634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills public synchronized void schedule(long when) { 83634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mAlarmManager.setExact( 84e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mCmdName, this, mHandler); 85634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mScheduled = true; 86e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 87e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 88634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills /** 89634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * Cancel all pending messages. This includes alarms that may have been fired, but have not been 90634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills * run on the handler yet. 91634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills */ 92634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills public synchronized void cancel() { 93634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills if (mScheduled) { 94634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mAlarmManager.cancel(this); 95634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mScheduled = false; 96634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills } 97e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 98e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti 99e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti @Override 100e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti public void onAlarm() { 101634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills // Once this method is called the alarm has already been fired and removed from 102634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills // AlarmManager (it is still partially tracked, but only for statistics). The alarm can now 103634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills // be marked as unscheduled so that it can be rescheduled in the message handler. 104634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills final boolean stillScheduled; 105634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills synchronized (this) { 106634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills stillScheduled = mScheduled; 107634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills mScheduled = false; 108634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills } 109634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills if (stillScheduled) { 110eab17da5882e59caff25c73aa6bcd0587aca9dd4Lorenzo Colitti Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); 111a457ebbda6c84d5f6abd055828ef02ceaf809c08Erik Kline mHandler.dispatchMessage(msg); 112634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills msg.recycle(); 113634c1f9d0d43c7874ea433188b45fdf944d98a5aMitchell Wills } 114e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti } 115e9ae977322d40eff94fcbe3fad186cd082a577b6Lorenzo Colitti} 116