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