1bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette/*
2bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * Copyright (C) 2015 The Android Open Source Project
3bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *
4bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
5bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * you may not use this file except in compliance with the License.
6bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * You may obtain a copy of the License at
7bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *
8bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
9bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *
10bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * Unless required by applicable law or agreed to in writing, software
11bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
12bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * See the License for the specific language governing permissions and
14bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * limitations under the License.
15bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette */
16bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
17bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverettepackage android.view;
18bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
19bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viveretteimport android.os.Handler;
20bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
2167e2ae86396c6d0f989285275cbf908dee5e71f7Aurimas Liutikasimport com.android.internal.util.GrowingArrayUtils;
22bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
23bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette/**
24bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * Class used to enqueue pending work from Views when no Handler is attached.
25bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *
26bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * @hide Exposed for test framework only.
27bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette */
28bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverettepublic class HandlerActionQueue {
29bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private HandlerAction[] mActions;
30bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private int mCount;
31bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
32bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void post(Runnable action) {
33bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        postDelayed(action, 0);
34bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
35bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
36bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void postDelayed(Runnable action, long delayMillis) {
37bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
38bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
39bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
40bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            if (mActions == null) {
41bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                mActions = new HandlerAction[4];
42bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
43bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
44bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount++;
45bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
46bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
47bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
48bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void removeCallbacks(Runnable action) {
49bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
50bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final int count = mCount;
51bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            int j = 0;
52bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
53bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final HandlerAction[] actions = mActions;
54bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (int i = 0; i < count; i++) {
55bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                if (actions[i].matches(action)) {
56bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // Remove this action by overwriting it within
57bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // this loop or nulling it out later.
58bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    continue;
59bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                }
60bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
61bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                if (j != i) {
62bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // At least one previous entry was removed, so
63bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // this one needs to move to the "new" list.
64bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    actions[j] = actions[i];
65bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                }
66bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
67bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                j++;
68bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
69bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
70bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            // The "new" list only has j entries.
71bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount = j;
72bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
73bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            // Null out any remaining entries.
74bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (; j < count; j++) {
75bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                actions[j] = null;
76bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
77bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
78bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
79bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
80bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void executeActions(Handler handler) {
81bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
82bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final HandlerAction[] actions = mActions;
83bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (int i = 0, count = mCount; i < count; i++) {
84bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                final HandlerAction handlerAction = actions[i];
85bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                handler.postDelayed(handlerAction.action, handlerAction.delay);
86bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
87bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
88bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mActions = null;
89bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount = 0;
90bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
91bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
92bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
93bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public int size() {
94bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mCount;
95bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
96bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
97bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public Runnable getRunnable(int index) {
98bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        if (index >= mCount) {
99bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            throw new IndexOutOfBoundsException();
100bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
101bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mActions[index].action;
102bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
103bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
104bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public long getDelay(int index) {
105bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        if (index >= mCount) {
106bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            throw new IndexOutOfBoundsException();
107bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
108bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mActions[index].delay;
109bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
110bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
111bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private static class HandlerAction {
112bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final Runnable action;
113bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final long delay;
114bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
115bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        public HandlerAction(Runnable action, long delay) {
116bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            this.action = action;
117bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            this.delay = delay;
118bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
119bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
120bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        public boolean matches(Runnable otherAction) {
121bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            return otherAction == null && action == null
122bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    || action != null && action.equals(otherAction);
123bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
124bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
125bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette}
126