CommandQueue.java revision 665366a3055c7baa36242b8c92c5ff85b1c3394b
1/*
2 * Copyright (C) 2010 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
17package com.android.systemui.statusbar;
18
19import android.os.Handler;
20import android.os.IBinder;
21import android.os.Message;
22
23import com.android.internal.statusbar.IStatusBar;
24import com.android.internal.statusbar.StatusBarIcon;
25import com.android.internal.statusbar.StatusBarIconList;
26
27/**
28 * This class takes the functions from IStatusBar that come in on
29 * binder pool threads and posts messages to get them onto the main
30 * thread, and calls onto Callbacks.  It also takes care of
31 * coalescing these calls so they don't stack up.  For the calls
32 * are coalesced, note that they are all idempotent.
33 */
34public class CommandQueue extends IStatusBar.Stub {
35    private static final int INDEX_MASK = 0xffff;
36    private static final int MSG_SHIFT  = 16;
37    private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
38
39    private static final int OP_SET_ICON    = 1;
40    private static final int OP_REMOVE_ICON = 2;
41
42    private static final int MSG_ICON                       = 1 << MSG_SHIFT;
43    private static final int MSG_DISABLE                    = 2 << MSG_SHIFT;
44    private static final int MSG_EXPAND_NOTIFICATIONS       = 3 << MSG_SHIFT;
45    private static final int MSG_COLLAPSE_PANELS            = 4 << MSG_SHIFT;
46    private static final int MSG_EXPAND_SETTINGS            = 5 << MSG_SHIFT;
47    private static final int MSG_SET_SYSTEMUI_VISIBILITY    = 6 << MSG_SHIFT;
48    private static final int MSG_TOP_APP_WINDOW_CHANGED     = 7 << MSG_SHIFT;
49    private static final int MSG_SHOW_IME_BUTTON            = 8 << MSG_SHIFT;
50    private static final int MSG_TOGGLE_RECENT_APPS         = 9 << MSG_SHIFT;
51    private static final int MSG_PRELOAD_RECENT_APPS        = 10 << MSG_SHIFT;
52    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 11 << MSG_SHIFT;
53    private static final int MSG_SET_WINDOW_STATE           = 12 << MSG_SHIFT;
54    private static final int MSG_SHOW_RECENT_APPS           = 13 << MSG_SHIFT;
55    private static final int MSG_HIDE_RECENT_APPS           = 14 << MSG_SHIFT;
56    private static final int MSG_BUZZ_BEEP_BLINKED          = 15 << MSG_SHIFT;
57    private static final int MSG_NOTIFICATION_LIGHT_OFF     = 16 << MSG_SHIFT;
58    private static final int MSG_NOTIFICATION_LIGHT_PULSE   = 17 << MSG_SHIFT;
59
60    public static final int FLAG_EXCLUDE_NONE = 0;
61    public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
62    public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1;
63    public static final int FLAG_EXCLUDE_NOTIFICATION_PANEL = 1 << 2;
64    public static final int FLAG_EXCLUDE_INPUT_METHODS_PANEL = 1 << 3;
65    public static final int FLAG_EXCLUDE_COMPAT_MODE_PANEL = 1 << 4;
66
67    private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
68
69    private StatusBarIconList mList;
70    private Callbacks mCallbacks;
71    private Handler mHandler = new H();
72
73    /**
74     * These methods are called back on the main thread.
75     */
76    public interface Callbacks {
77        public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon);
78        public void updateIcon(String slot, int index, int viewIndex,
79                StatusBarIcon old, StatusBarIcon icon);
80        public void removeIcon(String slot, int index, int viewIndex);
81        public void disable(int state, boolean animate);
82        public void animateExpandNotificationsPanel();
83        public void animateCollapsePanels(int flags);
84        public void animateExpandSettingsPanel();
85        public void setSystemUiVisibility(int vis, int mask);
86        public void topAppWindowChanged(boolean visible);
87        public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
88                boolean showImeSwitcher);
89        public void showRecentApps(boolean triggeredFromAltTab);
90        public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
91        public void toggleRecentApps();
92        public void preloadRecentApps();
93        public void cancelPreloadRecentApps();
94        public void showSearchPanel();
95        public void hideSearchPanel();
96        public void setWindowState(int window, int state);
97        public void buzzBeepBlinked();
98        public void notificationLightOff();
99        public void notificationLightPulse(int argb, int onMillis, int offMillis);
100    }
101
102    public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
103        mCallbacks = callbacks;
104        mList = list;
105    }
106
107    public void setIcon(int index, StatusBarIcon icon) {
108        synchronized (mList) {
109            int what = MSG_ICON | index;
110            mHandler.removeMessages(what);
111            mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
112        }
113    }
114
115    public void removeIcon(int index) {
116        synchronized (mList) {
117            int what = MSG_ICON | index;
118            mHandler.removeMessages(what);
119            mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).sendToTarget();
120        }
121    }
122
123    public void disable(int state) {
124        synchronized (mList) {
125            mHandler.removeMessages(MSG_DISABLE);
126            mHandler.obtainMessage(MSG_DISABLE, state, 0, null).sendToTarget();
127        }
128    }
129
130    public void animateExpandNotificationsPanel() {
131        synchronized (mList) {
132            mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
133            mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
134        }
135    }
136
137    public void animateCollapsePanels() {
138        synchronized (mList) {
139            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
140            mHandler.sendEmptyMessage(MSG_COLLAPSE_PANELS);
141        }
142    }
143
144    public void animateExpandSettingsPanel() {
145        synchronized (mList) {
146            mHandler.removeMessages(MSG_EXPAND_SETTINGS);
147            mHandler.sendEmptyMessage(MSG_EXPAND_SETTINGS);
148        }
149    }
150
151    public void setSystemUiVisibility(int vis, int mask) {
152        synchronized (mList) {
153            mHandler.removeMessages(MSG_SET_SYSTEMUI_VISIBILITY);
154            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, mask, null).sendToTarget();
155        }
156    }
157
158    public void topAppWindowChanged(boolean menuVisible) {
159        synchronized (mList) {
160            mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED);
161            mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, menuVisible ? 1 : 0, 0,
162                    null).sendToTarget();
163        }
164    }
165
166    public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
167            boolean showImeSwitcher) {
168        synchronized (mList) {
169            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
170            Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, vis, backDisposition, token);
171            m.getData().putBoolean(SHOW_IME_SWITCHER_KEY, showImeSwitcher);
172            m.sendToTarget();
173        }
174    }
175
176    public void showRecentApps(boolean triggeredFromAltTab) {
177        synchronized (mList) {
178            mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
179            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS,
180                    triggeredFromAltTab ? 1 : 0, 0, null).sendToTarget();
181        }
182    }
183
184    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
185        synchronized (mList) {
186            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
187            mHandler.obtainMessage(MSG_HIDE_RECENT_APPS,
188                    triggeredFromAltTab ? 1 : 0, triggeredFromHomeKey ? 1 : 0,
189                    null).sendToTarget();
190        }
191    }
192
193    public void toggleRecentApps() {
194        synchronized (mList) {
195            mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
196            mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
197        }
198    }
199
200    public void preloadRecentApps() {
201        synchronized (mList) {
202            mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
203            mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
204        }
205    }
206
207    public void cancelPreloadRecentApps() {
208        synchronized (mList) {
209            mHandler.removeMessages(MSG_CANCEL_PRELOAD_RECENT_APPS);
210            mHandler.obtainMessage(MSG_CANCEL_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
211        }
212    }
213
214    public void setWindowState(int window, int state) {
215        synchronized (mList) {
216            // don't coalesce these
217            mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget();
218        }
219    }
220
221    public void buzzBeepBlinked() {
222        synchronized (mList) {
223            mHandler.removeMessages(MSG_BUZZ_BEEP_BLINKED);
224            mHandler.sendEmptyMessage(MSG_BUZZ_BEEP_BLINKED);
225        }
226    }
227
228    public void notificationLightOff() {
229        synchronized (mList) {
230            mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF);
231        }
232    }
233
234    public void notificationLightPulse(int argb, int onMillis, int offMillis) {
235        synchronized (mList) {
236            mHandler.obtainMessage(MSG_NOTIFICATION_LIGHT_PULSE, onMillis, offMillis, argb)
237                    .sendToTarget();
238        }
239    }
240
241    private final class H extends Handler {
242        public void handleMessage(Message msg) {
243            final int what = msg.what & MSG_MASK;
244            switch (what) {
245                case MSG_ICON: {
246                    final int index = msg.what & INDEX_MASK;
247                    final int viewIndex = mList.getViewIndex(index);
248                    switch (msg.arg1) {
249                        case OP_SET_ICON: {
250                            StatusBarIcon icon = (StatusBarIcon)msg.obj;
251                            StatusBarIcon old = mList.getIcon(index);
252                            if (old == null) {
253                                mList.setIcon(index, icon);
254                                mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
255                            } else {
256                                mList.setIcon(index, icon);
257                                mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
258                                        old, icon);
259                            }
260                            break;
261                        }
262                        case OP_REMOVE_ICON:
263                            if (mList.getIcon(index) != null) {
264                                mList.removeIcon(index);
265                                mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
266                            }
267                            break;
268                    }
269                    break;
270                }
271                case MSG_DISABLE:
272                    mCallbacks.disable(msg.arg1, true /* animate */);
273                    break;
274                case MSG_EXPAND_NOTIFICATIONS:
275                    mCallbacks.animateExpandNotificationsPanel();
276                    break;
277                case MSG_COLLAPSE_PANELS:
278                    mCallbacks.animateCollapsePanels(0);
279                    break;
280                case MSG_EXPAND_SETTINGS:
281                    mCallbacks.animateExpandSettingsPanel();
282                    break;
283                case MSG_SET_SYSTEMUI_VISIBILITY:
284                    mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);
285                    break;
286                case MSG_TOP_APP_WINDOW_CHANGED:
287                    mCallbacks.topAppWindowChanged(msg.arg1 != 0);
288                    break;
289                case MSG_SHOW_IME_BUTTON:
290                    mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
291                            msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
292                    break;
293                case MSG_SHOW_RECENT_APPS:
294                    mCallbacks.showRecentApps(msg.arg1 != 0);
295                    break;
296                case MSG_HIDE_RECENT_APPS:
297                    mCallbacks.hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
298                    break;
299                case MSG_TOGGLE_RECENT_APPS:
300                    mCallbacks.toggleRecentApps();
301                    break;
302                case MSG_PRELOAD_RECENT_APPS:
303                    mCallbacks.preloadRecentApps();
304                    break;
305                case MSG_CANCEL_PRELOAD_RECENT_APPS:
306                    mCallbacks.cancelPreloadRecentApps();
307                    break;
308                case MSG_SET_WINDOW_STATE:
309                    mCallbacks.setWindowState(msg.arg1, msg.arg2);
310                    break;
311                case MSG_BUZZ_BEEP_BLINKED:
312                    mCallbacks.buzzBeepBlinked();
313                    break;
314                case MSG_NOTIFICATION_LIGHT_OFF:
315                    mCallbacks.notificationLightOff();
316                    break;
317                case MSG_NOTIFICATION_LIGHT_PULSE:
318                    mCallbacks.notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
319                    break;
320            }
321        }
322    }
323}
324
325