CommandQueue.java revision 2992ea782fa61780d8e0de7a36a2a84622f8694b
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;
26import com.android.internal.statusbar.StatusBarNotification;
27
28/**
29 * This class takes the functions from IStatusBar that come in on
30 * binder pool threads and posts messages to get them onto the main
31 * thread, and calls onto Callbacks.  It also takes care of
32 * coalescing these calls so they don't stack up.  For the calls
33 * are coalesced, note that they are all idempotent.
34 */
35public class CommandQueue extends IStatusBar.Stub {
36    private static final String TAG = "StatusBar.CommandQueue";
37
38    private static final int MSG_MASK = 0xffff0000;
39    private static final int INDEX_MASK = 0x0000ffff;
40
41    private static final int MSG_ICON = 0x00010000;
42    private static final int OP_SET_ICON = 1;
43    private static final int OP_REMOVE_ICON = 2;
44
45    private static final int MSG_ADD_NOTIFICATION = 0x00020000;
46    private static final int MSG_UPDATE_NOTIFICATION = 0x00030000;
47    private static final int MSG_REMOVE_NOTIFICATION = 0x00040000;
48
49    private static final int MSG_DISABLE = 0x00050000;
50
51    private static final int MSG_SET_VISIBILITY = 0x00060000;
52    private static final int OP_EXPAND = 1;
53    private static final int OP_COLLAPSE = 2;
54
55    private static final int MSG_SET_LIGHTS_ON = 0x00070000;
56
57    private static final int MSG_SHOW_MENU = 0x00080000;
58    private static final int MSG_SHOW_IME_BUTTON = 0x00090000;
59    private static final int MSG_SET_HARD_KEYBOARD_STATUS = 0x000a0000;
60
61    private StatusBarIconList mList;
62    private Callbacks mCallbacks;
63    private Handler mHandler = new H();
64
65    private class NotificationQueueEntry {
66        IBinder key;
67        StatusBarNotification notification;
68    }
69
70    /**
71     * These methods are called back on the main thread.
72     */
73    public interface Callbacks {
74        public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon);
75        public void updateIcon(String slot, int index, int viewIndex,
76                StatusBarIcon old, StatusBarIcon icon);
77        public void removeIcon(String slot, int index, int viewIndex);
78        public void addNotification(IBinder key, StatusBarNotification notification);
79        public void updateNotification(IBinder key, StatusBarNotification notification);
80        public void removeNotification(IBinder key);
81        public void disable(int state);
82        public void animateExpand();
83        public void animateCollapse();
84        public void setLightsOn(boolean on);
85        public void setMenuKeyVisible(boolean visible);
86        public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
87        public void setHardKeyboardStatus(boolean available, boolean enabled);
88    }
89
90    public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
91        mCallbacks = callbacks;
92        mList = list;
93    }
94
95    public void setIcon(int index, StatusBarIcon icon) {
96        synchronized (mList) {
97            int what = MSG_ICON | index;
98            mHandler.removeMessages(what);
99            mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
100        }
101    }
102
103    public void removeIcon(int index) {
104        synchronized (mList) {
105            int what = MSG_ICON | index;
106            mHandler.removeMessages(what);
107            mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).sendToTarget();
108        }
109    }
110
111    public void addNotification(IBinder key, StatusBarNotification notification) {
112        synchronized (mList) {
113            NotificationQueueEntry ne = new NotificationQueueEntry();
114            ne.key = key;
115            ne.notification = notification;
116            mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, ne).sendToTarget();
117        }
118    }
119
120    public void updateNotification(IBinder key, StatusBarNotification notification) {
121        synchronized (mList) {
122            NotificationQueueEntry ne = new NotificationQueueEntry();
123            ne.key = key;
124            ne.notification = notification;
125            mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, ne).sendToTarget();
126        }
127    }
128
129    public void removeNotification(IBinder key) {
130        synchronized (mList) {
131            mHandler.obtainMessage(MSG_REMOVE_NOTIFICATION, 0, 0, key).sendToTarget();
132        }
133    }
134
135    public void disable(int state) {
136        synchronized (mList) {
137            mHandler.removeMessages(MSG_DISABLE);
138            mHandler.obtainMessage(MSG_DISABLE, state, 0, null).sendToTarget();
139        }
140    }
141
142    public void animateExpand() {
143        synchronized (mList) {
144            mHandler.removeMessages(MSG_SET_VISIBILITY);
145            mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_EXPAND, 0, null).sendToTarget();
146        }
147    }
148
149    public void animateCollapse() {
150        synchronized (mList) {
151            mHandler.removeMessages(MSG_SET_VISIBILITY);
152            mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_COLLAPSE, 0, null).sendToTarget();
153        }
154    }
155
156    public void setLightsOn(boolean on) {
157        synchronized (mList) {
158            mHandler.removeMessages(MSG_SET_LIGHTS_ON);
159            mHandler.obtainMessage(MSG_SET_LIGHTS_ON, on ? 1 : 0, 0, null).sendToTarget();
160        }
161    }
162
163    public void setMenuKeyVisible(boolean visible) {
164        synchronized (mList) {
165            mHandler.removeMessages(MSG_SHOW_MENU);
166            mHandler.obtainMessage(MSG_SHOW_MENU, visible ? 1 : 0, 0, null).sendToTarget();
167        }
168    }
169
170    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
171        synchronized (mList) {
172            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
173            mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, vis, backDisposition, token)
174                    .sendToTarget();
175        }
176    }
177
178    public void setHardKeyboardStatus(boolean available, boolean enabled) {
179        synchronized (mList) {
180            mHandler.removeMessages(MSG_SET_HARD_KEYBOARD_STATUS);
181            mHandler.obtainMessage(MSG_SET_HARD_KEYBOARD_STATUS,
182                    available ? 1 : 0, enabled ? 1 : 0).sendToTarget();
183        }
184    }
185
186    private final class H extends Handler {
187        public void handleMessage(Message msg) {
188            final int what = msg.what & MSG_MASK;
189            switch (what) {
190                case MSG_ICON: {
191                    final int index = msg.what & INDEX_MASK;
192                    final int viewIndex = mList.getViewIndex(index);
193                    switch (msg.arg1) {
194                        case OP_SET_ICON: {
195                            StatusBarIcon icon = (StatusBarIcon)msg.obj;
196                            StatusBarIcon old = mList.getIcon(index);
197                            if (old == null) {
198                                mList.setIcon(index, icon);
199                                mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
200                            } else {
201                                mList.setIcon(index, icon);
202                                mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
203                                        old, icon);
204                            }
205                            break;
206                        }
207                        case OP_REMOVE_ICON:
208                            if (mList.getIcon(index) != null) {
209                                mList.removeIcon(index);
210                                mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
211                            }
212                            break;
213                    }
214                    break;
215                }
216                case MSG_ADD_NOTIFICATION: {
217                    final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
218                    mCallbacks.addNotification(ne.key, ne.notification);
219                    break;
220                }
221                case MSG_UPDATE_NOTIFICATION: {
222                    final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
223                    mCallbacks.updateNotification(ne.key, ne.notification);
224                    break;
225                }
226                case MSG_REMOVE_NOTIFICATION: {
227                    mCallbacks.removeNotification((IBinder)msg.obj);
228                    break;
229                }
230                case MSG_DISABLE:
231                    mCallbacks.disable(msg.arg1);
232                    break;
233                case MSG_SET_VISIBILITY:
234                    if (msg.arg1 == OP_EXPAND) {
235                        mCallbacks.animateExpand();
236                    } else {
237                        mCallbacks.animateCollapse();
238                    }
239                    break;
240                case MSG_SET_LIGHTS_ON:
241                    mCallbacks.setLightsOn(msg.arg1 != 0);
242                    break;
243                case MSG_SHOW_MENU:
244                    mCallbacks.setMenuKeyVisible(msg.arg1 != 0);
245                    break;
246                case MSG_SHOW_IME_BUTTON:
247                    mCallbacks.setImeWindowStatus((IBinder)msg.obj, msg.arg1, msg.arg2);
248                    break;
249                case MSG_SET_HARD_KEYBOARD_STATUS:
250                    mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
251                    break;
252            }
253        }
254    }
255}
256
257