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