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