/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import android.os.SystemClock;

import android.os.ConditionVariable;

Utility class that you can call on with a timeout, and get called back after a given time, dealing correctly with restarting the timeout.

For example, this class is used by the android.os.Vibrator class.

/** * Utility class that you can call on with a timeout, and get called back * after a given time, dealing correctly with restarting the timeout. * * <p>For example, this class is used by the android.os.Vibrator class. */
abstract class ResettableTimeout {
Override this do what you need to do when it's starting This is called with the monitor on this method held, so be careful.
Params:
  • alreadyOn – is true if it's currently running
/** * Override this do what you need to do when it's starting * This is called with the monitor on this method held, so be careful. * * @param alreadyOn is true if it's currently running */
public abstract void on(boolean alreadyOn);
Override this to do what you need to do when it's stopping. This is called with the monitor on this method held, so be careful.
/** * Override this to do what you need to do when it's stopping. * This is called with the monitor on this method held, so be careful. */
public abstract void off();
Does the following steps.

1. Call on()

2. Start the timer.

3. At the timeout, calls off()

If you call this again, the timeout is reset to the new one

/** * Does the following steps. * <p>1. Call on()</p> * <p>2. Start the timer.</p> * <p>3. At the timeout, calls off()<p> * <p>If you call this again, the timeout is reset to the new one</p> */
public void go(long milliseconds) { synchronized (this) { mOffAt = SystemClock.uptimeMillis() + milliseconds; boolean alreadyOn; // By starting the thread first and waiting, we ensure that if the // thread to stop it can't start, we don't turn the vibrator on // forever. This still isn't really sufficient, because we don't // have another processor watching us. We really should have a // service for this in case our process crashes. if (mThread == null) { alreadyOn = false; mLock.close(); mThread = new T(); mThread.start(); mLock.block(); mOffCalled = false; } else { alreadyOn = true; // poke the thread so it gets the new timeout. mThread.interrupt(); } on(alreadyOn); } }
Cancel the timeout and call off now.
/** * Cancel the timeout and call off now. */
public void cancel() { synchronized (this) { mOffAt = 0; if (mThread != null) { mThread.interrupt(); mThread = null; } if (!mOffCalled) { mOffCalled = true; off(); } } } private class T extends Thread { public void run() { mLock.open(); while (true) { long diff; synchronized (this) { diff = mOffAt - SystemClock.uptimeMillis(); if (diff <= 0) { mOffCalled = true; off(); mThread = null; break; } } try { sleep(diff); } catch (InterruptedException e) { } } } } private ConditionVariable mLock = new ConditionVariable(); // turn it off at this time. private volatile long mOffAt; private volatile boolean mOffCalled; private Thread mThread; }