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