OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / java / com / android / server / ResettableTimeout.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.server;
18
19 import android.os.SystemClock;
20
21 import android.os.ConditionVariable;
22
23 /**
24  * Utility class that you can call on with a timeout, and get called back
25  * after a given time, dealing correctly with restarting the timeout.
26  *
27  * <p>For example, this class is used by the android.os.Vibrator class.
28  */
29 abstract class ResettableTimeout
30 {
31     /**
32      * Override this do what you need to do when it's starting
33      * This is called with the monitor on this method held, so be careful.
34      *
35      * @param alreadyOn is true if it's currently running
36      */
37     public abstract void on(boolean alreadyOn);
38
39     /**
40      * Override this to do what you need to do when it's stopping.
41      * This is called with the monitor on this method held, so be careful.
42      */
43     public abstract void off();
44
45     /**
46      * Does the following steps.
47      * <p>1. Call on()</p>
48      * <p>2. Start the timer.</p>
49      * <p>3. At the timeout, calls off()<p>
50      * <p>If you call this again, the timeout is reset to the new one</p>
51      */
52     public void go(long milliseconds)
53     {
54         synchronized (this) {
55             mOffAt = SystemClock.uptimeMillis() + milliseconds;
56
57             boolean alreadyOn;
58
59             // By starting the thread first and waiting, we ensure that if the
60             // thread to stop it can't start, we don't turn the vibrator on
61             // forever.  This still isn't really sufficient, because we don't
62             // have another processor watching us.  We really should have a
63             // service for this in case our process crashes.
64             if (mThread == null) {
65                 alreadyOn = false;
66                 mLock.close();
67                 mThread = new T();
68                 mThread.start();
69                 mLock.block();
70                 mOffCalled = false;
71             } else {
72                 alreadyOn = true;
73                 // poke the thread so it gets the new timeout.
74                 mThread.interrupt();
75             }
76             on(alreadyOn);
77         }
78     }
79
80     /**
81      * Cancel the timeout and call off now.
82      */
83     public void cancel()
84     {
85         synchronized (this) {
86             mOffAt = 0;
87             if (mThread != null) {
88                 mThread.interrupt();
89                 mThread = null;
90             }
91             if (!mOffCalled) {
92                 mOffCalled = true;
93                 off();
94             }
95         }
96     }
97
98     private class T extends Thread
99     {
100         public void run()
101         {
102             mLock.open();
103             while (true) {
104                 long diff;
105                 synchronized (this) {
106                     diff = mOffAt - SystemClock.uptimeMillis();
107                     if (diff <= 0) {
108                         mOffCalled = true;
109                         off();
110                         mThread = null;
111                         break;
112                     }
113                 }
114                 try {
115                     sleep(diff);
116                 }
117                 catch (InterruptedException e) {
118                 }
119             }
120         }
121     }
122
123     private ConditionVariable mLock = new ConditionVariable();
124
125     // turn it off at this time.
126     private volatile long mOffAt;
127     private volatile boolean mOffCalled;
128
129     private Thread mThread;
130
131 }
132