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 com.android.internal.util.GrowingArrayUtils;
20bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
21bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viveretteimport android.os.Handler;
22bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
23bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viveretteimport java.util.ArrayList;
24bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
25bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette/**
26bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * Class used to enqueue pending work from Views when no Handler is attached.
27bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette *
28bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette * @hide Exposed for test framework only.
29bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette */
30bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverettepublic class HandlerActionQueue {
31bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private HandlerAction[] mActions;
32bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private int mCount;
33bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
34bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void post(Runnable action) {
35bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        postDelayed(action, 0);
36bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
37bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
38bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void postDelayed(Runnable action, long delayMillis) {
39bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
40bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
41bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
42bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            if (mActions == null) {
43bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                mActions = new HandlerAction[4];
44bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
45bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
46bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount++;
47bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
48bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
49bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
50bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void removeCallbacks(Runnable action) {
51bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
52bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final int count = mCount;
53bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            int j = 0;
54bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
55bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final HandlerAction[] actions = mActions;
56bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (int i = 0; i < count; i++) {
57bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                if (actions[i].matches(action)) {
58bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // Remove this action by overwriting it within
59bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // this loop or nulling it out later.
60bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    continue;
61bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                }
62bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
63bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                if (j != i) {
64bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // At least one previous entry was removed, so
65bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    // this one needs to move to the "new" list.
66bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    actions[j] = actions[i];
67bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                }
68bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
69bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                j++;
70bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
71bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
72bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            // The "new" list only has j entries.
73bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount = j;
74bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
75bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            // Null out any remaining entries.
76bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (; j < count; j++) {
77bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                actions[j] = null;
78bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
79bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
80bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
81bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
82bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public void executeActions(Handler handler) {
83bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        synchronized (this) {
84bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            final HandlerAction[] actions = mActions;
85bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            for (int i = 0, count = mCount; i < count; i++) {
86bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                final HandlerAction handlerAction = actions[i];
87bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                handler.postDelayed(handlerAction.action, handlerAction.delay);
88bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            }
89bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
90bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mActions = null;
91bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            mCount = 0;
92bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
93bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
94bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
95bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public int size() {
96bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mCount;
97bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
98bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
99bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public Runnable getRunnable(int index) {
100bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        if (index >= mCount) {
101bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            throw new IndexOutOfBoundsException();
102bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
103bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mActions[index].action;
104bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
105bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
106bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    public long getDelay(int index) {
107bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        if (index >= mCount) {
108bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            throw new IndexOutOfBoundsException();
109bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
110bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        return mActions[index].delay;
111bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
112bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
113bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    private static class HandlerAction {
114bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final Runnable action;
115bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        final long delay;
116bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
117bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        public HandlerAction(Runnable action, long delay) {
118bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            this.action = action;
119bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            this.delay = delay;
120bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
121bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette
122bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        public boolean matches(Runnable otherAction) {
123bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette            return otherAction == null && action == null
124bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette                    || action != null && action.equals(otherAction);
125bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette        }
126bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette    }
127bea0c7daa6611d8b96e1271f8854f500a87342fcAlan Viverette}
128