CommandQueue.java revision 6b46038e6a0e4c45cebe655f1c3bcf8986319853
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.Looper;
25import android.os.Message;
26import android.support.annotation.VisibleForTesting;
27import android.util.Pair;
28
29import com.android.internal.os.SomeArgs;
30import com.android.internal.statusbar.IStatusBar;
31import com.android.internal.statusbar.StatusBarIcon;
32import com.android.systemui.SystemUI;
33
34import java.util.ArrayList;
35
36/**
37 * This class takes the functions from IStatusBar that come in on
38 * binder pool threads and posts messages to get them onto the main
39 * thread, and calls onto Callbacks.  It also takes care of
40 * coalescing these calls so they don't stack up.  For the calls
41 * are coalesced, note that they are all idempotent.
42 */
43public class CommandQueue extends IStatusBar.Stub {
44    private static final int INDEX_MASK = 0xffff;
45    private static final int MSG_SHIFT  = 16;
46    private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
47
48    private static final int OP_SET_ICON    = 1;
49    private static final int OP_REMOVE_ICON = 2;
50
51    private static final int MSG_ICON                          = 1 << MSG_SHIFT;
52    private static final int MSG_DISABLE                       = 2 << MSG_SHIFT;
53    private static final int MSG_EXPAND_NOTIFICATIONS          = 3 << MSG_SHIFT;
54    private static final int MSG_COLLAPSE_PANELS               = 4 << MSG_SHIFT;
55    private static final int MSG_EXPAND_SETTINGS               = 5 << MSG_SHIFT;
56    private static final int MSG_SET_SYSTEMUI_VISIBILITY       = 6 << MSG_SHIFT;
57    private static final int MSG_TOP_APP_WINDOW_CHANGED        = 7 << MSG_SHIFT;
58    private static final int MSG_SHOW_IME_BUTTON               = 8 << MSG_SHIFT;
59    private static final int MSG_TOGGLE_RECENT_APPS            = 9 << MSG_SHIFT;
60    private static final int MSG_PRELOAD_RECENT_APPS           = 10 << MSG_SHIFT;
61    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS    = 11 << MSG_SHIFT;
62    private static final int MSG_SET_WINDOW_STATE              = 12 << MSG_SHIFT;
63    private static final int MSG_SHOW_RECENT_APPS              = 13 << MSG_SHIFT;
64    private static final int MSG_HIDE_RECENT_APPS              = 14 << MSG_SHIFT;
65    private static final int MSG_SHOW_SCREEN_PIN_REQUEST       = 18 << MSG_SHIFT;
66    private static final int MSG_APP_TRANSITION_PENDING        = 19 << MSG_SHIFT;
67    private static final int MSG_APP_TRANSITION_CANCELLED      = 20 << MSG_SHIFT;
68    private static final int MSG_APP_TRANSITION_STARTING       = 21 << MSG_SHIFT;
69    private static final int MSG_ASSIST_DISCLOSURE             = 22 << MSG_SHIFT;
70    private static final int MSG_START_ASSIST                  = 23 << MSG_SHIFT;
71    private static final int MSG_CAMERA_LAUNCH_GESTURE         = 24 << MSG_SHIFT;
72    private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS     = 25 << MSG_SHIFT;
73    private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU  = 26 << MSG_SHIFT;
74    private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
75    private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
76    private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
77    private static final int MSG_TOGGLE_APP_SPLIT_SCREEN       = 30 << MSG_SHIFT;
78    private static final int MSG_APP_TRANSITION_FINISHED       = 31 << MSG_SHIFT;
79    private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS    = 32 << MSG_SHIFT;
80    private static final int MSG_HANDLE_SYSNAV_KEY             = 33 << MSG_SHIFT;
81    private static final int MSG_SHOW_GLOBAL_ACTIONS           = 34 << MSG_SHIFT;
82
83    public static final int FLAG_EXCLUDE_NONE = 0;
84    public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
85    public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1;
86    public static final int FLAG_EXCLUDE_NOTIFICATION_PANEL = 1 << 2;
87    public static final int FLAG_EXCLUDE_INPUT_METHODS_PANEL = 1 << 3;
88    public static final int FLAG_EXCLUDE_COMPAT_MODE_PANEL = 1 << 4;
89
90    private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
91
92    private final Object mLock = new Object();
93    private ArrayList<Callbacks> mCallbacks = new ArrayList<>();
94    private Handler mHandler = new H(Looper.getMainLooper());
95    private int mDisable1;
96    private int mDisable2;
97
98    /**
99     * These methods are called back on the main thread.
100     */
101    public interface Callbacks {
102        default void setIcon(String slot, StatusBarIcon icon) { }
103        default void removeIcon(String slot) { }
104        default void disable(int state1, int state2, boolean animate) { }
105        default void animateExpandNotificationsPanel() { }
106        default void animateCollapsePanels(int flags) { }
107        default void animateExpandSettingsPanel(String obj) { }
108        default void setSystemUiVisibility(int vis, int fullscreenStackVis,
109                int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
110        }
111        default void topAppWindowChanged(boolean visible) { }
112        default void setImeWindowStatus(IBinder token, int vis, int backDisposition,
113                boolean showImeSwitcher) { }
114        default void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { }
115        default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
116        default void toggleRecentApps() { }
117        default void toggleSplitScreen() { }
118        default void preloadRecentApps() { }
119        default void dismissKeyboardShortcutsMenu() { }
120        default void toggleKeyboardShortcutsMenu(int deviceId) { }
121        default void cancelPreloadRecentApps() { }
122        default void setWindowState(int window, int state) { }
123        default void showScreenPinningRequest(int taskId) { }
124        default void appTransitionPending(boolean forced) { }
125        default void appTransitionCancelled() { }
126        default void appTransitionStarting(long startTime, long duration, boolean forced) { }
127        default void appTransitionFinished() { }
128        default void showAssistDisclosure() { }
129        default void startAssist(Bundle args) { }
130        default void onCameraLaunchGestureDetected(int source) { }
131        default void showPictureInPictureMenu() { }
132
133        default void addQsTile(ComponentName tile) { }
134        default void remQsTile(ComponentName tile) { }
135        default void clickTile(ComponentName tile) { }
136
137        default void handleSystemNavigationKey(int arg1) { }
138        default void handleShowGlobalActionsMenu() { }
139    }
140
141    @VisibleForTesting
142    protected CommandQueue() {
143    }
144
145    public void addCallbacks(Callbacks callbacks) {
146        mCallbacks.add(callbacks);
147        callbacks.disable(mDisable1, mDisable2, false /* animate */);
148    }
149
150    public void removeCallbacks(Callbacks callbacks) {
151        mCallbacks.remove(callbacks);
152    }
153
154    public void setIcon(String slot, StatusBarIcon icon) {
155        synchronized (mLock) {
156            // don't coalesce these
157            mHandler.obtainMessage(MSG_ICON, OP_SET_ICON, 0,
158                    new Pair<String, StatusBarIcon>(slot, icon)).sendToTarget();
159        }
160    }
161
162    public void removeIcon(String slot) {
163        synchronized (mLock) {
164            // don't coalesce these
165            mHandler.obtainMessage(MSG_ICON, OP_REMOVE_ICON, 0, slot).sendToTarget();
166        }
167    }
168
169    public void disable(int state1, int state2, boolean animate) {
170        synchronized (mLock) {
171            mDisable1 = state1;
172            mDisable2 = state2;
173            mHandler.removeMessages(MSG_DISABLE);
174            Message msg = mHandler.obtainMessage(MSG_DISABLE, state1, state2, animate);
175            if (Looper.myLooper() == mHandler.getLooper()) {
176                // If its the right looper execute immediately so hides can be handled quickly.
177                mHandler.handleMessage(msg);
178                msg.recycle();
179            } else {
180                msg.sendToTarget();
181            }
182        }
183    }
184
185    public void disable(int state1, int state2) {
186        disable(state1, state2, true);
187    }
188
189    public void recomputeDisableFlags(boolean animate) {
190        disable(mDisable1, mDisable2, animate);
191    }
192
193    public void animateExpandNotificationsPanel() {
194        synchronized (mLock) {
195            mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
196            mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
197        }
198    }
199
200    public void animateCollapsePanels() {
201        synchronized (mLock) {
202            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
203            mHandler.obtainMessage(MSG_COLLAPSE_PANELS, 0, 0).sendToTarget();
204        }
205    }
206
207    public void animateCollapsePanels(int flags) {
208        synchronized (mLock) {
209            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
210            mHandler.obtainMessage(MSG_COLLAPSE_PANELS, flags, 0).sendToTarget();
211        }
212    }
213
214    public void animateExpandSettingsPanel(String subPanel) {
215        synchronized (mLock) {
216            mHandler.removeMessages(MSG_EXPAND_SETTINGS);
217            mHandler.obtainMessage(MSG_EXPAND_SETTINGS, subPanel).sendToTarget();
218        }
219    }
220
221    public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
222            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
223        synchronized (mLock) {
224            // Don't coalesce these, since it might have one time flags set such as
225            // STATUS_BAR_UNHIDE which might get lost.
226            SomeArgs args = SomeArgs.obtain();
227            args.argi1 = vis;
228            args.argi2 = fullscreenStackVis;
229            args.argi3 = dockedStackVis;
230            args.argi4 = mask;
231            args.arg1 = fullscreenStackBounds;
232            args.arg2 = dockedStackBounds;
233            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
234        }
235    }
236
237    public void topAppWindowChanged(boolean menuVisible) {
238        synchronized (mLock) {
239            mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED);
240            mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, menuVisible ? 1 : 0, 0,
241                    null).sendToTarget();
242        }
243    }
244
245    public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
246            boolean showImeSwitcher) {
247        synchronized (mLock) {
248            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
249            Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, vis, backDisposition, token);
250            m.getData().putBoolean(SHOW_IME_SWITCHER_KEY, showImeSwitcher);
251            m.sendToTarget();
252        }
253    }
254
255    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
256        synchronized (mLock) {
257            mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
258            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS,
259                    triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0, null).sendToTarget();
260        }
261    }
262
263    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
264        synchronized (mLock) {
265            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
266            mHandler.obtainMessage(MSG_HIDE_RECENT_APPS,
267                    triggeredFromAltTab ? 1 : 0, triggeredFromHomeKey ? 1 : 0,
268                    null).sendToTarget();
269        }
270    }
271
272    public void toggleSplitScreen() {
273        synchronized (mLock) {
274            mHandler.removeMessages(MSG_TOGGLE_APP_SPLIT_SCREEN);
275            mHandler.obtainMessage(MSG_TOGGLE_APP_SPLIT_SCREEN, 0, 0, null).sendToTarget();
276        }
277    }
278
279    public void toggleRecentApps() {
280        synchronized (mLock) {
281            mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
282            Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null);
283            msg.setAsynchronous(true);
284            msg.sendToTarget();
285        }
286    }
287
288    public void preloadRecentApps() {
289        synchronized (mLock) {
290            mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
291            mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
292        }
293    }
294
295    public void cancelPreloadRecentApps() {
296        synchronized (mLock) {
297            mHandler.removeMessages(MSG_CANCEL_PRELOAD_RECENT_APPS);
298            mHandler.obtainMessage(MSG_CANCEL_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
299        }
300    }
301
302    @Override
303    public void dismissKeyboardShortcutsMenu() {
304        synchronized (mLock) {
305            mHandler.removeMessages(MSG_DISMISS_KEYBOARD_SHORTCUTS);
306            mHandler.obtainMessage(MSG_DISMISS_KEYBOARD_SHORTCUTS).sendToTarget();
307        }
308    }
309
310    @Override
311    public void toggleKeyboardShortcutsMenu(int deviceId) {
312        synchronized (mLock) {
313            mHandler.removeMessages(MSG_TOGGLE_KEYBOARD_SHORTCUTS);
314            mHandler.obtainMessage(MSG_TOGGLE_KEYBOARD_SHORTCUTS, deviceId, 0).sendToTarget();
315        }
316    }
317
318    @Override
319    public void showPictureInPictureMenu() {
320        synchronized (mLock) {
321            mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
322            mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU).sendToTarget();
323        }
324    }
325
326    public void setWindowState(int window, int state) {
327        synchronized (mLock) {
328            // don't coalesce these
329            mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget();
330        }
331    }
332
333    public void showScreenPinningRequest(int taskId) {
334        synchronized (mLock) {
335            mHandler.obtainMessage(MSG_SHOW_SCREEN_PIN_REQUEST, taskId, 0, null)
336                    .sendToTarget();
337        }
338    }
339
340    public void appTransitionPending() {
341        appTransitionPending(false /* forced */);
342    }
343
344    public void appTransitionPending(boolean forced) {
345        synchronized (mLock) {
346            mHandler.obtainMessage(MSG_APP_TRANSITION_PENDING, forced ? 1 : 0, 0).sendToTarget();
347        }
348    }
349
350    public void appTransitionCancelled() {
351        synchronized (mLock) {
352            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_CANCELLED);
353        }
354    }
355
356    public void appTransitionStarting(long startTime, long duration) {
357        appTransitionStarting(startTime, duration, false /* forced */);
358    }
359
360    public void appTransitionStarting(long startTime, long duration, boolean forced) {
361        synchronized (mLock) {
362            mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, forced ? 1 : 0, 0,
363                    Pair.create(startTime, duration)).sendToTarget();
364        }
365    }
366
367    @Override
368    public void appTransitionFinished() {
369        synchronized (mLock) {
370            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_FINISHED);
371        }
372    }
373
374    public void showAssistDisclosure() {
375        synchronized (mLock) {
376            mHandler.removeMessages(MSG_ASSIST_DISCLOSURE);
377            mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget();
378        }
379    }
380
381    public void startAssist(Bundle args) {
382        synchronized (mLock) {
383            mHandler.removeMessages(MSG_START_ASSIST);
384            mHandler.obtainMessage(MSG_START_ASSIST, args).sendToTarget();
385        }
386    }
387
388    @Override
389    public void onCameraLaunchGestureDetected(int source) {
390        synchronized (mLock) {
391            mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
392            mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
393        }
394    }
395
396    @Override
397    public void addQsTile(ComponentName tile) {
398        synchronized (mLock) {
399            mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
400        }
401    }
402
403    @Override
404    public void remQsTile(ComponentName tile) {
405        synchronized (mLock) {
406            mHandler.obtainMessage(MSG_REMOVE_QS_TILE, tile).sendToTarget();
407        }
408    }
409
410    @Override
411    public void clickQsTile(ComponentName tile) {
412        synchronized (mLock) {
413            mHandler.obtainMessage(MSG_CLICK_QS_TILE, tile).sendToTarget();
414        }
415    }
416
417    @Override
418    public void handleSystemNavigationKey(int key) {
419        synchronized (mLock) {
420            mHandler.obtainMessage(MSG_HANDLE_SYSNAV_KEY, key, 0).sendToTarget();
421        }
422    }
423
424    @Override
425    public void showGlobalActionsMenu() {
426        synchronized (mLock) {
427            mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
428            mHandler.obtainMessage(MSG_SHOW_GLOBAL_ACTIONS).sendToTarget();
429        }
430    }
431
432    private final class H extends Handler {
433        private H(Looper l) {
434            super(l);
435        }
436
437        public void handleMessage(Message msg) {
438            final int what = msg.what & MSG_MASK;
439            switch (what) {
440                case MSG_ICON: {
441                    switch (msg.arg1) {
442                        case OP_SET_ICON: {
443                            Pair<String, StatusBarIcon> p = (Pair<String, StatusBarIcon>) msg.obj;
444                            for (int i = 0; i < mCallbacks.size(); i++) {
445                                mCallbacks.get(i).setIcon(p.first, p.second);
446                            }
447                            break;
448                        }
449                        case OP_REMOVE_ICON:
450                            for (int i = 0; i < mCallbacks.size(); i++) {
451                                mCallbacks.get(i).removeIcon((String) msg.obj);
452                            }
453                            break;
454                    }
455                    break;
456                }
457                case MSG_DISABLE:
458                    for (int i = 0; i < mCallbacks.size(); i++) {
459                        mCallbacks.get(i).disable(msg.arg1, msg.arg2, (Boolean) msg.obj);
460                    }
461                    break;
462                case MSG_EXPAND_NOTIFICATIONS:
463                    for (int i = 0; i < mCallbacks.size(); i++) {
464                        mCallbacks.get(i).animateExpandNotificationsPanel();
465                    }
466                    break;
467                case MSG_COLLAPSE_PANELS:
468                    for (int i = 0; i < mCallbacks.size(); i++) {
469                        mCallbacks.get(i).animateCollapsePanels(msg.arg1);
470                    }
471                    break;
472                case MSG_EXPAND_SETTINGS:
473                    for (int i = 0; i < mCallbacks.size(); i++) {
474                        mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
475                    }
476                    break;
477                case MSG_SET_SYSTEMUI_VISIBILITY:
478                    SomeArgs args = (SomeArgs) msg.obj;
479                    for (int i = 0; i < mCallbacks.size(); i++) {
480                        mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
481                                args.argi4, (Rect) args.arg1, (Rect) args.arg2);
482                    }
483                    args.recycle();
484                    break;
485                case MSG_TOP_APP_WINDOW_CHANGED:
486                    for (int i = 0; i < mCallbacks.size(); i++) {
487                        mCallbacks.get(i).topAppWindowChanged(msg.arg1 != 0);
488                    }
489                    break;
490                case MSG_SHOW_IME_BUTTON:
491                    for (int i = 0; i < mCallbacks.size(); i++) {
492                        mCallbacks.get(i).setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
493                                msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
494                    }
495                    break;
496                case MSG_SHOW_RECENT_APPS:
497                    for (int i = 0; i < mCallbacks.size(); i++) {
498                        mCallbacks.get(i).showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
499                    }
500                    break;
501                case MSG_HIDE_RECENT_APPS:
502                    for (int i = 0; i < mCallbacks.size(); i++) {
503                        mCallbacks.get(i).hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
504                    }
505                    break;
506                case MSG_TOGGLE_RECENT_APPS:
507                    for (int i = 0; i < mCallbacks.size(); i++) {
508                        mCallbacks.get(i).toggleRecentApps();
509                    }
510                    break;
511                case MSG_PRELOAD_RECENT_APPS:
512                    for (int i = 0; i < mCallbacks.size(); i++) {
513                        mCallbacks.get(i).preloadRecentApps();
514                    }
515                    break;
516                case MSG_CANCEL_PRELOAD_RECENT_APPS:
517                    for (int i = 0; i < mCallbacks.size(); i++) {
518                        mCallbacks.get(i).cancelPreloadRecentApps();
519                    }
520                    break;
521                case MSG_DISMISS_KEYBOARD_SHORTCUTS:
522                    for (int i = 0; i < mCallbacks.size(); i++) {
523                        mCallbacks.get(i).dismissKeyboardShortcutsMenu();
524                    }
525                    break;
526                case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
527                    for (int i = 0; i < mCallbacks.size(); i++) {
528                        mCallbacks.get(i).toggleKeyboardShortcutsMenu(msg.arg1);
529                    }
530                    break;
531                case MSG_SET_WINDOW_STATE:
532                    for (int i = 0; i < mCallbacks.size(); i++) {
533                        mCallbacks.get(i).setWindowState(msg.arg1, msg.arg2);
534                    }
535                    break;
536                case MSG_SHOW_SCREEN_PIN_REQUEST:
537                    for (int i = 0; i < mCallbacks.size(); i++) {
538                        mCallbacks.get(i).showScreenPinningRequest(msg.arg1);
539                    }
540                    break;
541                case MSG_APP_TRANSITION_PENDING:
542                    for (int i = 0; i < mCallbacks.size(); i++) {
543                        mCallbacks.get(i).appTransitionPending(msg.arg1 != 0);
544                    }
545                    break;
546                case MSG_APP_TRANSITION_CANCELLED:
547                    for (int i = 0; i < mCallbacks.size(); i++) {
548                        mCallbacks.get(i).appTransitionCancelled();
549                    }
550                    break;
551                case MSG_APP_TRANSITION_STARTING:
552                    for (int i = 0; i < mCallbacks.size(); i++) {
553                        Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
554                        mCallbacks.get(i).appTransitionStarting(data.first, data.second,
555                                msg.arg1 != 0);
556                    }
557                    break;
558                case MSG_APP_TRANSITION_FINISHED:
559                    for (int i = 0; i < mCallbacks.size(); i++) {
560                        mCallbacks.get(i).appTransitionFinished();
561                    }
562                    break;
563                case MSG_ASSIST_DISCLOSURE:
564                    for (int i = 0; i < mCallbacks.size(); i++) {
565                        mCallbacks.get(i).showAssistDisclosure();
566                    }
567                    break;
568                case MSG_START_ASSIST:
569                    for (int i = 0; i < mCallbacks.size(); i++) {
570                        mCallbacks.get(i).startAssist((Bundle) msg.obj);
571                    }
572                    break;
573                case MSG_CAMERA_LAUNCH_GESTURE:
574                    for (int i = 0; i < mCallbacks.size(); i++) {
575                        mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1);
576                    }
577                    break;
578                case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
579                    for (int i = 0; i < mCallbacks.size(); i++) {
580                        mCallbacks.get(i).showPictureInPictureMenu();
581                    }
582                    break;
583                case MSG_ADD_QS_TILE:
584                    for (int i = 0; i < mCallbacks.size(); i++) {
585                        mCallbacks.get(i).addQsTile((ComponentName) msg.obj);
586                    }
587                    break;
588                case MSG_REMOVE_QS_TILE:
589                    for (int i = 0; i < mCallbacks.size(); i++) {
590                        mCallbacks.get(i).remQsTile((ComponentName) msg.obj);
591                    }
592                    break;
593                case MSG_CLICK_QS_TILE:
594                    for (int i = 0; i < mCallbacks.size(); i++) {
595                        mCallbacks.get(i).clickTile((ComponentName) msg.obj);
596                    }
597                    break;
598                case MSG_TOGGLE_APP_SPLIT_SCREEN:
599                    for (int i = 0; i < mCallbacks.size(); i++) {
600                        mCallbacks.get(i).toggleSplitScreen();
601                    }
602                    break;
603                case MSG_HANDLE_SYSNAV_KEY:
604                    for (int i = 0; i < mCallbacks.size(); i++) {
605                        mCallbacks.get(i).handleSystemNavigationKey(msg.arg1);
606                    }
607                    break;
608                case MSG_SHOW_GLOBAL_ACTIONS:
609                    for (int i = 0; i < mCallbacks.size(); i++) {
610                        mCallbacks.get(i).handleShowGlobalActionsMenu();
611                    }
612                    break;
613            }
614        }
615    }
616
617    // Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
618    // is needed so it can extend SystemUI.
619    public static class CommandQueueStart extends SystemUI {
620        @Override
621        public void start() {
622            putComponent(CommandQueue.class, new CommandQueue());
623        }
624    }
625}
626
627