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.hardware.biometrics.IBiometricPromptReceiver;
22import android.os.Bundle;
23import android.os.Handler;
24import android.os.IBinder;
25import android.os.Looper;
26import android.os.Message;
27import android.os.RemoteException;
28import android.support.annotation.VisibleForTesting;
29import android.util.Pair;
30
31import com.android.internal.os.SomeArgs;
32import com.android.internal.statusbar.IStatusBar;
33import com.android.internal.statusbar.StatusBarIcon;
34import com.android.systemui.SystemUI;
35
36import java.util.ArrayList;
37
38/**
39 * This class takes the functions from IStatusBar that come in on
40 * binder pool threads and posts messages to get them onto the main
41 * thread, and calls onto Callbacks.  It also takes care of
42 * coalescing these calls so they don't stack up.  For the calls
43 * are coalesced, note that they are all idempotent.
44 */
45public class CommandQueue extends IStatusBar.Stub {
46    private static final int INDEX_MASK = 0xffff;
47    private static final int MSG_SHIFT  = 16;
48    private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
49
50    private static final int OP_SET_ICON    = 1;
51    private static final int OP_REMOVE_ICON = 2;
52
53    private static final int MSG_ICON                          = 1 << MSG_SHIFT;
54    private static final int MSG_DISABLE                       = 2 << MSG_SHIFT;
55    private static final int MSG_EXPAND_NOTIFICATIONS          = 3 << MSG_SHIFT;
56    private static final int MSG_COLLAPSE_PANELS               = 4 << MSG_SHIFT;
57    private static final int MSG_EXPAND_SETTINGS               = 5 << MSG_SHIFT;
58    private static final int MSG_SET_SYSTEMUI_VISIBILITY       = 6 << MSG_SHIFT;
59    private static final int MSG_TOP_APP_WINDOW_CHANGED        = 7 << MSG_SHIFT;
60    private static final int MSG_SHOW_IME_BUTTON               = 8 << MSG_SHIFT;
61    private static final int MSG_TOGGLE_RECENT_APPS            = 9 << MSG_SHIFT;
62    private static final int MSG_PRELOAD_RECENT_APPS           = 10 << MSG_SHIFT;
63    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS    = 11 << MSG_SHIFT;
64    private static final int MSG_SET_WINDOW_STATE              = 12 << MSG_SHIFT;
65    private static final int MSG_SHOW_RECENT_APPS              = 13 << MSG_SHIFT;
66    private static final int MSG_HIDE_RECENT_APPS              = 14 << MSG_SHIFT;
67    private static final int MSG_SHOW_SCREEN_PIN_REQUEST       = 18 << MSG_SHIFT;
68    private static final int MSG_APP_TRANSITION_PENDING        = 19 << MSG_SHIFT;
69    private static final int MSG_APP_TRANSITION_CANCELLED      = 20 << MSG_SHIFT;
70    private static final int MSG_APP_TRANSITION_STARTING       = 21 << MSG_SHIFT;
71    private static final int MSG_ASSIST_DISCLOSURE             = 22 << MSG_SHIFT;
72    private static final int MSG_START_ASSIST                  = 23 << MSG_SHIFT;
73    private static final int MSG_CAMERA_LAUNCH_GESTURE         = 24 << MSG_SHIFT;
74    private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS     = 25 << MSG_SHIFT;
75    private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU  = 26 << MSG_SHIFT;
76    private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
77    private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
78    private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
79    private static final int MSG_TOGGLE_APP_SPLIT_SCREEN       = 30 << MSG_SHIFT;
80    private static final int MSG_APP_TRANSITION_FINISHED       = 31 << MSG_SHIFT;
81    private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS    = 32 << MSG_SHIFT;
82    private static final int MSG_HANDLE_SYSTEM_KEY             = 33 << MSG_SHIFT;
83    private static final int MSG_SHOW_GLOBAL_ACTIONS           = 34 << MSG_SHIFT;
84    private static final int MSG_TOGGLE_PANEL                  = 35 << MSG_SHIFT;
85    private static final int MSG_SHOW_SHUTDOWN_UI              = 36 << MSG_SHIFT;
86    private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR  = 37 << MSG_SHIFT;
87    private static final int MSG_ROTATION_PROPOSAL             = 38 << MSG_SHIFT;
88    private static final int MSG_FINGERPRINT_SHOW              = 39 << MSG_SHIFT;
89    private static final int MSG_FINGERPRINT_AUTHENTICATED     = 40 << MSG_SHIFT;
90    private static final int MSG_FINGERPRINT_HELP              = 41 << MSG_SHIFT;
91    private static final int MSG_FINGERPRINT_ERROR             = 42 << MSG_SHIFT;
92    private static final int MSG_FINGERPRINT_HIDE              = 43 << MSG_SHIFT;
93    private static final int MSG_SHOW_CHARGING_ANIMATION       = 44 << MSG_SHIFT;
94    private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
95    private static final int MSG_SHOW_PINNING_TOAST_ESCAPE     = 46 << MSG_SHIFT;
96
97    public static final int FLAG_EXCLUDE_NONE = 0;
98    public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
99    public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1;
100    public static final int FLAG_EXCLUDE_NOTIFICATION_PANEL = 1 << 2;
101    public static final int FLAG_EXCLUDE_INPUT_METHODS_PANEL = 1 << 3;
102    public static final int FLAG_EXCLUDE_COMPAT_MODE_PANEL = 1 << 4;
103
104    private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
105
106    private final Object mLock = new Object();
107    private ArrayList<Callbacks> mCallbacks = new ArrayList<>();
108    private Handler mHandler = new H(Looper.getMainLooper());
109    private int mDisable1;
110    private int mDisable2;
111
112    /**
113     * These methods are called back on the main thread.
114     */
115    public interface Callbacks {
116        default void setIcon(String slot, StatusBarIcon icon) { }
117        default void removeIcon(String slot) { }
118        default void disable(int state1, int state2, boolean animate) { }
119        default void animateExpandNotificationsPanel() { }
120        default void animateCollapsePanels(int flags) { }
121        default void togglePanel() { }
122        default void animateExpandSettingsPanel(String obj) { }
123        default void setSystemUiVisibility(int vis, int fullscreenStackVis,
124                int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
125        }
126        default void topAppWindowChanged(boolean visible) { }
127        default void setImeWindowStatus(IBinder token, int vis, int backDisposition,
128                boolean showImeSwitcher) { }
129        default void showRecentApps(boolean triggeredFromAltTab) { }
130        default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
131        default void toggleRecentApps() { }
132        default void toggleSplitScreen() { }
133        default void preloadRecentApps() { }
134        default void dismissKeyboardShortcutsMenu() { }
135        default void toggleKeyboardShortcutsMenu(int deviceId) { }
136        default void cancelPreloadRecentApps() { }
137        default void setWindowState(int window, int state) { }
138        default void showScreenPinningRequest(int taskId) { }
139        default void appTransitionPending(boolean forced) { }
140        default void appTransitionCancelled() { }
141        default void appTransitionStarting(long startTime, long duration, boolean forced) { }
142        default void appTransitionFinished() { }
143        default void showAssistDisclosure() { }
144        default void startAssist(Bundle args) { }
145        default void onCameraLaunchGestureDetected(int source) { }
146        default void showPictureInPictureMenu() { }
147        default void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { }
148
149        default void addQsTile(ComponentName tile) { }
150        default void remQsTile(ComponentName tile) { }
151        default void clickTile(ComponentName tile) { }
152
153        default void handleSystemKey(int arg1) { }
154        default void showPinningEnterExitToast(boolean entering) { }
155        default void showPinningEscapeToast() { }
156        default void handleShowGlobalActionsMenu() { }
157        default void handleShowShutdownUi(boolean isReboot, String reason) { }
158
159        default void showWirelessChargingAnimation(int batteryLevel) {  }
160
161        default void onRotationProposal(int rotation, boolean isValid) { }
162
163        default void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
164        default void onFingerprintAuthenticated() { }
165        default void onFingerprintHelp(String message) { }
166        default void onFingerprintError(String error) { }
167        default void hideFingerprintDialog() { }
168    }
169
170    @VisibleForTesting
171    protected CommandQueue() {
172    }
173
174    public void addCallbacks(Callbacks callbacks) {
175        mCallbacks.add(callbacks);
176        callbacks.disable(mDisable1, mDisable2, false /* animate */);
177    }
178
179    public void removeCallbacks(Callbacks callbacks) {
180        mCallbacks.remove(callbacks);
181    }
182
183    public void setIcon(String slot, StatusBarIcon icon) {
184        synchronized (mLock) {
185            // don't coalesce these
186            mHandler.obtainMessage(MSG_ICON, OP_SET_ICON, 0,
187                    new Pair<String, StatusBarIcon>(slot, icon)).sendToTarget();
188        }
189    }
190
191    public void removeIcon(String slot) {
192        synchronized (mLock) {
193            // don't coalesce these
194            mHandler.obtainMessage(MSG_ICON, OP_REMOVE_ICON, 0, slot).sendToTarget();
195        }
196    }
197
198    public void disable(int state1, int state2, boolean animate) {
199        synchronized (mLock) {
200            mDisable1 = state1;
201            mDisable2 = state2;
202            mHandler.removeMessages(MSG_DISABLE);
203            Message msg = mHandler.obtainMessage(MSG_DISABLE, state1, state2, animate);
204            if (Looper.myLooper() == mHandler.getLooper()) {
205                // If its the right looper execute immediately so hides can be handled quickly.
206                mHandler.handleMessage(msg);
207                msg.recycle();
208            } else {
209                msg.sendToTarget();
210            }
211        }
212    }
213
214    public void disable(int state1, int state2) {
215        disable(state1, state2, true);
216    }
217
218    public void recomputeDisableFlags(boolean animate) {
219        disable(mDisable1, mDisable2, animate);
220    }
221
222    public void animateExpandNotificationsPanel() {
223        synchronized (mLock) {
224            mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
225            mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
226        }
227    }
228
229    public void animateCollapsePanels() {
230        synchronized (mLock) {
231            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
232            mHandler.obtainMessage(MSG_COLLAPSE_PANELS, 0, 0).sendToTarget();
233        }
234    }
235
236    public void animateCollapsePanels(int flags) {
237        synchronized (mLock) {
238            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
239            mHandler.obtainMessage(MSG_COLLAPSE_PANELS, flags, 0).sendToTarget();
240        }
241    }
242
243    public void togglePanel() {
244        synchronized (mLock) {
245            mHandler.removeMessages(MSG_TOGGLE_PANEL);
246            mHandler.obtainMessage(MSG_TOGGLE_PANEL, 0, 0).sendToTarget();
247        }
248    }
249
250    public void animateExpandSettingsPanel(String subPanel) {
251        synchronized (mLock) {
252            mHandler.removeMessages(MSG_EXPAND_SETTINGS);
253            mHandler.obtainMessage(MSG_EXPAND_SETTINGS, subPanel).sendToTarget();
254        }
255    }
256
257    public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
258            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
259        synchronized (mLock) {
260            // Don't coalesce these, since it might have one time flags set such as
261            // STATUS_BAR_UNHIDE which might get lost.
262            SomeArgs args = SomeArgs.obtain();
263            args.argi1 = vis;
264            args.argi2 = fullscreenStackVis;
265            args.argi3 = dockedStackVis;
266            args.argi4 = mask;
267            args.arg1 = fullscreenStackBounds;
268            args.arg2 = dockedStackBounds;
269            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
270        }
271    }
272
273    public void topAppWindowChanged(boolean menuVisible) {
274        synchronized (mLock) {
275            mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED);
276            mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, menuVisible ? 1 : 0, 0,
277                    null).sendToTarget();
278        }
279    }
280
281    public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
282            boolean showImeSwitcher) {
283        synchronized (mLock) {
284            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
285            Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, vis, backDisposition, token);
286            m.getData().putBoolean(SHOW_IME_SWITCHER_KEY, showImeSwitcher);
287            m.sendToTarget();
288        }
289    }
290
291    public void showRecentApps(boolean triggeredFromAltTab) {
292        synchronized (mLock) {
293            mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
294            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0, 0,
295                    null).sendToTarget();
296        }
297    }
298
299    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
300        synchronized (mLock) {
301            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
302            mHandler.obtainMessage(MSG_HIDE_RECENT_APPS,
303                    triggeredFromAltTab ? 1 : 0, triggeredFromHomeKey ? 1 : 0,
304                    null).sendToTarget();
305        }
306    }
307
308    public void toggleSplitScreen() {
309        synchronized (mLock) {
310            mHandler.removeMessages(MSG_TOGGLE_APP_SPLIT_SCREEN);
311            mHandler.obtainMessage(MSG_TOGGLE_APP_SPLIT_SCREEN, 0, 0, null).sendToTarget();
312        }
313    }
314
315    public void toggleRecentApps() {
316        synchronized (mLock) {
317            mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
318            Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null);
319            msg.setAsynchronous(true);
320            msg.sendToTarget();
321        }
322    }
323
324    public void preloadRecentApps() {
325        synchronized (mLock) {
326            mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
327            mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
328        }
329    }
330
331    public void cancelPreloadRecentApps() {
332        synchronized (mLock) {
333            mHandler.removeMessages(MSG_CANCEL_PRELOAD_RECENT_APPS);
334            mHandler.obtainMessage(MSG_CANCEL_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
335        }
336    }
337
338    @Override
339    public void dismissKeyboardShortcutsMenu() {
340        synchronized (mLock) {
341            mHandler.removeMessages(MSG_DISMISS_KEYBOARD_SHORTCUTS);
342            mHandler.obtainMessage(MSG_DISMISS_KEYBOARD_SHORTCUTS).sendToTarget();
343        }
344    }
345
346    @Override
347    public void toggleKeyboardShortcutsMenu(int deviceId) {
348        synchronized (mLock) {
349            mHandler.removeMessages(MSG_TOGGLE_KEYBOARD_SHORTCUTS);
350            mHandler.obtainMessage(MSG_TOGGLE_KEYBOARD_SHORTCUTS, deviceId, 0).sendToTarget();
351        }
352    }
353
354    @Override
355    public void showPictureInPictureMenu() {
356        synchronized (mLock) {
357            mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
358            mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU).sendToTarget();
359        }
360    }
361
362    public void setWindowState(int window, int state) {
363        synchronized (mLock) {
364            // don't coalesce these
365            mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget();
366        }
367    }
368
369    public void showScreenPinningRequest(int taskId) {
370        synchronized (mLock) {
371            mHandler.obtainMessage(MSG_SHOW_SCREEN_PIN_REQUEST, taskId, 0, null)
372                    .sendToTarget();
373        }
374    }
375
376    public void appTransitionPending() {
377        appTransitionPending(false /* forced */);
378    }
379
380    public void appTransitionPending(boolean forced) {
381        synchronized (mLock) {
382            mHandler.obtainMessage(MSG_APP_TRANSITION_PENDING, forced ? 1 : 0, 0).sendToTarget();
383        }
384    }
385
386    public void appTransitionCancelled() {
387        synchronized (mLock) {
388            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_CANCELLED);
389        }
390    }
391
392    public void appTransitionStarting(long startTime, long duration) {
393        appTransitionStarting(startTime, duration, false /* forced */);
394    }
395
396    public void appTransitionStarting(long startTime, long duration, boolean forced) {
397        synchronized (mLock) {
398            mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, forced ? 1 : 0, 0,
399                    Pair.create(startTime, duration)).sendToTarget();
400        }
401    }
402
403    @Override
404    public void appTransitionFinished() {
405        synchronized (mLock) {
406            mHandler.sendEmptyMessage(MSG_APP_TRANSITION_FINISHED);
407        }
408    }
409
410    public void showAssistDisclosure() {
411        synchronized (mLock) {
412            mHandler.removeMessages(MSG_ASSIST_DISCLOSURE);
413            mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget();
414        }
415    }
416
417    public void startAssist(Bundle args) {
418        synchronized (mLock) {
419            mHandler.removeMessages(MSG_START_ASSIST);
420            mHandler.obtainMessage(MSG_START_ASSIST, args).sendToTarget();
421        }
422    }
423
424    @Override
425    public void onCameraLaunchGestureDetected(int source) {
426        synchronized (mLock) {
427            mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
428            mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
429        }
430    }
431
432    @Override
433    public void addQsTile(ComponentName tile) {
434        synchronized (mLock) {
435            mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
436        }
437    }
438
439    @Override
440    public void remQsTile(ComponentName tile) {
441        synchronized (mLock) {
442            mHandler.obtainMessage(MSG_REMOVE_QS_TILE, tile).sendToTarget();
443        }
444    }
445
446    @Override
447    public void clickQsTile(ComponentName tile) {
448        synchronized (mLock) {
449            mHandler.obtainMessage(MSG_CLICK_QS_TILE, tile).sendToTarget();
450        }
451    }
452
453    @Override
454    public void handleSystemKey(int key) {
455        synchronized (mLock) {
456            mHandler.obtainMessage(MSG_HANDLE_SYSTEM_KEY, key, 0).sendToTarget();
457        }
458    }
459
460    @Override
461    public void showPinningEnterExitToast(boolean entering) {
462        synchronized (mLock) {
463            mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ENTER_EXIT, entering).sendToTarget();
464        }
465    }
466
467    @Override
468    public void showPinningEscapeToast() {
469        synchronized (mLock) {
470            mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ESCAPE).sendToTarget();
471        }
472    }
473
474
475    @Override
476    public void showGlobalActionsMenu() {
477        synchronized (mLock) {
478            mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
479            mHandler.obtainMessage(MSG_SHOW_GLOBAL_ACTIONS).sendToTarget();
480        }
481    }
482
483    @Override
484    public void setTopAppHidesStatusBar(boolean hidesStatusBar) {
485        mHandler.removeMessages(MSG_SET_TOP_APP_HIDES_STATUS_BAR);
486        mHandler.obtainMessage(MSG_SET_TOP_APP_HIDES_STATUS_BAR, hidesStatusBar ? 1 : 0, 0)
487                .sendToTarget();
488    }
489
490    @Override
491    public void showShutdownUi(boolean isReboot, String reason) {
492        synchronized (mLock) {
493            mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI);
494            mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, 0, reason)
495                    .sendToTarget();
496        }
497    }
498
499    @Override
500    public void showWirelessChargingAnimation(int batteryLevel) {
501        mHandler.removeMessages(MSG_SHOW_CHARGING_ANIMATION);
502        mHandler.obtainMessage(MSG_SHOW_CHARGING_ANIMATION, batteryLevel, 0)
503                .sendToTarget();
504    }
505
506    @Override
507    public void onProposedRotationChanged(int rotation, boolean isValid) {
508        synchronized (mLock) {
509            mHandler.removeMessages(MSG_ROTATION_PROPOSAL);
510            mHandler.obtainMessage(MSG_ROTATION_PROPOSAL, rotation, isValid ? 1 : 0,
511                    null).sendToTarget();
512        }
513    }
514
515    @Override
516    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
517        synchronized (mLock) {
518            SomeArgs args = SomeArgs.obtain();
519            args.arg1 = bundle;
520            args.arg2 = receiver;
521            mHandler.obtainMessage(MSG_FINGERPRINT_SHOW, args)
522                    .sendToTarget();
523        }
524    }
525
526    @Override
527    public void onFingerprintAuthenticated() {
528        synchronized (mLock) {
529            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
530        }
531    }
532
533    @Override
534    public void onFingerprintHelp(String message) {
535        synchronized (mLock) {
536            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
537        }
538    }
539
540    @Override
541    public void onFingerprintError(String error) {
542        synchronized (mLock) {
543            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
544        }
545    }
546
547    @Override
548    public void hideFingerprintDialog() {
549        synchronized (mLock) {
550            mHandler.obtainMessage(MSG_FINGERPRINT_HIDE).sendToTarget();
551        }
552    }
553
554    private final class H extends Handler {
555        private H(Looper l) {
556            super(l);
557        }
558
559        public void handleMessage(Message msg) {
560            final int what = msg.what & MSG_MASK;
561            switch (what) {
562                case MSG_ICON: {
563                    switch (msg.arg1) {
564                        case OP_SET_ICON: {
565                            Pair<String, StatusBarIcon> p = (Pair<String, StatusBarIcon>) msg.obj;
566                            for (int i = 0; i < mCallbacks.size(); i++) {
567                                mCallbacks.get(i).setIcon(p.first, p.second);
568                            }
569                            break;
570                        }
571                        case OP_REMOVE_ICON:
572                            for (int i = 0; i < mCallbacks.size(); i++) {
573                                mCallbacks.get(i).removeIcon((String) msg.obj);
574                            }
575                            break;
576                    }
577                    break;
578                }
579                case MSG_DISABLE:
580                    for (int i = 0; i < mCallbacks.size(); i++) {
581                        mCallbacks.get(i).disable(msg.arg1, msg.arg2, (Boolean) msg.obj);
582                    }
583                    break;
584                case MSG_EXPAND_NOTIFICATIONS:
585                    for (int i = 0; i < mCallbacks.size(); i++) {
586                        mCallbacks.get(i).animateExpandNotificationsPanel();
587                    }
588                    break;
589                case MSG_COLLAPSE_PANELS:
590                    for (int i = 0; i < mCallbacks.size(); i++) {
591                        mCallbacks.get(i).animateCollapsePanels(msg.arg1);
592                    }
593                    break;
594                case MSG_TOGGLE_PANEL:
595                    for (int i = 0; i < mCallbacks.size(); i++) {
596                        mCallbacks.get(i).togglePanel();
597                    }
598                    break;
599                case MSG_EXPAND_SETTINGS:
600                    for (int i = 0; i < mCallbacks.size(); i++) {
601                        mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
602                    }
603                    break;
604                case MSG_SET_SYSTEMUI_VISIBILITY:
605                    SomeArgs args = (SomeArgs) msg.obj;
606                    for (int i = 0; i < mCallbacks.size(); i++) {
607                        mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
608                                args.argi4, (Rect) args.arg1, (Rect) args.arg2);
609                    }
610                    args.recycle();
611                    break;
612                case MSG_TOP_APP_WINDOW_CHANGED:
613                    for (int i = 0; i < mCallbacks.size(); i++) {
614                        mCallbacks.get(i).topAppWindowChanged(msg.arg1 != 0);
615                    }
616                    break;
617                case MSG_SHOW_IME_BUTTON:
618                    for (int i = 0; i < mCallbacks.size(); i++) {
619                        mCallbacks.get(i).setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
620                                msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
621                    }
622                    break;
623                case MSG_SHOW_RECENT_APPS:
624                    for (int i = 0; i < mCallbacks.size(); i++) {
625                        mCallbacks.get(i).showRecentApps(msg.arg1 != 0);
626                    }
627                    break;
628                case MSG_HIDE_RECENT_APPS:
629                    for (int i = 0; i < mCallbacks.size(); i++) {
630                        mCallbacks.get(i).hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
631                    }
632                    break;
633                case MSG_TOGGLE_RECENT_APPS:
634                    for (int i = 0; i < mCallbacks.size(); i++) {
635                        mCallbacks.get(i).toggleRecentApps();
636                    }
637                    break;
638                case MSG_PRELOAD_RECENT_APPS:
639                    for (int i = 0; i < mCallbacks.size(); i++) {
640                        mCallbacks.get(i).preloadRecentApps();
641                    }
642                    break;
643                case MSG_CANCEL_PRELOAD_RECENT_APPS:
644                    for (int i = 0; i < mCallbacks.size(); i++) {
645                        mCallbacks.get(i).cancelPreloadRecentApps();
646                    }
647                    break;
648                case MSG_DISMISS_KEYBOARD_SHORTCUTS:
649                    for (int i = 0; i < mCallbacks.size(); i++) {
650                        mCallbacks.get(i).dismissKeyboardShortcutsMenu();
651                    }
652                    break;
653                case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
654                    for (int i = 0; i < mCallbacks.size(); i++) {
655                        mCallbacks.get(i).toggleKeyboardShortcutsMenu(msg.arg1);
656                    }
657                    break;
658                case MSG_SET_WINDOW_STATE:
659                    for (int i = 0; i < mCallbacks.size(); i++) {
660                        mCallbacks.get(i).setWindowState(msg.arg1, msg.arg2);
661                    }
662                    break;
663                case MSG_SHOW_SCREEN_PIN_REQUEST:
664                    for (int i = 0; i < mCallbacks.size(); i++) {
665                        mCallbacks.get(i).showScreenPinningRequest(msg.arg1);
666                    }
667                    break;
668                case MSG_APP_TRANSITION_PENDING:
669                    for (int i = 0; i < mCallbacks.size(); i++) {
670                        mCallbacks.get(i).appTransitionPending(msg.arg1 != 0);
671                    }
672                    break;
673                case MSG_APP_TRANSITION_CANCELLED:
674                    for (int i = 0; i < mCallbacks.size(); i++) {
675                        mCallbacks.get(i).appTransitionCancelled();
676                    }
677                    break;
678                case MSG_APP_TRANSITION_STARTING:
679                    for (int i = 0; i < mCallbacks.size(); i++) {
680                        Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
681                        mCallbacks.get(i).appTransitionStarting(data.first, data.second,
682                                msg.arg1 != 0);
683                    }
684                    break;
685                case MSG_APP_TRANSITION_FINISHED:
686                    for (int i = 0; i < mCallbacks.size(); i++) {
687                        mCallbacks.get(i).appTransitionFinished();
688                    }
689                    break;
690                case MSG_ASSIST_DISCLOSURE:
691                    for (int i = 0; i < mCallbacks.size(); i++) {
692                        mCallbacks.get(i).showAssistDisclosure();
693                    }
694                    break;
695                case MSG_START_ASSIST:
696                    for (int i = 0; i < mCallbacks.size(); i++) {
697                        mCallbacks.get(i).startAssist((Bundle) msg.obj);
698                    }
699                    break;
700                case MSG_CAMERA_LAUNCH_GESTURE:
701                    for (int i = 0; i < mCallbacks.size(); i++) {
702                        mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1);
703                    }
704                    break;
705                case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
706                    for (int i = 0; i < mCallbacks.size(); i++) {
707                        mCallbacks.get(i).showPictureInPictureMenu();
708                    }
709                    break;
710                case MSG_ADD_QS_TILE:
711                    for (int i = 0; i < mCallbacks.size(); i++) {
712                        mCallbacks.get(i).addQsTile((ComponentName) msg.obj);
713                    }
714                    break;
715                case MSG_REMOVE_QS_TILE:
716                    for (int i = 0; i < mCallbacks.size(); i++) {
717                        mCallbacks.get(i).remQsTile((ComponentName) msg.obj);
718                    }
719                    break;
720                case MSG_CLICK_QS_TILE:
721                    for (int i = 0; i < mCallbacks.size(); i++) {
722                        mCallbacks.get(i).clickTile((ComponentName) msg.obj);
723                    }
724                    break;
725                case MSG_TOGGLE_APP_SPLIT_SCREEN:
726                    for (int i = 0; i < mCallbacks.size(); i++) {
727                        mCallbacks.get(i).toggleSplitScreen();
728                    }
729                    break;
730                case MSG_HANDLE_SYSTEM_KEY:
731                    for (int i = 0; i < mCallbacks.size(); i++) {
732                        mCallbacks.get(i).handleSystemKey(msg.arg1);
733                    }
734                    break;
735                case MSG_SHOW_GLOBAL_ACTIONS:
736                    for (int i = 0; i < mCallbacks.size(); i++) {
737                        mCallbacks.get(i).handleShowGlobalActionsMenu();
738                    }
739                    break;
740                case MSG_SHOW_SHUTDOWN_UI:
741                    for (int i = 0; i < mCallbacks.size(); i++) {
742                        mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj);
743                    }
744                    break;
745                case MSG_SET_TOP_APP_HIDES_STATUS_BAR:
746                    for (int i = 0; i < mCallbacks.size(); i++) {
747                        mCallbacks.get(i).setTopAppHidesStatusBar(msg.arg1 != 0);
748                    }
749                    break;
750                case MSG_ROTATION_PROPOSAL:
751                    for (int i = 0; i < mCallbacks.size(); i++) {
752                        mCallbacks.get(i).onRotationProposal(msg.arg1, msg.arg2 != 0);
753                    }
754                    break;
755                case MSG_FINGERPRINT_SHOW:
756                    mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
757                    mHandler.removeMessages(MSG_FINGERPRINT_HELP);
758                    mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
759                    for (int i = 0; i < mCallbacks.size(); i++) {
760                        mCallbacks.get(i).showFingerprintDialog(
761                                (Bundle)((SomeArgs)msg.obj).arg1,
762                                (IBiometricPromptReceiver)((SomeArgs)msg.obj).arg2);
763                    }
764                    break;
765                case MSG_FINGERPRINT_AUTHENTICATED:
766                    for (int i = 0; i < mCallbacks.size(); i++) {
767                        mCallbacks.get(i).onFingerprintAuthenticated();
768                    }
769                    break;
770                case MSG_FINGERPRINT_HELP:
771                    for (int i = 0; i < mCallbacks.size(); i++) {
772                        mCallbacks.get(i).onFingerprintHelp((String) msg.obj);
773                    }
774                    break;
775                case MSG_FINGERPRINT_ERROR:
776                    for (int i = 0; i < mCallbacks.size(); i++) {
777                        mCallbacks.get(i).onFingerprintError((String) msg.obj);
778                    }
779                    break;
780                case MSG_FINGERPRINT_HIDE:
781                    for (int i = 0; i < mCallbacks.size(); i++) {
782                        mCallbacks.get(i).hideFingerprintDialog();
783                    }
784                    break;
785                case MSG_SHOW_CHARGING_ANIMATION:
786                    for (int i = 0; i < mCallbacks.size(); i++) {
787                        mCallbacks.get(i).showWirelessChargingAnimation(msg.arg1);
788                    }
789                    break;
790                case MSG_SHOW_PINNING_TOAST_ENTER_EXIT:
791                    for (int i = 0; i < mCallbacks.size(); i++) {
792                        mCallbacks.get(i).showPinningEnterExitToast((Boolean) msg.obj);
793                    }
794                    break;
795                case MSG_SHOW_PINNING_TOAST_ESCAPE:
796                    for (int i = 0; i < mCallbacks.size(); i++) {
797                        mCallbacks.get(i).showPinningEscapeToast();
798                    }
799                    break;
800            }
801        }
802    }
803
804    // Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
805    // is needed so it can extend SystemUI.
806    public static class CommandQueueStart extends SystemUI {
807        @Override
808        public void start() {
809            putComponent(CommandQueue.class, new CommandQueue());
810        }
811    }
812}
813