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.Manifest; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.annotation.SystemService; 26 import android.annotation.TestApi; 27 import android.app.compat.CompatChanges; 28 import android.compat.annotation.ChangeId; 29 import android.compat.annotation.EnabledSince; 30 import android.compat.annotation.UnsupportedAppUsage; 31 import android.content.ComponentName; 32 import android.content.Context; 33 import android.graphics.drawable.Icon; 34 import android.media.INearbyMediaDevicesProvider; 35 import android.media.INearbyMediaDevicesUpdateCallback; 36 import android.media.MediaRoute2Info; 37 import android.media.NearbyDevice; 38 import android.media.NearbyMediaDevicesProvider; 39 import android.os.Binder; 40 import android.os.Build; 41 import android.os.Bundle; 42 import android.os.IBinder; 43 import android.os.RemoteException; 44 import android.os.ServiceManager; 45 import android.os.UserHandle; 46 import android.util.Pair; 47 import android.util.Slog; 48 import android.view.View; 49 50 import com.android.internal.statusbar.IAddTileResultCallback; 51 import com.android.internal.statusbar.IStatusBarService; 52 import com.android.internal.statusbar.IUndoMediaTransferCallback; 53 import com.android.internal.statusbar.NotificationVisibility; 54 55 import java.lang.annotation.Retention; 56 import java.lang.annotation.RetentionPolicy; 57 import java.util.HashMap; 58 import java.util.List; 59 import java.util.Map; 60 import java.util.Objects; 61 import java.util.Set; 62 import java.util.concurrent.Executor; 63 import java.util.function.Consumer; 64 65 /** 66 * Allows an app to control the status bar. 67 */ 68 @SystemService(Context.STATUS_BAR_SERVICE) 69 public class StatusBarManager { 70 // LINT.IfChange 71 /** @hide */ 72 public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; 73 /** @hide */ 74 public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS; 75 /** @hide */ 76 public static final int DISABLE_NOTIFICATION_ALERTS 77 = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; 78 79 /** @hide */ 80 @Deprecated 81 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 82 public static final int DISABLE_NOTIFICATION_TICKER 83 = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; 84 /** @hide */ 85 public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; 86 /** @hide */ 87 public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME; 88 /** @hide */ 89 public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT; 90 /** @hide */ 91 public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK; 92 /** @hide */ 93 public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK; 94 /** @hide */ 95 public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH; 96 97 /** @hide */ 98 public static final int DISABLE_ONGOING_CALL_CHIP = View.STATUS_BAR_DISABLE_ONGOING_CALL_CHIP; 99 100 /** @hide */ 101 @Deprecated 102 public static final int DISABLE_NAVIGATION = 103 View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT; 104 105 /** @hide */ 106 public static final int DISABLE_NONE = 0x00000000; 107 108 /** @hide */ 109 public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS 110 | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER 111 | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK 112 | DISABLE_SEARCH | DISABLE_ONGOING_CALL_CHIP; 113 114 /** @hide */ 115 @IntDef(flag = true, prefix = {"DISABLE_"}, value = { 116 DISABLE_NONE, 117 DISABLE_EXPAND, 118 DISABLE_NOTIFICATION_ICONS, 119 DISABLE_NOTIFICATION_ALERTS, 120 DISABLE_NOTIFICATION_TICKER, 121 DISABLE_SYSTEM_INFO, 122 DISABLE_HOME, 123 DISABLE_RECENT, 124 DISABLE_BACK, 125 DISABLE_CLOCK, 126 DISABLE_SEARCH, 127 DISABLE_ONGOING_CALL_CHIP 128 }) 129 @Retention(RetentionPolicy.SOURCE) 130 public @interface DisableFlags {} 131 132 /** 133 * Flag to disable quick settings. 134 * 135 * Setting this flag disables quick settings completely, but does not disable expanding the 136 * notification shade. 137 */ 138 /** @hide */ 139 public static final int DISABLE2_QUICK_SETTINGS = 1; 140 /** @hide */ 141 public static final int DISABLE2_SYSTEM_ICONS = 1 << 1; 142 /** @hide */ 143 public static final int DISABLE2_NOTIFICATION_SHADE = 1 << 2; 144 /** @hide */ 145 public static final int DISABLE2_GLOBAL_ACTIONS = 1 << 3; 146 /** @hide */ 147 public static final int DISABLE2_ROTATE_SUGGESTIONS = 1 << 4; 148 149 /** @hide */ 150 public static final int DISABLE2_NONE = 0x00000000; 151 152 /** @hide */ 153 public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS | DISABLE2_SYSTEM_ICONS 154 | DISABLE2_NOTIFICATION_SHADE | DISABLE2_GLOBAL_ACTIONS | DISABLE2_ROTATE_SUGGESTIONS; 155 156 /** @hide */ 157 @IntDef(flag = true, prefix = { "DISABLE2_" }, value = { 158 DISABLE2_NONE, 159 DISABLE2_MASK, 160 DISABLE2_QUICK_SETTINGS, 161 DISABLE2_SYSTEM_ICONS, 162 DISABLE2_NOTIFICATION_SHADE, 163 DISABLE2_GLOBAL_ACTIONS, 164 DISABLE2_ROTATE_SUGGESTIONS 165 }) 166 @Retention(RetentionPolicy.SOURCE) 167 public @interface Disable2Flags {} 168 // LINT.ThenChange(frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt) 169 170 /** 171 * Default disable flags for setup 172 * 173 * @hide 174 */ 175 public static final int DEFAULT_SETUP_DISABLE_FLAGS = DISABLE_NOTIFICATION_ALERTS 176 | DISABLE_HOME | DISABLE_EXPAND | DISABLE_RECENT | DISABLE_CLOCK | DISABLE_SEARCH; 177 178 /** 179 * Default disable2 flags for setup 180 * 181 * @hide 182 */ 183 public static final int DEFAULT_SETUP_DISABLE2_FLAGS = DISABLE2_NONE; 184 185 /** 186 * disable flags to be applied when the device is sim-locked. 187 */ 188 private static final int DEFAULT_SIM_LOCKED_DISABLED_FLAGS = DISABLE_EXPAND; 189 190 /** @hide */ 191 public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0; 192 /** @hide */ 193 public static final int NAVIGATION_HINT_IME_SHOWN = 1 << 1; 194 /** @hide */ 195 public static final int NAVIGATION_HINT_IME_SWITCHER_SHOWN = 1 << 2; 196 197 /** @hide */ 198 public static final int WINDOW_STATUS_BAR = 1; 199 /** @hide */ 200 public static final int WINDOW_NAVIGATION_BAR = 2; 201 202 /** @hide */ 203 @IntDef(flag = true, prefix = { "WINDOW_" }, value = { 204 WINDOW_STATUS_BAR, 205 WINDOW_NAVIGATION_BAR 206 }) 207 @Retention(RetentionPolicy.SOURCE) 208 public @interface WindowType {} 209 210 /** @hide */ 211 public static final int WINDOW_STATE_SHOWING = 0; 212 /** @hide */ 213 public static final int WINDOW_STATE_HIDING = 1; 214 /** @hide */ 215 public static final int WINDOW_STATE_HIDDEN = 2; 216 217 /** @hide */ 218 @IntDef(flag = true, prefix = { "WINDOW_STATE_" }, value = { 219 WINDOW_STATE_SHOWING, 220 WINDOW_STATE_HIDING, 221 WINDOW_STATE_HIDDEN 222 }) 223 @Retention(RetentionPolicy.SOURCE) 224 public @interface WindowVisibleState {} 225 226 /** @hide */ 227 public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; 228 /** @hide */ 229 public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; 230 /** @hide */ 231 public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2; 232 /** @hide */ 233 public static final int CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE = 3; 234 235 /** 236 * Session flag for {@link #registerSessionListener} indicating the listener 237 * is interested in sessions on the keygaurd. 238 * Keyguard Session Boundaries: 239 * START_SESSION: device starts going to sleep OR the keyguard is newly shown 240 * END_SESSION: device starts going to sleep OR keyguard is no longer showing 241 * @hide 242 */ 243 public static final int SESSION_KEYGUARD = 1 << 0; 244 245 /** 246 * Session flag for {@link #registerSessionListener} indicating the current session 247 * is interested in session on the biometric prompt. 248 * @hide 249 */ 250 public static final int SESSION_BIOMETRIC_PROMPT = 1 << 1; 251 252 /** @hide */ 253 public static final Set<Integer> ALL_SESSIONS = Set.of( 254 SESSION_KEYGUARD, 255 SESSION_BIOMETRIC_PROMPT 256 ); 257 258 /** @hide */ 259 @Retention(RetentionPolicy.SOURCE) 260 @IntDef(flag = true, prefix = { "SESSION_KEYGUARD" }, value = { 261 SESSION_KEYGUARD, 262 SESSION_BIOMETRIC_PROMPT, 263 }) 264 public @interface SessionFlags {} 265 266 /** 267 * Response indicating that the tile was not added. 268 */ 269 public static final int TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED = 0; 270 /** 271 * Response indicating that the tile was already added and the user was not prompted. 272 */ 273 public static final int TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED = 1; 274 /** 275 * Response indicating that the tile was added. 276 */ 277 public static final int TILE_ADD_REQUEST_RESULT_TILE_ADDED = 2; 278 /** @hide */ 279 public static final int TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED = 3; 280 281 /** 282 * Values greater or equal to this value indicate an error in the request. 283 */ 284 private static final int TILE_ADD_REQUEST_FIRST_ERROR_CODE = 1000; 285 286 /** 287 * Indicates that this package does not match that of the 288 * {@link android.service.quicksettings.TileService}. 289 */ 290 public static final int TILE_ADD_REQUEST_ERROR_MISMATCHED_PACKAGE = 291 TILE_ADD_REQUEST_FIRST_ERROR_CODE; 292 /** 293 * Indicates that there's a request in progress for this package. 294 */ 295 public static final int TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS = 296 TILE_ADD_REQUEST_FIRST_ERROR_CODE + 1; 297 /** 298 * Indicates that the component does not match an enabled exported 299 * {@link android.service.quicksettings.TileService} for the current user. 300 */ 301 public static final int TILE_ADD_REQUEST_ERROR_BAD_COMPONENT = 302 TILE_ADD_REQUEST_FIRST_ERROR_CODE + 2; 303 /** 304 * Indicates that the user is not the current user. 305 */ 306 public static final int TILE_ADD_REQUEST_ERROR_NOT_CURRENT_USER = 307 TILE_ADD_REQUEST_FIRST_ERROR_CODE + 3; 308 /** 309 * Indicates that the requesting application is not in the foreground. 310 */ 311 public static final int TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND = 312 TILE_ADD_REQUEST_FIRST_ERROR_CODE + 4; 313 /** 314 * The request could not be processed because no fulfilling service was found. This could be 315 * a temporary issue (for example, SystemUI has crashed). 316 */ 317 public static final int TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE = 318 TILE_ADD_REQUEST_FIRST_ERROR_CODE + 5; 319 320 /** @hide */ 321 @IntDef(prefix = {"TILE_ADD_REQUEST"}, value = { 322 TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED, 323 TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED, 324 TILE_ADD_REQUEST_RESULT_TILE_ADDED, 325 TILE_ADD_REQUEST_ERROR_MISMATCHED_PACKAGE, 326 TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS, 327 TILE_ADD_REQUEST_ERROR_BAD_COMPONENT, 328 TILE_ADD_REQUEST_ERROR_NOT_CURRENT_USER, 329 TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND, 330 TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE 331 }) 332 @Retention(RetentionPolicy.SOURCE) 333 public @interface RequestResult {} 334 335 /** 336 * Constant for {@link #setNavBarMode(int)} indicating the default navbar mode. 337 * 338 * @hide 339 */ 340 @SystemApi 341 public static final int NAV_BAR_MODE_DEFAULT = 0; 342 343 /** 344 * Constant for {@link #setNavBarMode(int)} indicating kids navbar mode. 345 * 346 * <p>When used, back and home icons will change drawables and layout, recents will be hidden, 347 * and enables the setting to force navbar visible, even when apps are in immersive mode. 348 * 349 * @hide 350 */ 351 @SystemApi 352 public static final int NAV_BAR_MODE_KIDS = 1; 353 354 /** @hide */ 355 @IntDef(prefix = {"NAV_BAR_MODE_"}, value = { 356 NAV_BAR_MODE_DEFAULT, 357 NAV_BAR_MODE_KIDS 358 }) 359 @Retention(RetentionPolicy.SOURCE) 360 public @interface NavBarMode {} 361 362 /** 363 * State indicating that this sender device is close to a receiver device, so the user can 364 * potentially *start* a cast to the receiver device if the user moves their device a bit 365 * closer. 366 * <p> 367 * Important notes: 368 * <ul> 369 * <li>This state represents that the device is close enough to inform the user that 370 * transferring is an option, but the device is *not* close enough to actually initiate a 371 * transfer yet.</li> 372 * <li>This state is for *starting* a cast. It should be used when this device is currently 373 * playing media locally and the media should be transferred to be played on the receiver 374 * device instead.</li> 375 * </ul> 376 * 377 * @hide 378 */ 379 @SystemApi 380 public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST = 0; 381 382 /** 383 * State indicating that this sender device is close to a receiver device, so the user can 384 * potentially *end* a cast on the receiver device if the user moves this device a bit closer. 385 * <p> 386 * Important notes: 387 * <ul> 388 * <li>This state represents that the device is close enough to inform the user that 389 * transferring is an option, but the device is *not* close enough to actually initiate a 390 * transfer yet.</li> 391 * <li>This state is for *ending* a cast. It should be used when media is currently being 392 * played on the receiver device and the media should be transferred to play locally 393 * instead.</li> 394 * </ul> 395 * 396 * @hide 397 */ 398 @SystemApi 399 public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST = 1; 400 401 /** 402 * State indicating that a media transfer from this sender device to a receiver device has been 403 * started. 404 * <p> 405 * Important note: This state is for *starting* a cast. It should be used when this device is 406 * currently playing media locally and the media has started being transferred to the receiver 407 * device instead. 408 * 409 * @hide 410 */ 411 @SystemApi 412 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED = 2; 413 414 /** 415 * State indicating that a media transfer from the receiver and back to this sender device 416 * has been started. 417 * <p> 418 * Important note: This state is for *ending* a cast. It should be used when media is currently 419 * being played on the receiver device and the media has started being transferred to play 420 * locally instead. 421 * 422 * @hide 423 */ 424 @SystemApi 425 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED = 3; 426 427 /** 428 * State indicating that a media transfer from this sender device to a receiver device has 429 * finished successfully. 430 * <p> 431 * Important note: This state is for *starting* a cast. It should be used when this device had 432 * previously been playing media locally and the media has successfully been transferred to the 433 * receiver device instead. 434 * 435 * @hide 436 */ 437 @SystemApi 438 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED = 4; 439 440 /** 441 * State indicating that a media transfer from the receiver and back to this sender device has 442 * finished successfully. 443 * <p> 444 * Important note: This state is for *ending* a cast. It should be used when media was 445 * previously being played on the receiver device and has been successfully transferred to play 446 * locally on this device instead. 447 * 448 * @hide 449 */ 450 @SystemApi 451 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED = 5; 452 453 /** 454 * State indicating that the attempted transfer to the receiver device has failed. 455 * 456 * @hide 457 */ 458 @SystemApi 459 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED = 6; 460 461 /** 462 * State indicating that the attempted transfer back to this device has failed. 463 * 464 * @hide 465 */ 466 @SystemApi 467 public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED = 7; 468 469 /** 470 * State indicating that this sender device is no longer close to the receiver device. 471 * 472 * @hide 473 */ 474 @SystemApi 475 public static final int MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER = 8; 476 477 /** @hide */ 478 @IntDef(prefix = {"MEDIA_TRANSFER_SENDER_STATE_"}, value = { 479 MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST, 480 MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST, 481 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED, 482 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED, 483 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, 484 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, 485 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED, 486 MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED, 487 MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, 488 }) 489 @Retention(RetentionPolicy.SOURCE) 490 public @interface MediaTransferSenderState {} 491 492 /** 493 * State indicating that this receiver device is close to a sender device, so the user can 494 * potentially start or end a cast to the receiver device if the user moves the sender device a 495 * bit closer. 496 * <p> 497 * Important note: This state represents that the device is close enough to inform the user that 498 * transferring is an option, but the device is *not* close enough to actually initiate a 499 * transfer yet. 500 * 501 * @hide 502 */ 503 @SystemApi 504 public static final int MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER = 0; 505 506 /** 507 * State indicating that this receiver device is no longer close to the sender device. 508 * 509 * @hide 510 */ 511 @SystemApi 512 public static final int MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER = 1; 513 514 /** 515 * State indicating that media transfer to this receiver device is succeeded. 516 * 517 * @hide 518 */ 519 public static final int MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED = 2; 520 521 /** 522 * State indicating that media transfer to this receiver device is failed. 523 * 524 * @hide 525 */ 526 public static final int MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED = 3; 527 528 /** @hide */ 529 @IntDef(prefix = {"MEDIA_TRANSFER_RECEIVER_STATE_"}, value = { 530 MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, 531 MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER, 532 MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, 533 MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED, 534 }) 535 @Retention(RetentionPolicy.SOURCE) 536 public @interface MediaTransferReceiverState {} 537 538 /** 539 * A map from a provider registered in 540 * {@link #registerNearbyMediaDevicesProvider(NearbyMediaDevicesProvider)} to the wrapper 541 * around the provider that was created internally. We need the wrapper to make the provider 542 * binder-compatible, and we need to store a reference to the wrapper so that when the provider 543 * is un-registered, we un-register the saved wrapper instance. 544 */ 545 private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper> 546 nearbyMediaDevicesProviderMap = new HashMap<>(); 547 548 /** 549 * Media controls based on {@link android.app.Notification.MediaStyle} notifications will have 550 * actions based on the media session's {@link android.media.session.PlaybackState}, rather than 551 * the notification's actions. 552 * 553 * These actions will be: 554 * - Play/Pause (depending on whether the current state is a playing state) 555 * - Previous (if declared), or a custom action if the slot is not reserved with 556 * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV} 557 * - Next (if declared), or a custom action if the slot is not reserved with 558 * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT} 559 * - Custom action 560 * - Custom action 561 * 562 * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV 563 * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT 564 */ 565 @ChangeId 566 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) 567 private static final long MEDIA_CONTROL_SESSION_ACTIONS = 203800354L; 568 569 @UnsupportedAppUsage 570 private Context mContext; 571 private IStatusBarService mService; 572 @UnsupportedAppUsage 573 private IBinder mToken = new Binder(); 574 575 @UnsupportedAppUsage StatusBarManager(Context context)576 StatusBarManager(Context context) { 577 mContext = context; 578 } 579 580 @UnsupportedAppUsage getService()581 private synchronized IStatusBarService getService() { 582 if (mService == null) { 583 mService = IStatusBarService.Stub.asInterface( 584 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 585 if (mService == null) { 586 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); 587 } 588 } 589 return mService; 590 } 591 592 /** 593 * Disable some features in the status bar. Pass the bitwise-or of the DISABLE_* flags. 594 * To re-enable everything, pass {@link #DISABLE_NONE}. 595 * 596 * @hide 597 */ 598 @UnsupportedAppUsage disable(int what)599 public void disable(int what) { 600 try { 601 final int userId = Binder.getCallingUserHandle().getIdentifier(); 602 final IStatusBarService svc = getService(); 603 if (svc != null) { 604 svc.disableForUser(what, mToken, mContext.getPackageName(), userId); 605 } 606 } catch (RemoteException ex) { 607 throw ex.rethrowFromSystemServer(); 608 } 609 } 610 611 /** 612 * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. 613 * To re-enable everything, pass {@link #DISABLE_NONE}. 614 * 615 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 616 * 617 * @hide 618 */ disable2(@isable2Flags int what)619 public void disable2(@Disable2Flags int what) { 620 try { 621 final int userId = Binder.getCallingUserHandle().getIdentifier(); 622 final IStatusBarService svc = getService(); 623 if (svc != null) { 624 svc.disable2ForUser(what, mToken, mContext.getPackageName(), userId); 625 } 626 } catch (RemoteException ex) { 627 throw ex.rethrowFromSystemServer(); 628 } 629 } 630 631 /** 632 * Simulate notification click for testing 633 * 634 * @hide 635 */ 636 @TestApi clickNotification(@ullable String key, int rank, int count, boolean visible)637 public void clickNotification(@Nullable String key, int rank, int count, boolean visible) { 638 clickNotificationInternal(key, rank, count, visible); 639 } 640 clickNotificationInternal(String key, int rank, int count, boolean visible)641 private void clickNotificationInternal(String key, int rank, int count, boolean visible) { 642 try { 643 final IStatusBarService svc = getService(); 644 if (svc != null) { 645 svc.onNotificationClick(key, 646 NotificationVisibility.obtain(key, rank, count, visible)); 647 } 648 } catch (RemoteException ex) { 649 throw ex.rethrowFromSystemServer(); 650 } 651 } 652 653 /** 654 * Simulate notification feedback for testing 655 * 656 * @hide 657 */ 658 @TestApi sendNotificationFeedback(@ullable String key, @Nullable Bundle feedback)659 public void sendNotificationFeedback(@Nullable String key, @Nullable Bundle feedback) { 660 try { 661 final IStatusBarService svc = getService(); 662 if (svc != null) { 663 svc.onNotificationFeedbackReceived(key, feedback); 664 } 665 } catch (RemoteException ex) { 666 throw ex.rethrowFromSystemServer(); 667 } 668 } 669 670 /** 671 * Expand the notifications panel. 672 * 673 * @hide 674 */ 675 @UnsupportedAppUsage 676 @TestApi expandNotificationsPanel()677 public void expandNotificationsPanel() { 678 try { 679 final IStatusBarService svc = getService(); 680 if (svc != null) { 681 svc.expandNotificationsPanel(); 682 } 683 } catch (RemoteException ex) { 684 throw ex.rethrowFromSystemServer(); 685 } 686 } 687 688 /** 689 * Collapse the notifications and settings panels. 690 * 691 * Starting in Android {@link Build.VERSION_CODES.S}, apps targeting SDK level {@link 692 * Build.VERSION_CODES.S} or higher will need {@link android.Manifest.permission.STATUS_BAR} 693 * permission to call this API. 694 * 695 * @hide 696 */ 697 @RequiresPermission(android.Manifest.permission.STATUS_BAR) 698 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "This operation" 699 + " is not allowed anymore, please see {@link android.content" 700 + ".Intent#ACTION_CLOSE_SYSTEM_DIALOGS} for more details.") 701 @TestApi collapsePanels()702 public void collapsePanels() { 703 704 try { 705 final IStatusBarService svc = getService(); 706 if (svc != null) { 707 svc.collapsePanels(); 708 } 709 } catch (RemoteException ex) { 710 throw ex.rethrowFromSystemServer(); 711 } 712 } 713 714 /** 715 * Toggles the notification panel. 716 * 717 * @hide 718 */ 719 @RequiresPermission(android.Manifest.permission.STATUS_BAR) 720 @TestApi togglePanel()721 public void togglePanel() { 722 try { 723 final IStatusBarService svc = getService(); 724 if (svc != null) { 725 svc.togglePanel(); 726 } 727 } catch (RemoteException ex) { 728 throw ex.rethrowFromSystemServer(); 729 } 730 } 731 732 /** 733 * Sends system keys to the status bar. 734 * 735 * @hide 736 */ 737 @RequiresPermission(android.Manifest.permission.STATUS_BAR) 738 @TestApi handleSystemKey(int key)739 public void handleSystemKey(int key) { 740 try { 741 final IStatusBarService svc = getService(); 742 if (svc != null) { 743 svc.handleSystemKey(key); 744 } 745 } catch (RemoteException ex) { 746 throw ex.rethrowFromSystemServer(); 747 } 748 } 749 750 /** 751 * Expand the settings panel. 752 * 753 * @hide 754 */ 755 @UnsupportedAppUsage expandSettingsPanel()756 public void expandSettingsPanel() { 757 expandSettingsPanel(null); 758 } 759 760 /** 761 * Expand the settings panel and open a subPanel. If the subpanel is null or does not have a 762 * corresponding tile, the QS panel is simply expanded 763 * 764 * @hide 765 */ 766 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) expandSettingsPanel(@ullable String subPanel)767 public void expandSettingsPanel(@Nullable String subPanel) { 768 try { 769 final IStatusBarService svc = getService(); 770 if (svc != null) { 771 svc.expandSettingsPanel(subPanel); 772 } 773 } catch (RemoteException ex) { 774 throw ex.rethrowFromSystemServer(); 775 } 776 } 777 778 /** @hide */ 779 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setIcon(String slot, int iconId, int iconLevel, String contentDescription)780 public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) { 781 try { 782 final IStatusBarService svc = getService(); 783 if (svc != null) { 784 svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel, 785 contentDescription); 786 } 787 } catch (RemoteException ex) { 788 throw ex.rethrowFromSystemServer(); 789 } 790 } 791 792 /** @hide */ 793 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) removeIcon(String slot)794 public void removeIcon(String slot) { 795 try { 796 final IStatusBarService svc = getService(); 797 if (svc != null) { 798 svc.removeIcon(slot); 799 } 800 } catch (RemoteException ex) { 801 throw ex.rethrowFromSystemServer(); 802 } 803 } 804 805 /** @hide */ 806 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setIconVisibility(String slot, boolean visible)807 public void setIconVisibility(String slot, boolean visible) { 808 try { 809 final IStatusBarService svc = getService(); 810 if (svc != null) { 811 svc.setIconVisibility(slot, visible); 812 } 813 } catch (RemoteException ex) { 814 throw ex.rethrowFromSystemServer(); 815 } 816 } 817 818 /** 819 * Enable or disable status bar elements (notifications, clock) which are inappropriate during 820 * device setup. 821 * 822 * @param disabled whether to apply or remove the disabled flags 823 * 824 * @hide 825 */ 826 @SystemApi 827 @RequiresPermission(android.Manifest.permission.STATUS_BAR) setDisabledForSetup(boolean disabled)828 public void setDisabledForSetup(boolean disabled) { 829 try { 830 final int userId = Binder.getCallingUserHandle().getIdentifier(); 831 final IStatusBarService svc = getService(); 832 if (svc != null) { 833 svc.disableForUser(disabled ? DEFAULT_SETUP_DISABLE_FLAGS : DISABLE_NONE, 834 mToken, mContext.getPackageName(), userId); 835 svc.disable2ForUser(disabled ? DEFAULT_SETUP_DISABLE2_FLAGS : DISABLE2_NONE, 836 mToken, mContext.getPackageName(), userId); 837 } 838 } catch (RemoteException ex) { 839 throw ex.rethrowFromSystemServer(); 840 } 841 } 842 843 /** 844 * Enable or disable expansion of the status bar. When the device is SIM-locked, the status 845 * bar should not be expandable. 846 * 847 * @param disabled If {@code true}, the status bar will be set to non-expandable. If 848 * {@code false}, re-enables expansion of the status bar. 849 * @hide 850 */ 851 @TestApi 852 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 853 @RequiresPermission(android.Manifest.permission.STATUS_BAR) setExpansionDisabledForSimNetworkLock(boolean disabled)854 public void setExpansionDisabledForSimNetworkLock(boolean disabled) { 855 try { 856 final int userId = Binder.getCallingUserHandle().getIdentifier(); 857 final IStatusBarService svc = getService(); 858 if (svc != null) { 859 svc.disableForUser(disabled ? DEFAULT_SIM_LOCKED_DISABLED_FLAGS : DISABLE_NONE, 860 mToken, mContext.getPackageName(), userId); 861 } 862 } catch (RemoteException ex) { 863 throw ex.rethrowFromSystemServer(); 864 } 865 } 866 867 /** 868 * Get this app's currently requested disabled components 869 * 870 * @return a new DisableInfo 871 * 872 * @hide 873 */ 874 @SystemApi 875 @RequiresPermission(android.Manifest.permission.STATUS_BAR) 876 @NonNull getDisableInfo()877 public DisableInfo getDisableInfo() { 878 try { 879 final int userId = Binder.getCallingUserHandle().getIdentifier(); 880 final IStatusBarService svc = getService(); 881 int[] flags = new int[] {0, 0}; 882 if (svc != null) { 883 flags = svc.getDisableFlags(mToken, userId); 884 } 885 886 return new DisableInfo(flags[0], flags[1]); 887 } catch (RemoteException ex) { 888 throw ex.rethrowFromSystemServer(); 889 } 890 } 891 892 /** 893 * Sets an active {@link android.service.quicksettings.TileService} to listening state 894 * 895 * The {@code componentName}'s package must match the calling package. 896 * 897 * @param componentName the tile to set into listening state 898 * @see android.service.quicksettings.TileService#requestListeningState 899 * @hide 900 */ requestTileServiceListeningState(@onNull ComponentName componentName)901 public void requestTileServiceListeningState(@NonNull ComponentName componentName) { 902 Objects.requireNonNull(componentName); 903 try { 904 getService().requestTileServiceListeningState(componentName, mContext.getUserId()); 905 } catch (RemoteException ex) { 906 throw ex.rethrowFromSystemServer(); 907 } 908 } 909 910 /** 911 * Request to the user to add a {@link android.service.quicksettings.TileService} 912 * to the set of current QS tiles. 913 * <p> 914 * Calling this will prompt the user to decide whether they want to add the shown 915 * {@link android.service.quicksettings.TileService} to their current tiles. The user can 916 * deny the request and the system can stop processing requests for a given 917 * {@link ComponentName} after a number of requests. 918 * <p> 919 * The request will show to the user information about the tile: 920 * <ul> 921 * <li>Application name</li> 922 * <li>Label for the tile</li> 923 * <li>Icon for the tile</li> 924 * </ul> 925 * <p> 926 * The user for which this will be added is determined from the {@link Context} used to retrieve 927 * this service, and must match the current user. The requesting application must be in the 928 * foreground ({@link ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND} 929 * and the {@link android.service.quicksettings.TileService} must be exported. 930 * 931 * Note: the system can choose to auto-deny a request if the user has denied that specific 932 * request (user, ComponentName) enough times before. 933 * 934 * @param tileServiceComponentName {@link ComponentName} of the 935 * {@link android.service.quicksettings.TileService} for the request. 936 * @param tileLabel label of the tile to show to the user. 937 * @param icon icon to use in the tile shown to the user. 938 * @param resultExecutor an executor to run the callback on 939 * @param resultCallback callback to indicate the {@link RequestResult}. 940 * 941 * @see android.service.quicksettings.TileService 942 */ requestAddTileService( @onNull ComponentName tileServiceComponentName, @NonNull CharSequence tileLabel, @NonNull Icon icon, @NonNull Executor resultExecutor, @NonNull Consumer<Integer> resultCallback )943 public void requestAddTileService( 944 @NonNull ComponentName tileServiceComponentName, 945 @NonNull CharSequence tileLabel, 946 @NonNull Icon icon, 947 @NonNull Executor resultExecutor, 948 @NonNull Consumer<Integer> resultCallback 949 ) { 950 Objects.requireNonNull(tileServiceComponentName); 951 Objects.requireNonNull(tileLabel); 952 Objects.requireNonNull(icon); 953 Objects.requireNonNull(resultExecutor); 954 Objects.requireNonNull(resultCallback); 955 if (!tileServiceComponentName.getPackageName().equals(mContext.getPackageName())) { 956 resultExecutor.execute( 957 () -> resultCallback.accept(TILE_ADD_REQUEST_ERROR_MISMATCHED_PACKAGE)); 958 return; 959 } 960 int userId = mContext.getUserId(); 961 RequestResultCallback callbackProxy = new RequestResultCallback(resultExecutor, 962 resultCallback); 963 IStatusBarService svc = getService(); 964 try { 965 svc.requestAddTile( 966 tileServiceComponentName, 967 tileLabel, 968 icon, 969 userId, 970 callbackProxy 971 ); 972 } catch (RemoteException ex) { 973 ex.rethrowFromSystemServer(); 974 } 975 } 976 977 /** 978 * @hide 979 * @param packageName 980 */ 981 @TestApi cancelRequestAddTile(@onNull String packageName)982 public void cancelRequestAddTile(@NonNull String packageName) { 983 Objects.requireNonNull(packageName); 984 IStatusBarService svc = getService(); 985 try { 986 svc.cancelRequestAddTile(packageName); 987 } catch (RemoteException e) { 988 e.rethrowFromSystemServer(); 989 } 990 } 991 992 /** 993 * Sets or removes the navigation bar mode. 994 * 995 * @param navBarMode the mode of the navigation bar to be set. 996 * 997 * @hide 998 */ 999 @SystemApi 1000 @RequiresPermission(android.Manifest.permission.STATUS_BAR) setNavBarMode(@avBarMode int navBarMode)1001 public void setNavBarMode(@NavBarMode int navBarMode) { 1002 if (navBarMode != NAV_BAR_MODE_DEFAULT && navBarMode != NAV_BAR_MODE_KIDS) { 1003 throw new IllegalArgumentException("Supplied navBarMode not supported: " + navBarMode); 1004 } 1005 1006 try { 1007 final IStatusBarService svc = getService(); 1008 if (svc != null) { 1009 svc.setNavBarMode(navBarMode); 1010 } 1011 } catch (RemoteException e) { 1012 throw e.rethrowFromSystemServer(); 1013 } 1014 } 1015 1016 /** 1017 * Gets the navigation bar mode. Returns default value if no mode is set. 1018 * 1019 * @hide 1020 */ 1021 @SystemApi 1022 @RequiresPermission(android.Manifest.permission.STATUS_BAR) getNavBarMode()1023 public @NavBarMode int getNavBarMode() { 1024 int navBarMode = NAV_BAR_MODE_DEFAULT; 1025 try { 1026 final IStatusBarService svc = getService(); 1027 if (svc != null) { 1028 navBarMode = svc.getNavBarMode(); 1029 } 1030 } catch (RemoteException e) { 1031 throw e.rethrowFromSystemServer(); 1032 } 1033 return navBarMode; 1034 } 1035 1036 /** 1037 * Notifies the system of a new media tap-to-transfer state for the <b>sender</b> device. 1038 * 1039 * <p>The callback should only be provided for the {@link 1040 * MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED} or {@link 1041 * MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED} states, since those are the 1042 * only states where an action can be un-done. 1043 * 1044 * @param displayState the new state for media tap-to-transfer. 1045 * @param routeInfo the media route information for the media being transferred. 1046 * @param undoExecutor an executor to run the callback on and must be provided if the 1047 * callback is non-null. 1048 * @param undoCallback a callback that will be triggered if the user elects to undo a media 1049 * transfer. 1050 * 1051 * @throws IllegalArgumentException if an undo callback is provided for states that are not a 1052 * succeeded state. 1053 * @throws IllegalArgumentException if an executor is not provided when a callback is. 1054 * 1055 * @hide 1056 */ 1057 @SystemApi 1058 @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL) updateMediaTapToTransferSenderDisplay( @ediaTransferSenderState int displayState, @NonNull MediaRoute2Info routeInfo, @Nullable Executor undoExecutor, @Nullable Runnable undoCallback )1059 public void updateMediaTapToTransferSenderDisplay( 1060 @MediaTransferSenderState int displayState, 1061 @NonNull MediaRoute2Info routeInfo, 1062 @Nullable Executor undoExecutor, 1063 @Nullable Runnable undoCallback 1064 ) { 1065 Objects.requireNonNull(routeInfo); 1066 if (displayState != MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED 1067 && displayState != MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED 1068 && undoCallback != null) { 1069 throw new IllegalArgumentException( 1070 "The undoCallback should only be provided when the state is a " 1071 + "transfer succeeded state"); 1072 } 1073 if (undoCallback != null && undoExecutor == null) { 1074 throw new IllegalArgumentException( 1075 "You must pass an executor when you pass an undo callback"); 1076 } 1077 IStatusBarService svc = getService(); 1078 try { 1079 UndoCallback callbackProxy = null; 1080 if (undoExecutor != null) { 1081 callbackProxy = new UndoCallback(undoExecutor, undoCallback); 1082 } 1083 svc.updateMediaTapToTransferSenderDisplay(displayState, routeInfo, callbackProxy); 1084 } catch (RemoteException e) { 1085 e.rethrowFromSystemServer(); 1086 } 1087 } 1088 1089 /** 1090 * Notifies the system of a new media tap-to-transfer state for the <b>receiver</b> device. 1091 * 1092 * @param displayState the new state for media tap-to-transfer. 1093 * @param routeInfo the media route information for the media being transferred. 1094 * @param appIcon the icon of the app playing the media. 1095 * @param appName the name of the app playing the media. 1096 * 1097 * @hide 1098 */ 1099 @SystemApi 1100 @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL) updateMediaTapToTransferReceiverDisplay( @ediaTransferReceiverState int displayState, @NonNull MediaRoute2Info routeInfo, @Nullable Icon appIcon, @Nullable CharSequence appName)1101 public void updateMediaTapToTransferReceiverDisplay( 1102 @MediaTransferReceiverState int displayState, 1103 @NonNull MediaRoute2Info routeInfo, 1104 @Nullable Icon appIcon, 1105 @Nullable CharSequence appName) { 1106 Objects.requireNonNull(routeInfo); 1107 IStatusBarService svc = getService(); 1108 try { 1109 svc.updateMediaTapToTransferReceiverDisplay(displayState, routeInfo, appIcon, appName); 1110 } catch (RemoteException e) { 1111 e.rethrowFromSystemServer(); 1112 } 1113 } 1114 1115 /** 1116 * Registers a provider that notifies callbacks about the status of nearby devices that are able 1117 * to play media. 1118 * <p> 1119 * If multiple providers are registered, all the providers will be used for nearby device 1120 * information. 1121 * <p> 1122 * @param provider the nearby device information provider to register 1123 * <p> 1124 * @hide 1125 */ 1126 @SystemApi 1127 @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) registerNearbyMediaDevicesProvider( @onNull NearbyMediaDevicesProvider provider )1128 public void registerNearbyMediaDevicesProvider( 1129 @NonNull NearbyMediaDevicesProvider provider 1130 ) { 1131 Objects.requireNonNull(provider); 1132 if (nearbyMediaDevicesProviderMap.containsKey(provider)) { 1133 return; 1134 } 1135 try { 1136 final IStatusBarService svc = getService(); 1137 NearbyMediaDevicesProviderWrapper providerWrapper = 1138 new NearbyMediaDevicesProviderWrapper(provider); 1139 nearbyMediaDevicesProviderMap.put(provider, providerWrapper); 1140 svc.registerNearbyMediaDevicesProvider(providerWrapper); 1141 } catch (RemoteException e) { 1142 throw e.rethrowFromSystemServer(); 1143 } 1144 } 1145 1146 /** 1147 * Unregisters a provider that gives information about nearby devices that are able to play 1148 * media. 1149 * <p> 1150 * See {@link registerNearbyMediaDevicesProvider}. 1151 * <p> 1152 * @param provider the nearby device information provider to unregister 1153 * <p> 1154 * @hide 1155 */ 1156 @SystemApi 1157 @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) unregisterNearbyMediaDevicesProvider( @onNull NearbyMediaDevicesProvider provider )1158 public void unregisterNearbyMediaDevicesProvider( 1159 @NonNull NearbyMediaDevicesProvider provider 1160 ) { 1161 Objects.requireNonNull(provider); 1162 if (!nearbyMediaDevicesProviderMap.containsKey(provider)) { 1163 return; 1164 } 1165 try { 1166 final IStatusBarService svc = getService(); 1167 NearbyMediaDevicesProviderWrapper providerWrapper = 1168 nearbyMediaDevicesProviderMap.get(provider); 1169 nearbyMediaDevicesProviderMap.remove(provider); 1170 svc.unregisterNearbyMediaDevicesProvider(providerWrapper); 1171 } catch (RemoteException e) { 1172 throw e.rethrowFromSystemServer(); 1173 } 1174 } 1175 1176 /** 1177 * Checks whether the given package should use session-based actions for its media controls. 1178 * 1179 * @param packageName App posting media controls 1180 * @param user Current user handle 1181 * @return true if the app supports session actions 1182 * 1183 * @hide 1184 */ 1185 @RequiresPermission(allOf = {android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG, 1186 android.Manifest.permission.LOG_COMPAT_CHANGE}) useMediaSessionActionsForApp(String packageName, UserHandle user)1187 public static boolean useMediaSessionActionsForApp(String packageName, UserHandle user) { 1188 return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, user); 1189 } 1190 1191 /** @hide */ windowStateToString(int state)1192 public static String windowStateToString(int state) { 1193 if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; 1194 if (state == WINDOW_STATE_HIDDEN) return "WINDOW_STATE_HIDDEN"; 1195 if (state == WINDOW_STATE_SHOWING) return "WINDOW_STATE_SHOWING"; 1196 return "WINDOW_STATE_UNKNOWN"; 1197 } 1198 1199 /** 1200 * DisableInfo describes this app's requested state of the StatusBar with regards to which 1201 * components are enabled/disabled 1202 * 1203 * @hide 1204 */ 1205 @SystemApi 1206 public static final class DisableInfo { 1207 1208 private boolean mStatusBarExpansion; 1209 private boolean mNavigateHome; 1210 private boolean mNotificationPeeking; 1211 private boolean mRecents; 1212 private boolean mSearch; 1213 private boolean mSystemIcons; 1214 private boolean mClock; 1215 private boolean mNotificationIcons; 1216 private boolean mRotationSuggestion; 1217 1218 /** @hide */ DisableInfo(int flags1, int flags2)1219 public DisableInfo(int flags1, int flags2) { 1220 mStatusBarExpansion = (flags1 & DISABLE_EXPAND) != 0; 1221 mNavigateHome = (flags1 & DISABLE_HOME) != 0; 1222 mNotificationPeeking = (flags1 & DISABLE_NOTIFICATION_ALERTS) != 0; 1223 mRecents = (flags1 & DISABLE_RECENT) != 0; 1224 mSearch = (flags1 & DISABLE_SEARCH) != 0; 1225 mSystemIcons = (flags1 & DISABLE_SYSTEM_INFO) != 0; 1226 mClock = (flags1 & DISABLE_CLOCK) != 0; 1227 mNotificationIcons = (flags1 & DISABLE_NOTIFICATION_ICONS) != 0; 1228 mRotationSuggestion = (flags2 & DISABLE2_ROTATE_SUGGESTIONS) != 0; 1229 } 1230 1231 /** @hide */ DisableInfo()1232 public DisableInfo() {} 1233 1234 /** 1235 * @return {@code true} if expanding the notification shade is disabled 1236 * 1237 * @hide 1238 */ 1239 @SystemApi isStatusBarExpansionDisabled()1240 public boolean isStatusBarExpansionDisabled() { 1241 return mStatusBarExpansion; 1242 } 1243 1244 /** * @hide */ setStatusBarExpansionDisabled(boolean disabled)1245 public void setStatusBarExpansionDisabled(boolean disabled) { 1246 mStatusBarExpansion = disabled; 1247 } 1248 1249 /** 1250 * @return {@code true} if navigation home is disabled 1251 * 1252 * @hide 1253 */ 1254 @SystemApi isNavigateToHomeDisabled()1255 public boolean isNavigateToHomeDisabled() { 1256 return mNavigateHome; 1257 } 1258 1259 /** * @hide */ setNagivationHomeDisabled(boolean disabled)1260 public void setNagivationHomeDisabled(boolean disabled) { 1261 mNavigateHome = disabled; 1262 } 1263 1264 /** 1265 * @return {@code true} if notification peeking (heads-up notification) is disabled 1266 * 1267 * @hide 1268 */ 1269 @SystemApi isNotificationPeekingDisabled()1270 public boolean isNotificationPeekingDisabled() { 1271 return mNotificationPeeking; 1272 } 1273 1274 /** @hide */ setNotificationPeekingDisabled(boolean disabled)1275 public void setNotificationPeekingDisabled(boolean disabled) { 1276 mNotificationPeeking = disabled; 1277 } 1278 1279 /** 1280 * @return {@code true} if mRecents/overview is disabled 1281 * 1282 * @hide 1283 */ 1284 @SystemApi isRecentsDisabled()1285 public boolean isRecentsDisabled() { 1286 return mRecents; 1287 } 1288 1289 /** @hide */ setRecentsDisabled(boolean disabled)1290 public void setRecentsDisabled(boolean disabled) { 1291 mRecents = disabled; 1292 } 1293 1294 /** 1295 * @return {@code true} if mSearch is disabled 1296 * 1297 * @hide 1298 */ 1299 @SystemApi isSearchDisabled()1300 public boolean isSearchDisabled() { 1301 return mSearch; 1302 } 1303 1304 /** @hide */ setSearchDisabled(boolean disabled)1305 public void setSearchDisabled(boolean disabled) { 1306 mSearch = disabled; 1307 } 1308 1309 /** 1310 * @return {@code true} if system icons are disabled 1311 * 1312 * @hide 1313 */ areSystemIconsDisabled()1314 public boolean areSystemIconsDisabled() { 1315 return mSystemIcons; 1316 } 1317 1318 /** * @hide */ setSystemIconsDisabled(boolean disabled)1319 public void setSystemIconsDisabled(boolean disabled) { 1320 mSystemIcons = disabled; 1321 } 1322 1323 /** 1324 * @return {@code true} if the clock icon is disabled 1325 * 1326 * @hide 1327 */ isClockDisabled()1328 public boolean isClockDisabled() { 1329 return mClock; 1330 } 1331 1332 /** * @hide */ setClockDisabled(boolean disabled)1333 public void setClockDisabled(boolean disabled) { 1334 mClock = disabled; 1335 } 1336 1337 /** 1338 * @return {@code true} if notification icons are disabled 1339 * 1340 * @hide 1341 */ areNotificationIconsDisabled()1342 public boolean areNotificationIconsDisabled() { 1343 return mNotificationIcons; 1344 } 1345 1346 /** * @hide */ setNotificationIconsDisabled(boolean disabled)1347 public void setNotificationIconsDisabled(boolean disabled) { 1348 mNotificationIcons = disabled; 1349 } 1350 1351 /** 1352 * Returns whether the rotation suggestion is disabled. 1353 * 1354 * @hide 1355 */ 1356 @TestApi isRotationSuggestionDisabled()1357 public boolean isRotationSuggestionDisabled() { 1358 return mRotationSuggestion; 1359 } 1360 1361 /** 1362 * @return {@code true} if no components are disabled (default state) 1363 * @hide 1364 */ 1365 @SystemApi areAllComponentsEnabled()1366 public boolean areAllComponentsEnabled() { 1367 return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents 1368 && !mSearch && !mSystemIcons && !mClock && !mNotificationIcons 1369 && !mRotationSuggestion; 1370 } 1371 1372 /** @hide */ setEnableAll()1373 public void setEnableAll() { 1374 mStatusBarExpansion = false; 1375 mNavigateHome = false; 1376 mNotificationPeeking = false; 1377 mRecents = false; 1378 mSearch = false; 1379 mSystemIcons = false; 1380 mClock = false; 1381 mNotificationIcons = false; 1382 mRotationSuggestion = false; 1383 } 1384 1385 /** 1386 * @return {@code true} if all status bar components are disabled 1387 * 1388 * @hide 1389 */ areAllComponentsDisabled()1390 public boolean areAllComponentsDisabled() { 1391 return mStatusBarExpansion && mNavigateHome && mNotificationPeeking 1392 && mRecents && mSearch && mSystemIcons && mClock && mNotificationIcons 1393 && mRotationSuggestion; 1394 } 1395 1396 /** @hide */ setDisableAll()1397 public void setDisableAll() { 1398 mStatusBarExpansion = true; 1399 mNavigateHome = true; 1400 mNotificationPeeking = true; 1401 mRecents = true; 1402 mSearch = true; 1403 mSystemIcons = true; 1404 mClock = true; 1405 mNotificationIcons = true; 1406 mRotationSuggestion = true; 1407 } 1408 1409 @NonNull 1410 @Override toString()1411 public String toString() { 1412 StringBuilder sb = new StringBuilder(); 1413 sb.append("DisableInfo: "); 1414 sb.append(" mStatusBarExpansion=").append(mStatusBarExpansion ? "disabled" : "enabled"); 1415 sb.append(" mNavigateHome=").append(mNavigateHome ? "disabled" : "enabled"); 1416 sb.append(" mNotificationPeeking=") 1417 .append(mNotificationPeeking ? "disabled" : "enabled"); 1418 sb.append(" mRecents=").append(mRecents ? "disabled" : "enabled"); 1419 sb.append(" mSearch=").append(mSearch ? "disabled" : "enabled"); 1420 sb.append(" mSystemIcons=").append(mSystemIcons ? "disabled" : "enabled"); 1421 sb.append(" mClock=").append(mClock ? "disabled" : "enabled"); 1422 sb.append(" mNotificationIcons=").append(mNotificationIcons ? "disabled" : "enabled"); 1423 sb.append(" mRotationSuggestion=").append(mRotationSuggestion ? "disabled" : "enabled"); 1424 1425 return sb.toString(); 1426 1427 } 1428 1429 /** 1430 * Convert a DisableInfo to equivalent flags 1431 * @return a pair of equivalent disable flags 1432 * 1433 * @hide 1434 */ toFlags()1435 public Pair<Integer, Integer> toFlags() { 1436 int disable1 = DISABLE_NONE; 1437 int disable2 = DISABLE2_NONE; 1438 1439 if (mStatusBarExpansion) disable1 |= DISABLE_EXPAND; 1440 if (mNavigateHome) disable1 |= DISABLE_HOME; 1441 if (mNotificationPeeking) disable1 |= DISABLE_NOTIFICATION_ALERTS; 1442 if (mRecents) disable1 |= DISABLE_RECENT; 1443 if (mSearch) disable1 |= DISABLE_SEARCH; 1444 if (mSystemIcons) disable1 |= DISABLE_SYSTEM_INFO; 1445 if (mClock) disable1 |= DISABLE_CLOCK; 1446 if (mNotificationIcons) disable1 |= DISABLE_NOTIFICATION_ICONS; 1447 if (mRotationSuggestion) disable2 |= DISABLE2_ROTATE_SUGGESTIONS; 1448 1449 return new Pair<Integer, Integer>(disable1, disable2); 1450 } 1451 } 1452 1453 /** 1454 * @hide 1455 */ 1456 static final class RequestResultCallback extends IAddTileResultCallback.Stub { 1457 1458 @NonNull 1459 private final Executor mExecutor; 1460 @NonNull 1461 private final Consumer<Integer> mCallback; 1462 RequestResultCallback(@onNull Executor executor, @NonNull Consumer<Integer> callback)1463 RequestResultCallback(@NonNull Executor executor, @NonNull Consumer<Integer> callback) { 1464 mExecutor = executor; 1465 mCallback = callback; 1466 } 1467 1468 @Override onTileRequest(int userResponse)1469 public void onTileRequest(int userResponse) { 1470 mExecutor.execute(() -> mCallback.accept(userResponse)); 1471 } 1472 } 1473 1474 /** 1475 * @hide 1476 */ 1477 static final class UndoCallback extends IUndoMediaTransferCallback.Stub { 1478 @NonNull 1479 private final Executor mExecutor; 1480 @NonNull 1481 private final Runnable mCallback; 1482 UndoCallback(@onNull Executor executor, @NonNull Runnable callback)1483 UndoCallback(@NonNull Executor executor, @NonNull Runnable callback) { 1484 mExecutor = executor; 1485 mCallback = callback; 1486 } 1487 1488 @Override onUndoTriggered()1489 public void onUndoTriggered() { 1490 final long callingIdentity = Binder.clearCallingIdentity(); 1491 try { 1492 mExecutor.execute(mCallback); 1493 } finally { 1494 restoreCallingIdentity(callingIdentity); 1495 } 1496 } 1497 } 1498 1499 /** 1500 * @hide 1501 */ 1502 static final class NearbyMediaDevicesProviderWrapper extends INearbyMediaDevicesProvider.Stub { 1503 @NonNull 1504 private final NearbyMediaDevicesProvider mProvider; 1505 // Because we're wrapping a {@link NearbyMediaDevicesProvider} in a binder-compatible 1506 // interface, we also need to wrap the callbacks that the provider receives. We use 1507 // this map to keep track of the original callback and the wrapper callback so that 1508 // unregistering the callback works correctly. 1509 @NonNull 1510 private final Map<INearbyMediaDevicesUpdateCallback, Consumer<List<NearbyDevice>>> 1511 mRegisteredCallbacks = new HashMap<>(); 1512 NearbyMediaDevicesProviderWrapper(@onNull NearbyMediaDevicesProvider provider)1513 NearbyMediaDevicesProviderWrapper(@NonNull NearbyMediaDevicesProvider provider) { 1514 mProvider = provider; 1515 } 1516 1517 @Override registerNearbyDevicesCallback( @onNull INearbyMediaDevicesUpdateCallback callback)1518 public void registerNearbyDevicesCallback( 1519 @NonNull INearbyMediaDevicesUpdateCallback callback) { 1520 Consumer<List<NearbyDevice>> callbackAsConsumer = nearbyDevices -> { 1521 try { 1522 callback.onDevicesUpdated(nearbyDevices); 1523 } catch (RemoteException ex) { 1524 throw ex.rethrowFromSystemServer(); 1525 } 1526 }; 1527 1528 mRegisteredCallbacks.put(callback, callbackAsConsumer); 1529 mProvider.registerNearbyDevicesCallback(callbackAsConsumer); 1530 } 1531 1532 @Override unregisterNearbyDevicesCallback( @onNull INearbyMediaDevicesUpdateCallback callback)1533 public void unregisterNearbyDevicesCallback( 1534 @NonNull INearbyMediaDevicesUpdateCallback callback) { 1535 if (!mRegisteredCallbacks.containsKey(callback)) { 1536 return; 1537 } 1538 mProvider.unregisterNearbyDevicesCallback(mRegisteredCallbacks.get(callback)); 1539 mRegisteredCallbacks.remove(callback); 1540 } 1541 } 1542 } 1543