CommandQueue.java revision 4e850ffaa757cd6f1e2578c454a7a83a93419e83
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.content.ComponentName;
20import android.graphics.Rect;
21import android.os.Bundle;
22import android.os.Handler;
23import android.os.IBinder;
24import android.os.Message;
25import android.util.Pair;
26
27import com.android.internal.os.SomeArgs;
28import com.android.internal.statusbar.IStatusBar;
29import com.android.internal.statusbar.StatusBarIcon;
30
31/**
32 * This class takes the functions from IStatusBar that come in on
33 * binder pool threads and posts messages to get them onto the main
34 * thread, and calls onto Callbacks.  It also takes care of
35 * coalescing these calls so they don't stack up.  For the calls
36 * are coalesced, note that they are all idempotent.
37 */
38public class CommandQueue extends IStatusBar.Stub {
39    private static final int INDEX_MASK = 0xffff;
40    private static final int MSG_SHIFT  = 16;
41    private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
42
43    private static final int OP_SET_ICON    = 1;
44    private static final int OP_REMOVE_ICON = 2;
45
46    private static final int MSG_ICON                          = 1 << MSG_SHIFT;
47    private static final int MSG_DISABLE                       = 2 << MSG_SHIFT;
48    private static final int MSG_EXPAND_NOTIFICATIONS          = 3 << MSG_SHIFT;
49    private static final int MSG_COLLAPSE_PANELS               = 4 << MSG_SHIFT;
50    private static final int MSG_EXPAND_SETTINGS               = 5 << MSG_SHIFT;
51    private static final int MSG_SET_SYSTEMUI_VISIBILITY       = 6 << MSG_SHIFT;
52    private static final int MSG_TOP_APP_WINDOW_CHANGED        = 7 << MSG_SHIFT;
53    private static final int MSG_SHOW_IME_BUTTON               = 8 << MSG_SHIFT;
54    private static final int MSG_TOGGLE_RECENT_APPS            = 9 << MSG_SHIFT;
55    private static final int MSG_PRELOAD_RECENT_APPS           = 10 << MSG_SHIFT;
56    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS    = 11 << MSG_SHIFT;
57    private static final int MSG_SET_WINDOW_STATE              = 12 << MSG_SHIFT;
58    private static final int MSG_SHOW_RECENT_APPS              = 13 << MSG_SHIFT;
59    private static final int MSG_HIDE_RECENT_APPS              = 14 << MSG_SHIFT;
60    private static final int MSG_BUZZ_BEEP_BLINKED             = 15 << MSG_SHIFT;
61    private static final int MSG_NOTIFICATION_LIGHT_OFF        = 16 << MSG_SHIFT;
62    private static final int MSG_NOTIFICATION_LIGHT_PULSE      = 17 << MSG_SHIFT;
63    private static final int MSG_SHOW_SCREEN_PIN_REQUEST       = 18 << MSG_SHIFT;
64    private static final int MSG_APP_TRANSITION_PENDING        = 19 << MSG_SHIFT;
65    private static final int MSG_APP_TRANSITION_CANCELLED      = 20 << MSG_SHIFT;
66    private static final int MSG_APP_TRANSITION_STARTING       = 21 << MSG_SHIFT;
67    private static final int MSG_ASSIST_DISCLOSURE             = 22 << MSG_SHIFT;
68    private static final int MSG_START_ASSIST                  = 23 << MSG_SHIFT;
69    private static final int MSG_CAMERA_LAUNCH_GESTURE         = 24 << MSG_SHIFT;
70    private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS     = 25 << MSG_SHIFT;
71    private static final int MSG_REQUEST_TV_PICTURE_IN_PICTURE = 26 << MSG_SHIFT;
72    private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
73    private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
74    private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
75    private static final int MSG_TOGGLE_APP_SPLIT_SCREEN       = 30 << MSG_SHIFT;
76
77    public static final int FLAG_EXCLUDE_NONE = 0;
78    public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
79    public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1;
80    public static final int FLAG_EXCLUDE_NOTIFICATION_PANEL = 1 << 2;
81    public static final int FLAG_EXCLUDE_INPUT_METHODS_PANEL = 1 << 3;
82    public static final int FLAG_EXCLUDE_COMPAT_MODE_PANEL = 1 << 4;
83
84    private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
85
86    private final Object mLock = new Object();
87    private Callbacks mCallbacks;
88    private Handler mHandler = new H();
89
90    /**
91     * These methods are called back on the main thread.
92     */
93    public interface Callbacks {
94        public void setIcon(String slot, StatusBarIcon icon);
95        public void removeIcon(String slot);
96        public void disable(int state1, int state2, boolean animate);
97        public void animateExpandNotificationsPanel();
98        public void animateCollapsePanels(int flags);
99        public void animateExpandSettingsPanel(String obj);
100        public void setSystemUiVisibility(int vis, int fullscreenStackVis,
101                int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds);
102        public void topAppWindowChanged(boolean visible);
103        public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
104                boolean showImeSwitcher);
105        public void showRecentApps(boolean triggeredFromAltTab);
106        public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
107        public void toggleRecentApps();
108        public void toggleSplitScreen();
109        public void preloadRecentApps();
110        public void toggleKeyboardShortcutsMenu(int deviceId);
111        public void cancelPreloadRecentApps();
112        public void setWindowState(int window, int state);
113        public void buzzBeepBlinked();
114        public void notificationLightOff();
115        public void notificationLightPulse(int argb, int onMillis, int offMillis);
116        public void showScreenPinningRequest();
117        public void appTransitionPending();
118        public void appTransitionCancelled();
119        public void appTransitionStarting(long startTime, long duration);
120        public void showAssistDisclosure();
121        public void startAssist(Bundle args);
122        public void onCameraLaunchGestureDetected(int source);
123        public void requestTvPictureInPicture();
124
125        void addQsTile(ComponentName tile);
126        void remQsTile(ComponentName tile);
127        void clickTile(ComponentName tile);
128    }
129
130    public CommandQueue(Callbacks callbacks) {
131        mCallbacks = callbacks;
132    }
133
134    public void setIcon(String slot, StatusBarIcon icon) {
135        synchronized (mLock) {
136            // don't coalesce these
137            mHandler.obtainMessage(MSG_ICON, OP_SET_ICON, 0,
138                    new Pair<String, StatusBarIcon>(slot, icon)).sendToTarget();
139        }
140    }
141
142    public void removeIcon(String slot) {
143        synchronized (mLock) {
144            // don't coalesce these
145            mHandler.obtainMessage(MSG_ICON, OP_REMOVE_ICON, 0, slot).sendToTarget();
146        }
147    }
148
149    public void disable(int state1, int state2) {
150        synchronized (mLock) {
151            mHandler.removeMessages(MSG_DISABLE);
152            mHandler.obtainMessage(MSG_DISABLE, state1, state2, null).sendToTarget();
153        }
154    }
155
156    public void animateExpandNotificationsPanel() {
157        synchronized (mLock) {
158            mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
159            mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
160        }
161    }
162
163    public void animateCollapsePanels() {
164        synchronized (mLock) {
165            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
166            mHandler.sendEmptyMessage(MSG_COLLAPSE_PANELS);
167        }
168    }
169
170    public void animateExpandSettingsPanel(String subPanel) {
171        synchronized (mLock) {
172            mHandler.removeMessages(MSG_EXPAND_SETTINGS);
173            mHandler.obtainMessage(MSG_EXPAND_SETTINGS, subPanel).sendToTarget();
174        }
175    }
176
177    public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
178            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
179        synchronized (mLock) {
180            // Don't coalesce these, since it might have one time flags set such as
181            // STATUS_BAR_UNHIDE which might get lost.
182            SomeArgs args = SomeArgs.obtain();
183            args.argi1 = vis;
184            args.argi2 = fullscreenStackVis;
185            args.argi3 = dockedStackVis;
186            args.argi4 = mask;
187            args.arg1 = fullscreenStackBounds;
188            args.arg2 = dockedStackBounds;
189            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
190        }
191    }
192
193    public void topAppWindowChanged(boolean menuVisible) {
194        synchronized (mLock) {
195            mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED);
196            mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, menuVisible ? 1 : 0, 0,
197                    null).sendToTarget();
198        }
199    }
200
201    public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
202            boolean showImeSwitcher) {
203        synchronized (mLock) {
204            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
205            Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, vis, backDisposition, token);
206            m.getData().putBoolean(SHOW_IME_SWITCHER_KEY, showImeSwitcher);
207            m.sendToTarget();
208        }
209    }
210
211    public void showRecentApps(boolean triggeredFromAltTab) {
212        synchronized (mLock) {
213            mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
214            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS,
215                    triggeredFromAltTab ? 1 : 0, 0, null).sendToTarget();
216        }
217    }
218
219    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
220        synchronized (mLock) {
221            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
222            mHandler.obtainMessage(MSG_HIDE_RECENT_APPS,
223                    triggeredFromAltTab ? 1 : 0, triggeredFromHomeKey ? 1 : 0,
224                    null).sendToTarget();
225        }
226    }
227
228    public void toggleSplitScreen() {
229        synchronized (mLock) {
230            mHandler.removeMessages(MSG_TOGGLE_APP_SPLIT_SCREEN);
231            mHandler.obtainMessage(MSG_TOGGLE_APP_SPLIT_SCREEN, 0, 0, null).sendToTarget();
232        }
233    }
234
235    public void toggleRecentApps() {
236        synchronized (mLock) {
237            mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
238            mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
239        }
240    }
241
242    public void preloadRecentApps() {
243        synchronized (mLock) {
244            mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
245            mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
246        }
247    }
248
249    public void cancelPreloadRecentApps() {
250        synchronized (mLock) {
251            mHandler.removeMessages(MSG_CANCEL_PRELOAD_RECENT_APPS);
252            mHandler.obtainMessage(MSG_CANCEL_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
253        }
254    }
255
256    @Override
257    public void toggleKeyboardShortcutsMenu(int deviceId) {
258        synchronized (mLock) {
259            mHandler.removeMessages(MSG_TOGGLE_KEYBOARD_SHORTCUTS);
260            mHandler.obtainMessage(MSG_TOGGLE_KEYBOARD_SHORTCUTS, deviceId, 0).sendToTarget();
261        }
262    }
263
264    @Override
265    public void requestTvPictureInPicture() {
266        synchronized (mLock) {
267            mHandler.removeMessages(MSG_REQUEST_TV_PICTURE_IN_PICTURE);
268            mHandler.obtainMessage(MSG_REQUEST_TV_PICTURE_IN_PICTURE).sendToTarget();
269        }
270    }
271
272    public void setWindowState(int window, int state) {
273        synchronized (mLock) {
274            // don't coalesce these
275            mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget();
276        }
277    }
278
279    public void buzzBeepBlinked() {
280        synchronized (mLock) {
281            mHandler.removeMessages(MSG_BUZZ_BEEP_BLINKED);
282            mHandler.sendEmptyMessage(MSG_BUZZ_BEEP_BLINKED);
283        }
284    }
285
286    public void notificationLightOff() {
287        synchronized (mLock) {
288            mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF);
289        }
290    }
291
292    public void notificationLightPulse(int argb, int onMillis, int offMillis) {
293        synchronized (mLock) {
294            mHandler.obtainMessage(MSG_NOTIFICATION_LIGHT_PULSE, onMillis, offMillis, argb)
295                    .sendToTarget();
296        }
297    }
298
299    public void showScreenPinningRequest() {
300        synchronized (mLock) {
301            mHandler.sendEmptyMessage(MSG_SHOW_SCREEN_PIN_REQUEST);
302        }
303    }
304
305    public void appTransitionPending() {
306        synchronized (mLock) {
307            mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
308            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
309        }
310    }
311
312    public void appTransitionCancelled() {
313        synchronized (mLock) {
314            mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
315            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
316        }
317    }
318
319    public void appTransitionStarting(long startTime, long duration) {
320        synchronized (mLock) {
321            mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
322            mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration))
323                    .sendToTarget();
324        }
325    }
326
327    public void showAssistDisclosure() {
328        synchronized (mLock) {
329            mHandler.removeMessages(MSG_ASSIST_DISCLOSURE);
330            mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget();
331        }
332    }
333
334    public void startAssist(Bundle args) {
335        synchronized (mLock) {
336            mHandler.removeMessages(MSG_START_ASSIST);
337            mHandler.obtainMessage(MSG_START_ASSIST, args).sendToTarget();
338        }
339    }
340
341    @Override
342    public void onCameraLaunchGestureDetected(int source) {
343        synchronized (mLock) {
344            mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
345            mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
346        }
347    }
348
349    @Override
350    public void addQsTile(ComponentName tile) {
351        synchronized (mLock) {
352            mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
353        }
354    }
355
356    @Override
357    public void remQsTile(ComponentName tile) {
358        synchronized (mLock) {
359            mHandler.obtainMessage(MSG_REMOVE_QS_TILE, tile).sendToTarget();
360        }
361    }
362
363    @Override
364    public void clickQsTile(ComponentName tile) {
365        synchronized (mLock) {
366            mHandler.obtainMessage(MSG_CLICK_QS_TILE, tile).sendToTarget();
367        }
368    }
369
370    private final class H extends Handler {
371        public void handleMessage(Message msg) {
372            final int what = msg.what & MSG_MASK;
373            switch (what) {
374                case MSG_ICON: {
375                    switch (msg.arg1) {
376                        case OP_SET_ICON: {
377                            Pair<String, StatusBarIcon> p = (Pair<String, StatusBarIcon>) msg.obj;
378                            mCallbacks.setIcon(p.first, p.second);
379                            break;
380                        }
381                        case OP_REMOVE_ICON:
382                            mCallbacks.removeIcon((String) msg.obj);
383                            break;
384                    }
385                    break;
386                }
387                case MSG_DISABLE:
388                    mCallbacks.disable(msg.arg1, msg.arg2, true /* animate */);
389                    break;
390                case MSG_EXPAND_NOTIFICATIONS:
391                    mCallbacks.animateExpandNotificationsPanel();
392                    break;
393                case MSG_COLLAPSE_PANELS:
394                    mCallbacks.animateCollapsePanels(0);
395                    break;
396                case MSG_EXPAND_SETTINGS:
397                    mCallbacks.animateExpandSettingsPanel((String) msg.obj);
398                    break;
399                case MSG_SET_SYSTEMUI_VISIBILITY:
400                    SomeArgs args = (SomeArgs) msg.obj;
401                    mCallbacks.setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
402                            args.argi4, (Rect) args.arg1, (Rect) args.arg2);
403                    args.recycle();
404                    break;
405                case MSG_TOP_APP_WINDOW_CHANGED:
406                    mCallbacks.topAppWindowChanged(msg.arg1 != 0);
407                    break;
408                case MSG_SHOW_IME_BUTTON:
409                    mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
410                            msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
411                    break;
412                case MSG_SHOW_RECENT_APPS:
413                    mCallbacks.showRecentApps(msg.arg1 != 0);
414                    break;
415                case MSG_HIDE_RECENT_APPS:
416                    mCallbacks.hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
417                    break;
418                case MSG_TOGGLE_RECENT_APPS:
419                    mCallbacks.toggleRecentApps();
420                    break;
421                case MSG_PRELOAD_RECENT_APPS:
422                    mCallbacks.preloadRecentApps();
423                    break;
424                case MSG_CANCEL_PRELOAD_RECENT_APPS:
425                    mCallbacks.cancelPreloadRecentApps();
426                    break;
427                case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
428                    mCallbacks.toggleKeyboardShortcutsMenu(msg.arg1);
429                    break;
430                case MSG_SET_WINDOW_STATE:
431                    mCallbacks.setWindowState(msg.arg1, msg.arg2);
432                    break;
433                case MSG_BUZZ_BEEP_BLINKED:
434                    mCallbacks.buzzBeepBlinked();
435                    break;
436                case MSG_NOTIFICATION_LIGHT_OFF:
437                    mCallbacks.notificationLightOff();
438                    break;
439                case MSG_NOTIFICATION_LIGHT_PULSE:
440                    mCallbacks.notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
441                    break;
442                case MSG_SHOW_SCREEN_PIN_REQUEST:
443                    mCallbacks.showScreenPinningRequest();
444                    break;
445                case MSG_APP_TRANSITION_PENDING:
446                    mCallbacks.appTransitionPending();
447                    break;
448                case MSG_APP_TRANSITION_CANCELLED:
449                    mCallbacks.appTransitionCancelled();
450                    break;
451                case MSG_APP_TRANSITION_STARTING:
452                    Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
453                    mCallbacks.appTransitionStarting(data.first, data.second);
454                    break;
455                case MSG_ASSIST_DISCLOSURE:
456                    mCallbacks.showAssistDisclosure();
457                    break;
458                case MSG_START_ASSIST:
459                    mCallbacks.startAssist((Bundle) msg.obj);
460                    break;
461                case MSG_CAMERA_LAUNCH_GESTURE:
462                    mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
463                    break;
464                case MSG_REQUEST_TV_PICTURE_IN_PICTURE:
465                    mCallbacks.requestTvPictureInPicture();
466                    break;
467                case MSG_ADD_QS_TILE:
468                    mCallbacks.addQsTile((ComponentName) msg.obj);
469                    break;
470                case MSG_REMOVE_QS_TILE:
471                    mCallbacks.remQsTile((ComponentName) msg.obj);
472                    break;
473                case MSG_CLICK_QS_TILE:
474                    mCallbacks.clickTile((ComponentName) msg.obj);
475                    break;
476                case MSG_TOGGLE_APP_SPLIT_SCREEN:
477                    mCallbacks.toggleSplitScreen();
478                    break;
479            }
480        }
481    }
482}
483
484