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