1 /* 2 * Copyright (C) 2007 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 android.app; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.annotation.SystemService; 25 import android.annotation.TestApi; 26 import android.annotation.UnsupportedAppUsage; 27 import android.content.Context; 28 import android.os.Binder; 29 import android.os.IBinder; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.util.Pair; 33 import android.util.Slog; 34 import android.view.View; 35 36 import com.android.internal.statusbar.IStatusBarService; 37 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.RetentionPolicy; 40 41 /** 42 * Allows an app to control the status bar. 43 */ 44 @SystemService(Context.STATUS_BAR_SERVICE) 45 public class StatusBarManager { 46 47 /** @hide */ 48 public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; 49 /** @hide */ 50 public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS; 51 /** @hide */ 52 public static final int DISABLE_NOTIFICATION_ALERTS 53 = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; 54 55 /** @hide */ 56 @Deprecated 57 @UnsupportedAppUsage 58 public static final int DISABLE_NOTIFICATION_TICKER 59 = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; 60 /** @hide */ 61 public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; 62 /** @hide */ 63 public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME; 64 /** @hide */ 65 public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT; 66 /** @hide */ 67 public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK; 68 /** @hide */ 69 public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK; 70 /** @hide */ 71 public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH; 72 73 /** @hide */ 74 @Deprecated 75 public static final int DISABLE_NAVIGATION = 76 View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT; 77 78 /** @hide */ 79 public static final int DISABLE_NONE = 0x00000000; 80 81 /** @hide */ 82 public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS 83 | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER 84 | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK 85 | DISABLE_SEARCH; 86 87 /** @hide */ 88 @IntDef(flag = true, prefix = {"DISABLE_"}, value = { 89 DISABLE_NONE, 90 DISABLE_EXPAND, 91 DISABLE_NOTIFICATION_ICONS, 92 DISABLE_NOTIFICATION_ALERTS, 93 DISABLE_NOTIFICATION_TICKER, 94 DISABLE_SYSTEM_INFO, 95 DISABLE_HOME, 96 DISABLE_RECENT, 97 DISABLE_BACK, 98 DISABLE_CLOCK, 99 DISABLE_SEARCH 100 }) 101 @Retention(RetentionPolicy.SOURCE) 102 public @interface DisableFlags {} 103 104 /** 105 * Flag to disable quick settings. 106 * 107 * Setting this flag disables quick settings completely, but does not disable expanding the 108 * notification shade. 109 */ 110 /** @hide */ 111 public static final int DISABLE2_QUICK_SETTINGS = 1; 112 /** @hide */ 113 public static final int DISABLE2_SYSTEM_ICONS = 1 << 1; 114 /** @hide */ 115 public static final int DISABLE2_NOTIFICATION_SHADE = 1 << 2; 116 /** @hide */ 117 public static final int DISABLE2_GLOBAL_ACTIONS = 1 << 3; 118 /** @hide */ 119 public static final int DISABLE2_ROTATE_SUGGESTIONS = 1 << 4; 120 121 /** @hide */ 122 public static final int DISABLE2_NONE = 0x00000000; 123 124 /** @hide */ 125 public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS | DISABLE2_SYSTEM_ICONS 126 | DISABLE2_NOTIFICATION_SHADE | DISABLE2_GLOBAL_ACTIONS | DISABLE2_ROTATE_SUGGESTIONS; 127 128 /** @hide */ 129 @IntDef(flag = true, prefix = { "DISABLE2_" }, value = { 130 DISABLE2_NONE, 131 DISABLE2_MASK, 132 DISABLE2_QUICK_SETTINGS, 133 DISABLE2_SYSTEM_ICONS, 134 DISABLE2_NOTIFICATION_SHADE, 135 DISABLE2_GLOBAL_ACTIONS, 136 DISABLE2_ROTATE_SUGGESTIONS 137 }) 138 @Retention(RetentionPolicy.SOURCE) 139 public @interface Disable2Flags {} 140 141 /** 142 * Default disable flags for setup 143 * 144 * @hide 145 */ 146 public static final int DEFAULT_SETUP_DISABLE_FLAGS = DISABLE_NOTIFICATION_ALERTS 147 | DISABLE_HOME | DISABLE_EXPAND | DISABLE_RECENT | DISABLE_CLOCK | DISABLE_SEARCH; 148 149 /** 150 * Default disable2 flags for setup 151 * 152 * @hide 153 */ 154 public static final int DEFAULT_SETUP_DISABLE2_FLAGS = DISABLE2_ROTATE_SUGGESTIONS; 155 156 /** @hide */ 157 public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0; 158 /** @hide */ 159 public static final int NAVIGATION_HINT_IME_SHOWN = 1 << 1; 160 161 /** @hide */ 162 public static final int WINDOW_STATUS_BAR = 1; 163 /** @hide */ 164 public static final int WINDOW_NAVIGATION_BAR = 2; 165 166 /** @hide */ 167 @IntDef(flag = true, prefix = { "WINDOW_" }, value = { 168 WINDOW_STATUS_BAR, 169 WINDOW_NAVIGATION_BAR 170 }) 171 @Retention(RetentionPolicy.SOURCE) 172 public @interface WindowType {} 173 174 /** @hide */ 175 public static final int WINDOW_STATE_SHOWING = 0; 176 /** @hide */ 177 public static final int WINDOW_STATE_HIDING = 1; 178 /** @hide */ 179 public static final int WINDOW_STATE_HIDDEN = 2; 180 181 /** @hide */ 182 @IntDef(flag = true, prefix = { "WINDOW_STATE_" }, value = { 183 WINDOW_STATE_SHOWING, 184 WINDOW_STATE_HIDING, 185 WINDOW_STATE_HIDDEN 186 }) 187 @Retention(RetentionPolicy.SOURCE) 188 public @interface WindowVisibleState {} 189 190 /** @hide */ 191 public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; 192 /** @hide */ 193 public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; 194 /** @hide */ 195 public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2; 196 197 @UnsupportedAppUsage 198 private Context mContext; 199 private IStatusBarService mService; 200 @UnsupportedAppUsage 201 private IBinder mToken = new Binder(); 202 203 @UnsupportedAppUsage StatusBarManager(Context context)204 StatusBarManager(Context context) { 205 mContext = context; 206 } 207 208 @UnsupportedAppUsage getService()209 private synchronized IStatusBarService getService() { 210 if (mService == null) { 211 mService = IStatusBarService.Stub.asInterface( 212 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 213 if (mService == null) { 214 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); 215 } 216 } 217 return mService; 218 } 219 220 /** 221 * Disable some features in the status bar. Pass the bitwise-or of the DISABLE_* flags. 222 * To re-enable everything, pass {@link #DISABLE_NONE}. 223 * 224 * @hide 225 */ 226 @UnsupportedAppUsage disable(int what)227 public void disable(int what) { 228 try { 229 final int userId = Binder.getCallingUserHandle().getIdentifier(); 230 final IStatusBarService svc = getService(); 231 if (svc != null) { 232 svc.disableForUser(what, mToken, mContext.getPackageName(), userId); 233 } 234 } catch (RemoteException ex) { 235 throw ex.rethrowFromSystemServer(); 236 } 237 } 238 239 /** 240 * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. 241 * To re-enable everything, pass {@link #DISABLE_NONE}. 242 * 243 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 244 * 245 * @hide 246 */ disable2(@isable2Flags int what)247 public void disable2(@Disable2Flags int what) { 248 try { 249 final int userId = Binder.getCallingUserHandle().getIdentifier(); 250 final IStatusBarService svc = getService(); 251 if (svc != null) { 252 svc.disable2ForUser(what, mToken, mContext.getPackageName(), userId); 253 } 254 } catch (RemoteException ex) { 255 throw ex.rethrowFromSystemServer(); 256 } 257 } 258 259 /** 260 * Expand the notifications panel. 261 * 262 * @hide 263 */ 264 @UnsupportedAppUsage expandNotificationsPanel()265 public void expandNotificationsPanel() { 266 try { 267 final IStatusBarService svc = getService(); 268 if (svc != null) { 269 svc.expandNotificationsPanel(); 270 } 271 } catch (RemoteException ex) { 272 throw ex.rethrowFromSystemServer(); 273 } 274 } 275 276 /** 277 * Collapse the notifications and settings panels. 278 * 279 * @hide 280 */ 281 @UnsupportedAppUsage collapsePanels()282 public void collapsePanels() { 283 try { 284 final IStatusBarService svc = getService(); 285 if (svc != null) { 286 svc.collapsePanels(); 287 } 288 } catch (RemoteException ex) { 289 throw ex.rethrowFromSystemServer(); 290 } 291 } 292 293 /** 294 * Expand the settings panel. 295 * 296 * @hide 297 */ 298 @UnsupportedAppUsage expandSettingsPanel()299 public void expandSettingsPanel() { 300 expandSettingsPanel(null); 301 } 302 303 /** 304 * Expand the settings panel and open a subPanel. If the subpanel is null or does not have a 305 * corresponding tile, the QS panel is simply expanded 306 * 307 * @hide 308 */ 309 @UnsupportedAppUsage expandSettingsPanel(@ullable String subPanel)310 public void expandSettingsPanel(@Nullable String subPanel) { 311 try { 312 final IStatusBarService svc = getService(); 313 if (svc != null) { 314 svc.expandSettingsPanel(subPanel); 315 } 316 } catch (RemoteException ex) { 317 throw ex.rethrowFromSystemServer(); 318 } 319 } 320 321 /** @hide */ 322 @UnsupportedAppUsage setIcon(String slot, int iconId, int iconLevel, String contentDescription)323 public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) { 324 try { 325 final IStatusBarService svc = getService(); 326 if (svc != null) { 327 svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel, 328 contentDescription); 329 } 330 } catch (RemoteException ex) { 331 throw ex.rethrowFromSystemServer(); 332 } 333 } 334 335 /** @hide */ 336 @UnsupportedAppUsage removeIcon(String slot)337 public void removeIcon(String slot) { 338 try { 339 final IStatusBarService svc = getService(); 340 if (svc != null) { 341 svc.removeIcon(slot); 342 } 343 } catch (RemoteException ex) { 344 throw ex.rethrowFromSystemServer(); 345 } 346 } 347 348 /** @hide */ 349 @UnsupportedAppUsage setIconVisibility(String slot, boolean visible)350 public void setIconVisibility(String slot, boolean visible) { 351 try { 352 final IStatusBarService svc = getService(); 353 if (svc != null) { 354 svc.setIconVisibility(slot, visible); 355 } 356 } catch (RemoteException ex) { 357 throw ex.rethrowFromSystemServer(); 358 } 359 } 360 361 /** 362 * Enable or disable status bar elements (notifications, clock) which are inappropriate during 363 * device setup. 364 * 365 * @param disabled whether to apply or remove the disabled flags 366 * 367 * @hide 368 */ 369 @SystemApi 370 @TestApi 371 @RequiresPermission(android.Manifest.permission.STATUS_BAR) setDisabledForSetup(boolean disabled)372 public void setDisabledForSetup(boolean disabled) { 373 try { 374 final int userId = Binder.getCallingUserHandle().getIdentifier(); 375 final IStatusBarService svc = getService(); 376 if (svc != null) { 377 svc.disableForUser(disabled ? DEFAULT_SETUP_DISABLE_FLAGS : DISABLE_NONE, 378 mToken, mContext.getPackageName(), userId); 379 svc.disable2ForUser(disabled ? DEFAULT_SETUP_DISABLE2_FLAGS : DISABLE2_NONE, 380 mToken, mContext.getPackageName(), userId); 381 } 382 } catch (RemoteException ex) { 383 throw ex.rethrowFromSystemServer(); 384 } 385 } 386 387 /** 388 * Get this app's currently requested disabled components 389 * 390 * @return a new DisableInfo 391 * 392 * @hide 393 */ 394 @SystemApi 395 @TestApi 396 @RequiresPermission(android.Manifest.permission.STATUS_BAR) 397 @NonNull getDisableInfo()398 public DisableInfo getDisableInfo() { 399 try { 400 final int userId = Binder.getCallingUserHandle().getIdentifier(); 401 final IStatusBarService svc = getService(); 402 int[] flags = new int[] {0, 0}; 403 if (svc != null) { 404 flags = svc.getDisableFlags(mToken, userId); 405 } 406 407 return new DisableInfo(flags[0], flags[1]); 408 } catch (RemoteException ex) { 409 throw ex.rethrowFromSystemServer(); 410 } 411 } 412 413 /** @hide */ windowStateToString(int state)414 public static String windowStateToString(int state) { 415 if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; 416 if (state == WINDOW_STATE_HIDDEN) return "WINDOW_STATE_HIDDEN"; 417 if (state == WINDOW_STATE_SHOWING) return "WINDOW_STATE_SHOWING"; 418 return "WINDOW_STATE_UNKNOWN"; 419 } 420 421 /** 422 * DisableInfo describes this app's requested state of the StatusBar with regards to which 423 * components are enabled/disabled 424 * 425 * @hide 426 */ 427 @SystemApi 428 @TestApi 429 public static final class DisableInfo { 430 431 private boolean mStatusBarExpansion; 432 private boolean mNavigateHome; 433 private boolean mNotificationPeeking; 434 private boolean mRecents; 435 private boolean mSearch; 436 437 /** @hide */ DisableInfo(int flags1, int flags2)438 public DisableInfo(int flags1, int flags2) { 439 mStatusBarExpansion = (flags1 & DISABLE_EXPAND) != 0; 440 mNavigateHome = (flags1 & DISABLE_HOME) != 0; 441 mNotificationPeeking = (flags1 & DISABLE_NOTIFICATION_ALERTS) != 0; 442 mRecents = (flags1 & DISABLE_RECENT) != 0; 443 mSearch = (flags1 & DISABLE_SEARCH) != 0; 444 } 445 446 /** @hide */ DisableInfo()447 public DisableInfo() {} 448 449 /** 450 * @return {@code true} if expanding the notification shade is disabled 451 * 452 * @hide 453 */ 454 @SystemApi 455 @TestApi isStatusBarExpansionDisabled()456 public boolean isStatusBarExpansionDisabled() { 457 return mStatusBarExpansion; 458 } 459 460 /** * @hide */ setStatusBarExpansionDisabled(boolean disabled)461 public void setStatusBarExpansionDisabled(boolean disabled) { 462 mStatusBarExpansion = disabled; 463 } 464 465 /** 466 * @return {@code true} if navigation home is disabled 467 * 468 * @hide 469 */ 470 @SystemApi 471 @TestApi isNavigateToHomeDisabled()472 public boolean isNavigateToHomeDisabled() { 473 return mNavigateHome; 474 } 475 476 /** * @hide */ setNagivationHomeDisabled(boolean disabled)477 public void setNagivationHomeDisabled(boolean disabled) { 478 mNavigateHome = disabled; 479 } 480 481 /** 482 * @return {@code true} if notification peeking (heads-up notification) is disabled 483 * 484 * @hide 485 */ 486 @SystemApi 487 @TestApi isNotificationPeekingDisabled()488 public boolean isNotificationPeekingDisabled() { 489 return mNotificationPeeking; 490 } 491 492 /** @hide */ setNotificationPeekingDisabled(boolean disabled)493 public void setNotificationPeekingDisabled(boolean disabled) { 494 mNotificationPeeking = disabled; 495 } 496 497 /** 498 * @return {@code true} if mRecents/overview is disabled 499 * 500 * @hide 501 */ 502 @SystemApi 503 @TestApi isRecentsDisabled()504 public boolean isRecentsDisabled() { 505 return mRecents; 506 } 507 508 /** @hide */ setRecentsDisabled(boolean disabled)509 public void setRecentsDisabled(boolean disabled) { 510 mRecents = disabled; 511 } 512 513 /** 514 * @return {@code true} if mSearch is disabled 515 * 516 * @hide 517 */ 518 @SystemApi 519 @TestApi isSearchDisabled()520 public boolean isSearchDisabled() { 521 return mSearch; 522 } 523 524 /** @hide */ setSearchDisabled(boolean disabled)525 public void setSearchDisabled(boolean disabled) { 526 mSearch = disabled; 527 } 528 529 /** 530 * @return {@code true} if no components are disabled (default state) 531 * 532 * @hide 533 */ 534 @SystemApi 535 @TestApi areAllComponentsEnabled()536 public boolean areAllComponentsEnabled() { 537 return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents 538 && !mSearch; 539 } 540 541 /** @hide */ setEnableAll()542 public void setEnableAll() { 543 mStatusBarExpansion = false; 544 mNavigateHome = false; 545 mNotificationPeeking = false; 546 mRecents = false; 547 mSearch = false; 548 } 549 550 /** 551 * @return {@code true} if all status bar components are disabled 552 * 553 * @hide 554 */ areAllComponentsDisabled()555 public boolean areAllComponentsDisabled() { 556 return mStatusBarExpansion && mNavigateHome && mNotificationPeeking 557 && mRecents && mSearch; 558 } 559 560 /** @hide */ setDisableAll()561 public void setDisableAll() { 562 mStatusBarExpansion = true; 563 mNavigateHome = true; 564 mNotificationPeeking = true; 565 mRecents = true; 566 mSearch = true; 567 } 568 569 @Override toString()570 public String toString() { 571 StringBuilder sb = new StringBuilder(); 572 sb.append("DisableInfo: "); 573 sb.append(" mStatusBarExpansion=").append(mStatusBarExpansion ? "disabled" : "enabled"); 574 sb.append(" mNavigateHome=").append(mNavigateHome ? "disabled" : "enabled"); 575 sb.append(" mNotificationPeeking=") 576 .append(mNotificationPeeking ? "disabled" : "enabled"); 577 sb.append(" mRecents=").append(mRecents ? "disabled" : "enabled"); 578 sb.append(" mSearch=").append(mSearch ? "disabled" : "enabled"); 579 580 return sb.toString(); 581 582 } 583 584 /** 585 * Convert a DisableInfo to equivalent flags 586 * @return a pair of equivalent disable flags 587 * 588 * @hide 589 */ toFlags()590 public Pair<Integer, Integer> toFlags() { 591 int disable1 = DISABLE_NONE; 592 int disable2 = DISABLE2_NONE; 593 594 if (mStatusBarExpansion) disable1 |= DISABLE_EXPAND; 595 if (mNavigateHome) disable1 |= DISABLE_HOME; 596 if (mNotificationPeeking) disable1 |= DISABLE_NOTIFICATION_ALERTS; 597 if (mRecents) disable1 |= DISABLE_RECENT; 598 if (mSearch) disable1 |= DISABLE_SEARCH; 599 600 return new Pair<Integer, Integer>(disable1, disable2); 601 } 602 } 603 } 604