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 { addIcon(String slot, int index, int viewIndex, StatusBarIcon icon)85 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon); updateIcon(String slot, int index, int viewIndex, StatusBarIcon old, StatusBarIcon icon)86 public void updateIcon(String slot, int index, int viewIndex, 87 StatusBarIcon old, StatusBarIcon icon); removeIcon(String slot, int index, int viewIndex)88 public void removeIcon(String slot, int index, int viewIndex); disable(int state1, int state2, boolean animate)89 public void disable(int state1, int state2, boolean animate); animateExpandNotificationsPanel()90 public void animateExpandNotificationsPanel(); animateCollapsePanels(int flags)91 public void animateCollapsePanels(int flags); animateExpandSettingsPanel()92 public void animateExpandSettingsPanel(); setSystemUiVisibility(int vis, int mask)93 public void setSystemUiVisibility(int vis, int mask); topAppWindowChanged(boolean visible)94 public void topAppWindowChanged(boolean visible); setImeWindowStatus(IBinder token, int vis, int backDisposition, boolean showImeSwitcher)95 public void setImeWindowStatus(IBinder token, int vis, int backDisposition, 96 boolean showImeSwitcher); showRecentApps(boolean triggeredFromAltTab)97 public void showRecentApps(boolean triggeredFromAltTab); hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey)98 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); toggleRecentApps()99 public void toggleRecentApps(); preloadRecentApps()100 public void preloadRecentApps(); cancelPreloadRecentApps()101 public void cancelPreloadRecentApps(); setWindowState(int window, int state)102 public void setWindowState(int window, int state); buzzBeepBlinked()103 public void buzzBeepBlinked(); notificationLightOff()104 public void notificationLightOff(); notificationLightPulse(int argb, int onMillis, int offMillis)105 public void notificationLightPulse(int argb, int onMillis, int offMillis); showScreenPinningRequest()106 public void showScreenPinningRequest(); appTransitionPending()107 public void appTransitionPending(); appTransitionCancelled()108 public void appTransitionCancelled(); appTransitionStarting(long startTime, long duration)109 public void appTransitionStarting(long startTime, long duration); showAssistDisclosure()110 public void showAssistDisclosure(); startAssist(Bundle args)111 public void startAssist(Bundle args); 112 } 113 CommandQueue(Callbacks callbacks, StatusBarIconList list)114 public CommandQueue(Callbacks callbacks, StatusBarIconList list) { 115 mCallbacks = callbacks; 116 mList = list; 117 } 118 setIcon(int index, StatusBarIcon icon)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 removeIcon(int index)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 disable(int state1, int state2)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 animateExpandNotificationsPanel()142 public void animateExpandNotificationsPanel() { 143 synchronized (mList) { 144 mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS); 145 mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS); 146 } 147 } 148 animateCollapsePanels()149 public void animateCollapsePanels() { 150 synchronized (mList) { 151 mHandler.removeMessages(MSG_COLLAPSE_PANELS); 152 mHandler.sendEmptyMessage(MSG_COLLAPSE_PANELS); 153 } 154 } 155 animateExpandSettingsPanel()156 public void animateExpandSettingsPanel() { 157 synchronized (mList) { 158 mHandler.removeMessages(MSG_EXPAND_SETTINGS); 159 mHandler.sendEmptyMessage(MSG_EXPAND_SETTINGS); 160 } 161 } 162 setSystemUiVisibility(int vis, int mask)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 topAppWindowChanged(boolean menuVisible)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 setImeWindowStatus(IBinder token, int vis, int backDisposition, boolean showImeSwitcher)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 showRecentApps(boolean triggeredFromAltTab)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 hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey)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 toggleRecentApps()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 preloadRecentApps()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 cancelPreloadRecentApps()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 setWindowState(int window, int state)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 buzzBeepBlinked()234 public void buzzBeepBlinked() { 235 synchronized (mList) { 236 mHandler.removeMessages(MSG_BUZZ_BEEP_BLINKED); 237 mHandler.sendEmptyMessage(MSG_BUZZ_BEEP_BLINKED); 238 } 239 } 240 notificationLightOff()241 public void notificationLightOff() { 242 synchronized (mList) { 243 mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF); 244 } 245 } 246 notificationLightPulse(int argb, int onMillis, int offMillis)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 showScreenPinningRequest()254 public void showScreenPinningRequest() { 255 synchronized (mList) { 256 mHandler.sendEmptyMessage(MSG_SHOW_SCREEN_PIN_REQUEST); 257 } 258 } 259 appTransitionPending()260 public void appTransitionPending() { 261 synchronized (mList) { 262 mHandler.removeMessages(MSG_APP_TRANSITION_PENDING); 263 mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING); 264 } 265 } 266 appTransitionCancelled()267 public void appTransitionCancelled() { 268 synchronized (mList) { 269 mHandler.removeMessages(MSG_APP_TRANSITION_PENDING); 270 mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING); 271 } 272 } 273 appTransitionStarting(long startTime, long duration)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 showAssistDisclosure()282 public void showAssistDisclosure() { 283 synchronized (mList) { 284 mHandler.removeMessages(MSG_ASSIST_DISCLOSURE); 285 mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget(); 286 } 287 } 288 startAssist(Bundle args)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 { handleMessage(Message msg)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