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 com.android.server.statusbar; 18 19 import static android.Manifest.permission.CONTROL_DEVICE_STATE; 20 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 21 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; 22 import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS; 23 import static android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE; 24 import static android.app.StatusBarManager.NAV_BAR_MODE_DEFAULT; 25 import static android.app.StatusBarManager.NAV_BAR_MODE_KIDS; 26 import static android.app.StatusBarManager.NavBarMode; 27 import static android.app.StatusBarManager.SessionFlags; 28 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 29 import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; 30 import static android.os.UserHandle.USER_SYSTEM; 31 import static android.os.UserHandle.getCallingUserId; 32 import static android.os.UserManager.isVisibleBackgroundUsersEnabled; 33 import static android.view.Display.DEFAULT_DISPLAY; 34 import static android.view.ViewRootImpl.CLIENT_TRANSIENT; 35 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; 36 37 import android.Manifest; 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.annotation.RequiresPermission; 41 import android.annotation.TestApi; 42 import android.app.ActivityManager; 43 import android.app.ActivityManagerInternal; 44 import android.app.ActivityThread; 45 import android.app.ITransientNotificationCallback; 46 import android.app.Notification; 47 import android.app.StatusBarManager; 48 import android.app.compat.CompatChanges; 49 import android.compat.annotation.ChangeId; 50 import android.compat.annotation.EnabledAfter; 51 import android.compat.annotation.EnabledSince; 52 import android.content.ComponentName; 53 import android.content.Context; 54 import android.content.Intent; 55 import android.content.om.IOverlayManager; 56 import android.content.pm.PackageManager; 57 import android.content.pm.PackageManagerInternal; 58 import android.content.pm.ResolveInfo; 59 import android.graphics.drawable.Icon; 60 import android.hardware.biometrics.BiometricAuthenticator.Modality; 61 import android.hardware.biometrics.IBiometricContextListener; 62 import android.hardware.biometrics.IBiometricSysuiReceiver; 63 import android.hardware.biometrics.PromptInfo; 64 import android.hardware.display.DisplayManager; 65 import android.hardware.display.DisplayManager.DisplayListener; 66 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; 67 import android.inputmethodservice.InputMethodService.BackDispositionMode; 68 import android.inputmethodservice.InputMethodService.ImeWindowVisibility; 69 import android.media.INearbyMediaDevicesProvider; 70 import android.media.MediaRoute2Info; 71 import android.net.Uri; 72 import android.os.Binder; 73 import android.os.Build; 74 import android.os.Bundle; 75 import android.os.Handler; 76 import android.os.IBinder; 77 import android.os.PowerManager; 78 import android.os.Process; 79 import android.os.RemoteException; 80 import android.os.ResultReceiver; 81 import android.os.ServiceManager; 82 import android.os.ShellCallback; 83 import android.os.UserHandle; 84 import android.provider.Settings; 85 import android.service.notification.NotificationStats; 86 import android.service.quicksettings.TileService; 87 import android.text.TextUtils; 88 import android.util.ArrayMap; 89 import android.util.IndentingPrintWriter; 90 import android.util.IntArray; 91 import android.util.Pair; 92 import android.util.Slog; 93 import android.util.SparseArray; 94 import android.view.KeyEvent; 95 import android.view.WindowInsets; 96 import android.view.WindowInsets.Type.InsetsType; 97 import android.view.WindowInsetsController.Appearance; 98 import android.view.WindowInsetsController.Behavior; 99 100 import com.android.internal.R; 101 import com.android.internal.annotations.GuardedBy; 102 import com.android.internal.annotations.VisibleForTesting; 103 import com.android.internal.inputmethod.SoftInputShowHideReason; 104 import com.android.internal.logging.InstanceId; 105 import com.android.internal.os.TransferPipe; 106 import com.android.internal.statusbar.DisableStates; 107 import com.android.internal.statusbar.IAddTileResultCallback; 108 import com.android.internal.statusbar.ISessionListener; 109 import com.android.internal.statusbar.IStatusBar; 110 import com.android.internal.statusbar.IStatusBarService; 111 import com.android.internal.statusbar.IUndoMediaTransferCallback; 112 import com.android.internal.statusbar.LetterboxDetails; 113 import com.android.internal.statusbar.NotificationVisibility; 114 import com.android.internal.statusbar.RegisterStatusBarResult; 115 import com.android.internal.statusbar.StatusBarIcon; 116 import com.android.internal.util.DumpUtils; 117 import com.android.internal.util.GcUtils; 118 import com.android.internal.view.AppearanceRegion; 119 import com.android.server.LocalServices; 120 import com.android.server.UiThread; 121 import com.android.server.inputmethod.InputMethodManagerInternal; 122 import com.android.server.notification.NotificationDelegate; 123 import com.android.server.pm.UserManagerInternal; 124 import com.android.server.pm.UserManagerService; 125 import com.android.server.policy.GlobalActionsProvider; 126 import com.android.server.power.ShutdownCheckPoints; 127 import com.android.server.power.ShutdownThread; 128 import com.android.server.wm.ActivityTaskManagerInternal; 129 import com.android.systemui.shared.Flags; 130 131 import java.io.FileDescriptor; 132 import java.io.PrintWriter; 133 import java.util.ArrayList; 134 import java.util.HashMap; 135 import java.util.Map; 136 import java.util.concurrent.TimeUnit; 137 138 /** 139 * A note on locking: We rely on the fact that calls onto mBar are oneway or 140 * if they are local, that they just enqueue messages to not deadlock. 141 */ 142 public class StatusBarManagerService extends IStatusBarService.Stub implements DisplayListener { 143 private static final String TAG = "StatusBarManagerService"; 144 private static final boolean SPEW = false; 145 146 /** 147 * Apps targeting {@code Build.VERSION_CODES.S} or higher need {@link 148 * android.Manifest.permission#STATUS_BAR} permission to collapse the status bar panels due to 149 * security reasons. 150 * 151 * This was being exploited by malware to prevent the user from accessing critical 152 * notifications. 153 */ 154 @ChangeId 155 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) 156 private static final long LOCK_DOWN_COLLAPSE_STATUS_BAR = 173031413L; 157 158 /** 159 * In apps targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher, calling 160 * {@link android.service.quicksettings.TileService#requestListeningState} will check that the 161 * calling package (uid) and the package of the target {@link android.content.ComponentName} 162 * match. It'll also make sure that the context used can take actions on behalf of the current 163 * user. 164 */ 165 @ChangeId 166 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) 167 static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L; 168 169 /** 170 * @hide 171 */ 172 @ChangeId 173 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) 174 static final long REQUEST_LISTENING_OTHER_USER_NOOP = 242194868L; 175 176 private final Context mContext; 177 178 private final Handler mHandler = new Handler(); 179 private NotificationDelegate mNotificationDelegate; 180 private volatile IStatusBar mBar; 181 private final ArrayMap<String, StatusBarIcon> mIcons = new ArrayMap<>(); 182 183 // for disabling the status bar 184 private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); 185 private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener; 186 private final IBinder mSysUiVisToken = new Binder(); 187 188 private final Object mLock = new Object(); 189 private final DeathRecipient mDeathRecipient = new DeathRecipient(); 190 private final ActivityManagerInternal mActivityManagerInternal; 191 private final ActivityTaskManagerInternal mActivityTaskManager; 192 private final PackageManagerInternal mPackageManagerInternal; 193 private final UserManagerInternal mUserManagerInternal; 194 private final SessionMonitor mSessionMonitor; 195 private int mCurrentUserId; 196 private boolean mTracingEnabled; 197 private int mLastSystemKey = -1; 198 199 private final TileRequestTracker mTileRequestTracker; 200 201 private final SparseArray<UiState> mDisplayUiState = new SparseArray<>(); 202 @GuardedBy("mLock") 203 private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback; 204 @GuardedBy("mLock") 205 private IBiometricContextListener mBiometricContextListener; 206 207 @GuardedBy("mCurrentRequestAddTilePackages") 208 private final ArrayMap<String, Long> mCurrentRequestAddTilePackages = new ArrayMap<>(); 209 private static final long REQUEST_TIME_OUT = TimeUnit.MINUTES.toNanos(5); 210 211 private IOverlayManager mOverlayManager; 212 213 private final boolean mVisibleBackgroundUsersEnabled; 214 private final UserManagerService mUserManager; 215 216 private class DeathRecipient implements IBinder.DeathRecipient { binderDied()217 public void binderDied() { 218 mBar.asBinder().unlinkToDeath(this,0); 219 mBar = null; 220 notifyBarAttachChanged(); 221 } 222 linkToDeath()223 public void linkToDeath() { 224 try { 225 mBar.asBinder().linkToDeath(mDeathRecipient,0); 226 } catch (RemoteException e) { 227 Slog.e(TAG,"Unable to register Death Recipient for status bar", e); 228 } 229 } 230 231 } 232 233 private class DisableRecord implements IBinder.DeathRecipient { 234 int userId; 235 String pkg; 236 int what1; 237 int what2; 238 IBinder token; 239 DisableRecord(int userId, IBinder token)240 public DisableRecord(int userId, IBinder token) { 241 this.userId = userId; 242 this.token = token; 243 try { 244 token.linkToDeath(this, 0); 245 } catch (RemoteException re) { 246 // Give up 247 } 248 } 249 250 @Override binderDied()251 public void binderDied() { 252 Slog.i(TAG, "binder died for pkg=" + pkg); 253 disableForUser(0, token, pkg, userId); 254 disable2ForUser(0, token, pkg, userId); 255 token.unlinkToDeath(this, 0); 256 } 257 setFlags(int what, int which, String pkg)258 public void setFlags(int what, int which, String pkg) { 259 switch (which) { 260 case 1: 261 what1 = what; 262 break; 263 case 2: 264 what2 = what; 265 break; 266 default: 267 Slog.w(TAG, "Can't set unsupported disable flag " + which 268 + ": 0x" + Integer.toHexString(what)); 269 break; 270 } 271 this.pkg = pkg; 272 } 273 getFlags(int which)274 public int getFlags(int which) { 275 switch (which) { 276 case 1: return what1; 277 case 2: return what2; 278 default: 279 Slog.w(TAG, "Can't get unsupported disable flag " + which); 280 return 0; 281 } 282 } 283 isEmpty()284 public boolean isEmpty() { 285 return what1 == 0 && what2 == 0; 286 } 287 288 @Override toString()289 public String toString() { 290 return String.format("userId=%d what1=0x%08X what2=0x%08X pkg=%s token=%s", 291 userId, what1, what2, pkg, token); 292 } 293 } 294 295 /** 296 * Construct the service 297 */ StatusBarManagerService(Context context)298 public StatusBarManagerService(Context context) { 299 mContext = context; 300 301 LocalServices.addService(StatusBarManagerInternal.class, mInternalService); 302 303 // We always have a default display. 304 final UiState state = new UiState(); 305 mDisplayUiState.put(DEFAULT_DISPLAY, state); 306 307 final DisplayManager displayManager = 308 (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 309 displayManager.registerDisplayListener(this, mHandler); 310 mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class); 311 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 312 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 313 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); 314 315 mTileRequestTracker = new TileRequestTracker(mContext); 316 mSessionMonitor = new SessionMonitor(mContext); 317 318 mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled(); 319 mUserManager = UserManagerService.getInstance(); 320 } 321 322 /** 323 * Publish the {@link GlobalActionsProvider}. 324 */ 325 // TODO(b/259420401): investigate if we can extract GlobalActionsProvider to its own system 326 // service. publishGlobalActionsProvider()327 public void publishGlobalActionsProvider() { 328 if (LocalServices.getService(GlobalActionsProvider.class) == null) { 329 LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider); 330 } 331 } 332 getOverlayManager()333 private IOverlayManager getOverlayManager() { 334 // No need to synchronize; worst-case scenario it will be fetched twice. 335 if (mOverlayManager == null) { 336 mOverlayManager = IOverlayManager.Stub.asInterface( 337 ServiceManager.getService(Context.OVERLAY_SERVICE)); 338 if (mOverlayManager == null) { 339 Slog.w("StatusBarManager", "warning: no OVERLAY_SERVICE"); 340 } 341 } 342 return mOverlayManager; 343 } 344 345 @Override onDisplayAdded(int displayId)346 public void onDisplayAdded(int displayId) { 347 synchronized (mLock) { 348 mDisplayUiState.put(displayId, new UiState()); 349 } 350 } 351 352 @Override onDisplayRemoved(int displayId)353 public void onDisplayRemoved(int displayId) { 354 synchronized (mLock) { 355 mDisplayUiState.remove(displayId); 356 } 357 } 358 359 @Override onDisplayChanged(int displayId)360 public void onDisplayChanged(int displayId) {} 361 362 /** 363 * Private API used by NotificationManagerService and other system services. 364 */ 365 private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { 366 @Override 367 public void setNotificationDelegate(NotificationDelegate delegate) { 368 mNotificationDelegate = delegate; 369 } 370 371 @Override 372 public void showScreenPinningRequest(int taskId, int userId) { 373 if (isVisibleBackgroundUser(userId)) { 374 if (SPEW) { 375 Slog.d(TAG, "Skipping showScreenPinningRequest for visible background user " 376 + userId); 377 } 378 return; 379 } 380 IStatusBar bar = mBar; 381 if (bar != null) { 382 try { 383 bar.showScreenPinningRequest(taskId); 384 } catch (RemoteException e) { 385 } 386 } 387 } 388 389 @Override 390 public void showAssistDisclosure() { 391 IStatusBar bar = mBar; 392 if (bar != null) { 393 try { 394 bar.showAssistDisclosure(); 395 } catch (RemoteException e) { 396 } 397 } 398 } 399 400 @Override 401 public void startAssist(Bundle args) { 402 IStatusBar bar = mBar; 403 if (bar != null) { 404 try { 405 bar.startAssist(args); 406 } catch (RemoteException e) { 407 } 408 } 409 } 410 411 @Override 412 public void onCameraLaunchGestureDetected(int source) { 413 IStatusBar bar = mBar; 414 if (bar != null) { 415 try { 416 bar.onCameraLaunchGestureDetected(source); 417 } catch (RemoteException e) { 418 } 419 } 420 } 421 422 @Override 423 public void onWalletLaunchGestureDetected() { 424 IStatusBar bar = mBar; 425 if (bar != null) { 426 try { 427 bar.onWalletLaunchGestureDetected(); 428 } catch (RemoteException e) { 429 } 430 } 431 } 432 433 /** 434 * Notifies the status bar that a Emergency Action launch gesture has been detected. 435 * 436 * TODO (b/169175022) Update method name and docs when feature name is locked. 437 */ 438 @Override 439 public void onEmergencyActionLaunchGestureDetected() { 440 if (SPEW) Slog.d(TAG, "Launching emergency action"); 441 IStatusBar bar = mBar; 442 if (bar != null) { 443 try { 444 bar.onEmergencyActionLaunchGestureDetected(); 445 } catch (RemoteException e) { 446 if (SPEW) Slog.d(TAG, "Failed to launch emergency action"); 447 } 448 } 449 } 450 451 @Override 452 public void setDisableFlags(int displayId, int flags, String cause) { 453 StatusBarManagerService.this.setDisableFlags(displayId, flags, cause); 454 } 455 456 @Override 457 public void toggleSplitScreen() { 458 enforceStatusBarService(); 459 IStatusBar bar = mBar; 460 if (bar != null) { 461 try { 462 bar.toggleSplitScreen(); 463 } catch (RemoteException ex) {} 464 } 465 } 466 467 @Override 468 public void appTransitionFinished(int displayId) { 469 if (isVisibleBackgroundUserOnDisplay(displayId)) { 470 if (SPEW) { 471 Slog.d(TAG, "Skipping appTransitionFinished for visible background user " 472 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 473 } 474 return; 475 } 476 enforceStatusBarService(); 477 IStatusBar bar = mBar; 478 if (bar != null) { 479 try { 480 bar.appTransitionFinished(displayId); 481 } catch (RemoteException ex) {} 482 } 483 } 484 485 @Override 486 public void toggleTaskbar() { 487 IStatusBar bar = mBar; 488 if (bar != null) { 489 try { 490 bar.toggleTaskbar(); 491 } catch (RemoteException ex) {} 492 } 493 } 494 495 @Override 496 public void toggleRecentApps() { 497 IStatusBar bar = mBar; 498 if (bar != null) { 499 try { 500 bar.toggleRecentApps(); 501 } catch (RemoteException ex) {} 502 } 503 } 504 505 @Override 506 public void setCurrentUser(int newUserId) { 507 if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId); 508 mCurrentUserId = newUserId; 509 } 510 511 512 @Override 513 public void preloadRecentApps() { 514 IStatusBar bar = mBar; 515 if (bar != null) { 516 try { 517 bar.preloadRecentApps(); 518 } catch (RemoteException ex) {} 519 } 520 } 521 522 @Override 523 public void cancelPreloadRecentApps() { 524 IStatusBar bar = mBar; 525 if (bar != null) { 526 try { 527 bar.cancelPreloadRecentApps(); 528 } catch (RemoteException ex) {} 529 } 530 } 531 532 @Override 533 public void showRecentApps(boolean triggeredFromAltTab) { 534 IStatusBar bar = mBar; 535 if (bar != null) { 536 try { 537 bar.showRecentApps(triggeredFromAltTab); 538 } catch (RemoteException ex) {} 539 } 540 } 541 542 @Override 543 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 544 IStatusBar bar = mBar; 545 if (bar != null) { 546 try { 547 bar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey); 548 } catch (RemoteException ex) {} 549 } 550 } 551 552 @Override 553 public void collapsePanels() { 554 IStatusBar bar = mBar; 555 if (bar != null) { 556 try { 557 bar.animateCollapsePanels(); 558 } catch (RemoteException ex) { 559 } 560 } 561 } 562 563 @Override 564 public void dismissKeyboardShortcutsMenu() { 565 IStatusBar bar = mBar; 566 if (bar != null) { 567 try { 568 bar.dismissKeyboardShortcutsMenu(); 569 } catch (RemoteException ex) {} 570 } 571 } 572 573 @Override 574 public void toggleKeyboardShortcutsMenu(int deviceId) { 575 IStatusBar bar = mBar; 576 if (bar != null) { 577 try { 578 bar.toggleKeyboardShortcutsMenu(deviceId); 579 } catch (RemoteException ex) {} 580 } 581 } 582 583 @Override 584 public void setImeWindowStatus(int displayId, @ImeWindowVisibility int vis, 585 @BackDispositionMode int backDisposition, boolean showImeSwitcher) { 586 StatusBarManagerService.this.setImeWindowStatus(displayId, vis, backDisposition, 587 showImeSwitcher); 588 } 589 590 @Override 591 public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, 592 String contentDescription) { 593 StatusBarManagerService.this.setIcon(slot, iconPackage, iconId, iconLevel, 594 contentDescription); 595 } 596 597 @Override 598 public void setIconVisibility(String slot, boolean visibility) { 599 StatusBarManagerService.this.setIconVisibility(slot, visibility); 600 } 601 602 @Override 603 public void showChargingAnimation(int batteryLevel) { 604 IStatusBar bar = mBar; 605 if (bar != null) { 606 try { 607 bar.showWirelessChargingAnimation(batteryLevel); 608 } catch (RemoteException ex){ 609 } 610 } 611 } 612 613 @Override 614 public void showPictureInPictureMenu() { 615 IStatusBar bar = mBar; 616 if (bar != null) { 617 try { 618 mBar.showPictureInPictureMenu(); 619 } catch (RemoteException ex) {} 620 } 621 } 622 623 @Override 624 public void setWindowState(int displayId, int window, int state) { 625 if (isVisibleBackgroundUserOnDisplay(displayId)) { 626 if (SPEW) { 627 Slog.d(TAG, "Skipping setWindowState for visible background user " 628 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 629 } 630 return; 631 } 632 IStatusBar bar = mBar; 633 if (bar != null) { 634 try { 635 bar.setWindowState(displayId, window, state); 636 } catch (RemoteException ex) {} 637 } 638 } 639 640 @Override 641 public void appTransitionPending(int displayId) { 642 if (isVisibleBackgroundUserOnDisplay(displayId)) { 643 if (SPEW) { 644 Slog.d(TAG, "Skipping appTransitionPending for visible background user " 645 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 646 } 647 return; 648 } 649 IStatusBar bar = mBar; 650 if (bar != null) { 651 try { 652 bar.appTransitionPending(displayId); 653 } catch (RemoteException ex) {} 654 } 655 } 656 657 @Override 658 public void appTransitionCancelled(int displayId) { 659 if (isVisibleBackgroundUserOnDisplay(displayId)) { 660 if (SPEW) { 661 Slog.d(TAG, "Skipping appTransitionCancelled for visible background user " 662 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 663 } 664 return; 665 } 666 IStatusBar bar = mBar; 667 if (bar != null) { 668 try { 669 bar.appTransitionCancelled(displayId); 670 } catch (RemoteException ex) {} 671 } 672 } 673 674 @Override 675 public void appTransitionStarting(int displayId, long statusBarAnimationsStartTime, 676 long statusBarAnimationsDuration) { 677 if (isVisibleBackgroundUserOnDisplay(displayId)) { 678 if (SPEW) { 679 Slog.d(TAG, "Skipping appTransitionStarting for visible background user " 680 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 681 } 682 return; 683 } 684 IStatusBar bar = mBar; 685 if (bar != null) { 686 try { 687 bar.appTransitionStarting( 688 displayId, statusBarAnimationsStartTime, statusBarAnimationsDuration); 689 } catch (RemoteException ex) {} 690 } 691 } 692 693 @Override 694 public void setTopAppHidesStatusBar(int displayId, boolean hidesStatusBar) { 695 if (isVisibleBackgroundUserOnDisplay(displayId)) { 696 if (SPEW) { 697 Slog.d(TAG, "Skipping setTopAppHidesStatusBar for visible background user " 698 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 699 } 700 return; 701 } 702 IStatusBar bar = mBar; 703 if (bar != null) { 704 try { 705 bar.setTopAppHidesStatusBar(hidesStatusBar); 706 } catch (RemoteException ex) {} 707 } 708 } 709 710 @Override 711 public boolean showShutdownUi(boolean isReboot, String reason) { 712 if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) { 713 return false; 714 } 715 IStatusBar bar = mBar; 716 if (bar != null) { 717 try { 718 bar.showShutdownUi(isReboot, reason); 719 return true; 720 } catch (RemoteException ex) {} 721 } 722 return false; 723 } 724 725 @Override 726 public void confirmImmersivePrompt() { 727 if (mBar == null) { 728 return; 729 } 730 try { 731 mBar.confirmImmersivePrompt(); 732 } catch (RemoteException ex) { 733 } 734 } 735 736 @Override 737 public void immersiveModeChanged(int displayId, int rootDisplayAreaId, 738 boolean isImmersiveMode, int windowType) { 739 if (mBar == null) { 740 return; 741 } 742 if (isVisibleBackgroundUserOnDisplay(displayId)) { 743 if (SPEW) { 744 Slog.d(TAG, "Skipping immersiveModeChanged for visible background user " 745 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 746 } 747 return; 748 } 749 if (!CLIENT_TRANSIENT) { 750 // Only call from here when the client transient is not enabled. 751 try { 752 mBar.immersiveModeChanged(rootDisplayAreaId, isImmersiveMode, windowType); 753 } catch (RemoteException ex) { 754 } 755 } 756 } 757 758 // TODO(b/118592525): support it per display if necessary. 759 @Override 760 public void onProposedRotationChanged(int displayId, int rotation, boolean isValid) { 761 if (isVisibleBackgroundUserOnDisplay(displayId)) { 762 if (SPEW) { 763 Slog.d(TAG, "Skipping onProposedRotationChanged for visible background user " 764 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 765 } 766 return; 767 } 768 if (mBar != null){ 769 try { 770 mBar.onProposedRotationChanged(rotation, isValid); 771 } catch (RemoteException ex) {} 772 } 773 } 774 775 @Override 776 public void onDisplayAddSystemDecorations(int displayId) { 777 if (isVisibleBackgroundUserOnDisplay(displayId)) { 778 if (SPEW) { 779 Slog.d(TAG, "Skipping onDisplayAddSystemDecorations for visible background " 780 + "user " 781 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 782 } 783 return; 784 } 785 IStatusBar bar = mBar; 786 if (bar != null) { 787 try { 788 bar.onDisplayAddSystemDecorations(displayId); 789 } catch (RemoteException ex) {} 790 } 791 } 792 793 @Override 794 public void onDisplayRemoveSystemDecorations(int displayId) { 795 if (isVisibleBackgroundUserOnDisplay(displayId)) { 796 if (SPEW) { 797 Slog.d(TAG, 798 "Skipping onDisplayRemoveSystemDecorations for visible background " 799 + "user " 800 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 801 } 802 return; 803 } 804 805 IStatusBar bar = mBar; 806 if (bar != null) { 807 try { 808 bar.onDisplayRemoveSystemDecorations(displayId); 809 } catch (RemoteException ex) {} 810 } 811 } 812 813 @Override 814 public void onSystemBarAttributesChanged(int displayId, @Appearance int appearance, 815 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, 816 @Behavior int behavior, @InsetsType int requestedVisibleTypes, 817 String packageName, LetterboxDetails[] letterboxDetails) { 818 if (isVisibleBackgroundUserOnDisplay(displayId)) { 819 if (SPEW) { 820 Slog.d(TAG, "Skipping onSystemBarAttributesChanged for visible background user " 821 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 822 } 823 return; 824 } 825 getUiState(displayId).setBarAttributes(appearance, appearanceRegions, 826 navbarColorManagedByIme, behavior, requestedVisibleTypes, packageName, 827 letterboxDetails); 828 IStatusBar bar = mBar; 829 if (bar != null) { 830 try { 831 bar.onSystemBarAttributesChanged(displayId, appearance, appearanceRegions, 832 navbarColorManagedByIme, behavior, requestedVisibleTypes, packageName, 833 letterboxDetails); 834 } catch (RemoteException ex) { } 835 } 836 } 837 838 @Override 839 public void showTransient(int displayId, @InsetsType int types, 840 boolean isGestureOnSystemBar) { 841 if (isVisibleBackgroundUserOnDisplay(displayId)) { 842 if (SPEW) { 843 Slog.d(TAG, "Skipping showTransient for visible background user " 844 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 845 } 846 return; 847 } 848 getUiState(displayId).showTransient(types); 849 IStatusBar bar = mBar; 850 if (bar != null) { 851 try { 852 bar.showTransient(displayId, types, isGestureOnSystemBar); 853 } catch (RemoteException ex) { } 854 } 855 } 856 857 @Override 858 public void abortTransient(int displayId, @InsetsType int types) { 859 if (isVisibleBackgroundUserOnDisplay(displayId)) { 860 if (SPEW) { 861 Slog.d(TAG, "Skipping abortTransient for visible background user " 862 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 863 } 864 return; 865 } 866 getUiState(displayId).clearTransient(types); 867 IStatusBar bar = mBar; 868 if (bar != null) { 869 try { 870 bar.abortTransient(displayId, types); 871 } catch (RemoteException ex) { } 872 } 873 } 874 875 @Override 876 public void showToast(int uid, String packageName, IBinder token, CharSequence text, 877 IBinder windowToken, int duration, 878 @Nullable ITransientNotificationCallback callback, int displayId) { 879 IStatusBar bar = mBar; 880 if (bar != null) { 881 try { 882 bar.showToast(uid, packageName, token, text, windowToken, duration, callback, 883 displayId); 884 } catch (RemoteException ex) { } 885 } 886 } 887 888 @Override 889 public void hideToast(String packageName, IBinder token) { 890 IStatusBar bar = mBar; 891 if (bar != null) { 892 try { 893 bar.hideToast(packageName, token); 894 } catch (RemoteException ex) { } 895 } 896 } 897 898 @Override 899 public boolean requestMagnificationConnection(boolean request) { 900 IStatusBar bar = mBar; 901 if (bar != null) { 902 try { 903 bar.requestMagnificationConnection(request); 904 return true; 905 } catch (RemoteException ex) { } 906 } 907 return false; 908 } 909 910 @Override 911 public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) { 912 if (isVisibleBackgroundUserOnDisplay(displayId)) { 913 if (SPEW) { 914 Slog.d(TAG, 915 "Skipping setNavigationBarLumaSamplingEnabled for visible background " 916 + "user " 917 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 918 } 919 return; 920 } 921 IStatusBar bar = mBar; 922 if (bar != null) { 923 try { 924 bar.setNavigationBarLumaSamplingEnabled(displayId, enable); 925 } catch (RemoteException ex) { } 926 } 927 } 928 929 @Override 930 public void setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback) { 931 synchronized (mLock) { 932 mUdfpsRefreshRateRequestCallback = callback; 933 } 934 IStatusBar bar = mBar; 935 if (bar != null) { 936 try { 937 bar.setUdfpsRefreshRateCallback(callback); 938 } catch (RemoteException ex) { } 939 } 940 } 941 942 @Override 943 public void showRearDisplayDialog(int currentBaseState) { 944 IStatusBar bar = mBar; 945 if (bar != null) { 946 try { 947 bar.showRearDisplayDialog(currentBaseState); 948 } catch (RemoteException ex) { } 949 } 950 } 951 952 @Override 953 public void moveFocusedTaskToFullscreen(int displayId) { 954 IStatusBar bar = mBar; 955 if (bar != null) { 956 try { 957 bar.moveFocusedTaskToFullscreen(displayId); 958 } catch (RemoteException ex) { } 959 } 960 } 961 962 @Override 963 public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { 964 IStatusBar bar = mBar; 965 if (bar != null) { 966 try { 967 bar.moveFocusedTaskToStageSplit(displayId, leftOrTop); 968 } catch (RemoteException ex) { } 969 } 970 } 971 972 @Override 973 public void setSplitscreenFocus(boolean leftOrTop) { 974 IStatusBar bar = mBar; 975 if (bar != null) { 976 try { 977 bar.setSplitscreenFocus(leftOrTop); 978 } catch (RemoteException ex) { } 979 } 980 } 981 982 @Override 983 public void moveFocusedTaskToDesktop(int displayId) { 984 IStatusBar bar = mBar; 985 if (bar != null) { 986 try { 987 bar.moveFocusedTaskToDesktop(displayId); 988 } catch (RemoteException ex) { } 989 } 990 } 991 992 @Override 993 public void showMediaOutputSwitcher(String targetPackageName, UserHandle targetUserHandle) { 994 IStatusBar bar = mBar; 995 if (bar != null) { 996 try { 997 bar.showMediaOutputSwitcher(targetPackageName, targetUserHandle); 998 } catch (RemoteException ex) { 999 } 1000 } 1001 } 1002 1003 @Override 1004 public void addQsTileToFrontOrEnd(ComponentName tile, boolean end) { 1005 StatusBarManagerService.this.addQsTileToFrontOrEnd(tile, end); 1006 } 1007 1008 @Override 1009 public void removeQsTile(ComponentName tile) { 1010 StatusBarManagerService.this.remTile(tile); 1011 } 1012 1013 @Override 1014 public void passThroughShellCommand(String[] args, FileDescriptor fd) { 1015 StatusBarManagerService.this.passThroughShellCommand(args, fd); 1016 } 1017 }; 1018 1019 private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() { 1020 @Override 1021 public boolean isGlobalActionsDisabled() { 1022 // TODO(b/118592525): support global actions for multi-display. 1023 final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2(); 1024 return (disabled2 & DISABLE2_GLOBAL_ACTIONS) != 0; 1025 } 1026 1027 @Override 1028 public void setGlobalActionsListener(GlobalActionsProvider.GlobalActionsListener listener) { 1029 mGlobalActionListener = listener; 1030 mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null); 1031 } 1032 1033 @Override 1034 public void showGlobalActions() { 1035 IStatusBar bar = mBar; 1036 if (bar != null) { 1037 try { 1038 bar.showGlobalActionsMenu(); 1039 } catch (RemoteException ex) {} 1040 } 1041 } 1042 }; 1043 1044 /** 1045 * Returns true if the target disable flag (target2) is set 1046 */ isDisable2FlagSet(int target2)1047 private boolean isDisable2FlagSet(int target2) { 1048 final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2(); 1049 return ((disabled2 & target2) == target2); 1050 } 1051 1052 // ================================================================================ 1053 // From IStatusBarService 1054 // ================================================================================ 1055 1056 @Override expandNotificationsPanel()1057 public void expandNotificationsPanel() { 1058 enforceExpandStatusBar(); 1059 enforceValidCallingUser(); 1060 1061 if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) { 1062 return; 1063 } 1064 1065 if (mBar != null) { 1066 try { 1067 mBar.animateExpandNotificationsPanel(); 1068 } catch (RemoteException ex) { 1069 } 1070 } 1071 } 1072 1073 @Override collapsePanels()1074 public void collapsePanels() { 1075 enforceValidCallingUser(); 1076 1077 if (!checkCanCollapseStatusBar("collapsePanels")) { 1078 return; 1079 } 1080 1081 if (mBar != null) { 1082 try { 1083 mBar.animateCollapsePanels(); 1084 } catch (RemoteException ex) { 1085 } 1086 } 1087 } 1088 1089 @Override togglePanel()1090 public void togglePanel() { 1091 enforceValidCallingUser(); 1092 1093 if (!checkCanCollapseStatusBar("togglePanel")) { 1094 return; 1095 } 1096 1097 if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) { 1098 return; 1099 } 1100 1101 if (mBar != null) { 1102 try { 1103 mBar.toggleNotificationsPanel(); 1104 } catch (RemoteException ex) { 1105 } 1106 } 1107 } 1108 1109 @Override expandSettingsPanel(String subPanel)1110 public void expandSettingsPanel(String subPanel) { 1111 enforceExpandStatusBar(); 1112 enforceValidCallingUser(); 1113 1114 if (mBar != null) { 1115 try { 1116 mBar.animateExpandSettingsPanel(subPanel); 1117 } catch (RemoteException ex) { 1118 } 1119 } 1120 } 1121 addTile(ComponentName component)1122 public void addTile(ComponentName component) { 1123 addQsTileToFrontOrEnd(component, false); 1124 } 1125 addQsTileToFrontOrEnd(ComponentName tile, boolean end)1126 private void addQsTileToFrontOrEnd(ComponentName tile, boolean end) { 1127 enforceStatusBarOrShell(); 1128 enforceValidCallingUser(); 1129 1130 if (mBar != null) { 1131 try { 1132 mBar.addQsTileToFrontOrEnd(tile, end); 1133 } catch (RemoteException ex) { 1134 } 1135 } 1136 } 1137 remTile(ComponentName component)1138 public void remTile(ComponentName component) { 1139 enforceStatusBarOrShell(); 1140 enforceValidCallingUser(); 1141 1142 if (mBar != null) { 1143 try { 1144 mBar.remQsTile(component); 1145 } catch (RemoteException ex) { 1146 } 1147 } 1148 } 1149 setTiles(String tiles)1150 public void setTiles(String tiles) { 1151 enforceStatusBarOrShell(); 1152 1153 if (mBar != null) { 1154 try { 1155 mBar.setQsTiles(tiles.split(",")); 1156 } catch (RemoteException ex) { 1157 } 1158 } 1159 } 1160 clickTile(ComponentName component)1161 public void clickTile(ComponentName component) { 1162 enforceStatusBarOrShell(); 1163 enforceValidCallingUser(); 1164 1165 if (mBar != null) { 1166 try { 1167 mBar.clickQsTile(component); 1168 } catch (RemoteException ex) { 1169 } 1170 } 1171 } 1172 1173 @Override handleSystemKey(KeyEvent key)1174 public void handleSystemKey(KeyEvent key) throws RemoteException { 1175 enforceValidCallingUser(); 1176 1177 if (!checkCanCollapseStatusBar("handleSystemKey")) { 1178 return; 1179 } 1180 1181 mLastSystemKey = key.getKeyCode(); 1182 1183 if (mBar != null) { 1184 try { 1185 mBar.handleSystemKey(key); 1186 } catch (RemoteException ex) { 1187 } 1188 } 1189 } 1190 1191 @Override 1192 @TestApi getLastSystemKey()1193 public int getLastSystemKey() { 1194 enforceStatusBar(); 1195 1196 return mLastSystemKey; 1197 } 1198 1199 @Override showPinningEnterExitToast(boolean entering)1200 public void showPinningEnterExitToast(boolean entering) throws RemoteException { 1201 enforceValidCallingUser(); 1202 1203 if (mBar != null) { 1204 try { 1205 mBar.showPinningEnterExitToast(entering); 1206 } catch (RemoteException ex) { 1207 } 1208 } 1209 } 1210 1211 @Override showPinningEscapeToast()1212 public void showPinningEscapeToast() throws RemoteException { 1213 enforceValidCallingUser(); 1214 1215 if (mBar != null) { 1216 try { 1217 mBar.showPinningEscapeToast(); 1218 } catch (RemoteException ex) { 1219 } 1220 } 1221 } 1222 1223 @Override showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, int userId, long operationId, String opPackageName, long requestId)1224 public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, 1225 int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, 1226 int userId, long operationId, String opPackageName, long requestId) { 1227 enforceBiometricDialog(); 1228 enforceValidCallingUser(); 1229 1230 if (mBar != null) { 1231 try { 1232 mBar.showAuthenticationDialog(promptInfo, receiver, sensorIds, credentialAllowed, 1233 requireConfirmation, userId, operationId, opPackageName, requestId); 1234 } catch (RemoteException ex) { 1235 } 1236 } 1237 } 1238 1239 @Override onBiometricAuthenticated(@odality int modality)1240 public void onBiometricAuthenticated(@Modality int modality) { 1241 enforceBiometricDialog(); 1242 enforceValidCallingUser(); 1243 1244 if (mBar != null) { 1245 try { 1246 mBar.onBiometricAuthenticated(modality); 1247 } catch (RemoteException ex) { 1248 } 1249 } 1250 } 1251 1252 @Override onBiometricHelp(@odality int modality, String message)1253 public void onBiometricHelp(@Modality int modality, String message) { 1254 enforceBiometricDialog(); 1255 enforceValidCallingUser(); 1256 1257 if (mBar != null) { 1258 try { 1259 mBar.onBiometricHelp(modality, message); 1260 } catch (RemoteException ex) { 1261 } 1262 } 1263 } 1264 1265 @Override onBiometricError(int modality, int error, int vendorCode)1266 public void onBiometricError(int modality, int error, int vendorCode) { 1267 enforceBiometricDialog(); 1268 enforceValidCallingUser(); 1269 1270 if (mBar != null) { 1271 try { 1272 mBar.onBiometricError(modality, error, vendorCode); 1273 } catch (RemoteException ex) { 1274 } 1275 } 1276 } 1277 1278 @Override hideAuthenticationDialog(long requestId)1279 public void hideAuthenticationDialog(long requestId) { 1280 enforceBiometricDialog(); 1281 enforceValidCallingUser(); 1282 1283 if (mBar != null) { 1284 try { 1285 mBar.hideAuthenticationDialog(requestId); 1286 } catch (RemoteException ex) { 1287 } 1288 } 1289 } 1290 1291 @Override setBiometicContextListener(IBiometricContextListener listener)1292 public void setBiometicContextListener(IBiometricContextListener listener) { 1293 enforceStatusBarService(); 1294 enforceValidCallingUser(); 1295 1296 synchronized (mLock) { 1297 mBiometricContextListener = listener; 1298 } 1299 if (mBar != null) { 1300 try { 1301 mBar.setBiometicContextListener(listener); 1302 } catch (RemoteException ex) { 1303 } 1304 } 1305 } 1306 1307 @Override setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback)1308 public void setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback) { 1309 enforceStatusBarService(); 1310 enforceValidCallingUser(); 1311 1312 if (mBar != null) { 1313 try { 1314 mBar.setUdfpsRefreshRateCallback(callback); 1315 } catch (RemoteException ex) { 1316 } 1317 } 1318 } 1319 1320 @Override startTracing()1321 public void startTracing() { 1322 enforceValidCallingUser(); 1323 1324 if (mBar != null) { 1325 try { 1326 mBar.startTracing(); 1327 mTracingEnabled = true; 1328 } catch (RemoteException ex) { 1329 } 1330 } 1331 } 1332 1333 @Override stopTracing()1334 public void stopTracing() { 1335 enforceValidCallingUser(); 1336 1337 if (mBar != null) { 1338 try { 1339 mTracingEnabled = false; 1340 mBar.stopTracing(); 1341 } catch (RemoteException ex) {} 1342 } 1343 } 1344 1345 @Override isTracing()1346 public boolean isTracing() { 1347 return mTracingEnabled; 1348 } 1349 1350 /** 1351 * Disable status bar features. Pass the bitwise-or of the {@code #DISABLE_*} flags. 1352 * To re-enable everything, pass {@code #DISABLE_NONE}. 1353 * 1354 * Warning: Only pass {@code #DISABLE_*} flags into this function, do not use 1355 * {@code #DISABLE2_*} flags. 1356 */ 1357 @Override disable(int what, IBinder token, String pkg)1358 public void disable(int what, IBinder token, String pkg) { 1359 disableForUser(what, token, pkg, mCurrentUserId); 1360 } 1361 1362 /** 1363 * Disable status bar features for a given user. Pass the bitwise-or of the 1364 * {@code #DISABLE_*} flags. To re-enable everything, pass {@code #DISABLE_NONE}. 1365 * 1366 * Warning: Only pass {@code #DISABLE_*} flags into this function, do not use 1367 * {@code #DISABLE2_*} flags. 1368 */ 1369 @Override disableForUser(int what, IBinder token, String pkg, int userId)1370 public void disableForUser(int what, IBinder token, String pkg, int userId) { 1371 enforceStatusBar(); 1372 enforceValidCallingUser(); 1373 1374 synchronized (mLock) { 1375 if (Flags.statusBarConnectedDisplays()) { 1376 IntArray displayIds = new IntArray(); 1377 for (int i = 0; i < mDisplayUiState.size(); i++) { 1378 displayIds.add(mDisplayUiState.keyAt(i)); 1379 } 1380 disableAllDisplaysLocked(displayIds, userId, what, token, pkg, /* whichFlag= */ 1); 1381 } else { 1382 disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, /* whichFlag= */ 1); 1383 } 1384 } 1385 } 1386 1387 /** 1388 * Disable additional status bar features. Pass the bitwise-or of the {@code #DISABLE2_*} flags. 1389 * To re-enable everything, pass {@code #DISABLE2_NONE}. 1390 * 1391 * Warning: Only pass {@code #DISABLE2_*} flags into this function, do not use 1392 * {@code #DISABLE_*} flags. 1393 */ 1394 @Override disable2(int what, IBinder token, String pkg)1395 public void disable2(int what, IBinder token, String pkg) { 1396 disable2ForUser(what, token, pkg, mCurrentUserId); 1397 } 1398 1399 /** 1400 * Disable additional status bar features for a given user. Pass the bitwise-or 1401 * of the {@code #DISABLE2_*} flags. To re-enable everything, pass {@code #DISABLE2_NONE}. 1402 * 1403 * Warning: Only pass {@code #DISABLE2_*} flags into this function, do not use 1404 * {@code #DISABLE_*} flags. 1405 */ 1406 @Override disable2ForUser(int what, IBinder token, String pkg, int userId)1407 public void disable2ForUser(int what, IBinder token, String pkg, int userId) { 1408 enforceStatusBar(); 1409 1410 synchronized (mLock) { 1411 if (Flags.statusBarConnectedDisplays()) { 1412 IntArray displayIds = new IntArray(); 1413 for (int i = 0; i < mDisplayUiState.size(); i++) { 1414 displayIds.add(mDisplayUiState.keyAt(i)); 1415 } 1416 disableAllDisplaysLocked(displayIds, userId, what, token, pkg, /* whichFlag= */ 2); 1417 } else { 1418 disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, /* whichFlag= */ 2); 1419 } 1420 } 1421 } 1422 disableLocked(int displayId, int userId, int what, IBinder token, String pkg, int whichFlag)1423 private void disableLocked(int displayId, int userId, int what, IBinder token, String pkg, 1424 int whichFlag) { 1425 // It's important that the the callback and the call to mBar get done 1426 // in the same order when multiple threads are calling this function 1427 // so they are paired correctly. The messages on the handler will be 1428 // handled in the order they were enqueued, but will be outside the lock. 1429 manageDisableListLocked(userId, what, token, pkg, whichFlag); 1430 1431 // Ensure state for the current user is applied, even if passed a non-current user. 1432 final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1); 1433 final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2); 1434 final UiState state = getUiState(displayId); 1435 if (!state.disableEquals(net1, net2)) { 1436 state.setDisabled(net1, net2); 1437 mHandler.post(() -> mNotificationDelegate.onSetDisabled(net1)); 1438 IStatusBar bar = mBar; 1439 if (bar != null) { 1440 try { 1441 bar.disable(displayId, net1, net2); 1442 } catch (RemoteException ex) { 1443 } 1444 } 1445 } 1446 } 1447 1448 // This method batches disable state across all displays into a single remote call 1449 // (IStatusBar#disableForAllDisplays) for efficiency and calls 1450 // NotificationDelegate#onSetDisabled only if any display's disable state changes. disableAllDisplaysLocked(IntArray displayIds, int userId, int what, IBinder token, String pkg, int whichFlag)1451 private void disableAllDisplaysLocked(IntArray displayIds, int userId, int what, IBinder token, 1452 String pkg, int whichFlag) { 1453 // It's important that the the callback and the call to mBar get done 1454 // in the same order when multiple threads are calling this function 1455 // so they are paired correctly. The messages on the handler will be 1456 // handled in the order they were enqueued, but will be outside the lock. 1457 manageDisableListLocked(userId, what, token, pkg, whichFlag); 1458 1459 // Ensure state for the current user is applied, even if passed a non-current user. 1460 final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1); 1461 final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2); 1462 1463 IStatusBar bar = mBar; 1464 Map<Integer, Pair<Integer, Integer>> displaysWithNewDisableStates = new HashMap<>(); 1465 for (int displayId : displayIds.toArray()) { 1466 final UiState state = getUiState(displayId); 1467 if (!state.disableEquals(net1, net2)) { 1468 state.setDisabled(net1, net2); 1469 displaysWithNewDisableStates.put(displayId, new Pair(net1, net2)); 1470 } 1471 } 1472 if (bar != null) { 1473 try { 1474 bar.disableForAllDisplays(new DisableStates(displaysWithNewDisableStates)); 1475 } catch (RemoteException ex) { 1476 Slog.e(TAG, "Unable to disable Status bar.", ex); 1477 } 1478 } 1479 if (!displaysWithNewDisableStates.isEmpty()) { 1480 mHandler.post(() -> mNotificationDelegate.onSetDisabled(net1)); 1481 } 1482 } 1483 1484 /** 1485 * Get the currently applied disable flags, in the form of one Pair<Integer, Integer>. 1486 * 1487 * @return pair of disable flags in the form of (disabled1, disabled2), where (0, 0) indicates 1488 * no flags are set for this token. 1489 */ 1490 @Override getDisableFlags(IBinder token, int userId)1491 public int[] getDisableFlags(IBinder token, int userId) { 1492 enforceStatusBar(); 1493 1494 int disable1 = 0; 1495 int disable2 = 0; 1496 synchronized (mLock) { 1497 // Find a matching record if it exists 1498 DisableRecord record = findMatchingRecordLocked(token, userId).second; 1499 if (record != null) { 1500 disable1 = record.what1; 1501 disable2 = record.what2; 1502 } 1503 } 1504 1505 return new int[] {disable1, disable2}; 1506 } 1507 runGcForTest()1508 void runGcForTest() { 1509 if (!Build.IS_DEBUGGABLE) { 1510 throw new SecurityException("runGcForTest requires a debuggable build"); 1511 } 1512 1513 // Gc the system along the way 1514 GcUtils.runGcAndFinalizersSync(); 1515 1516 if (mBar != null) { 1517 try { 1518 mBar.runGcForTest(); 1519 } catch (RemoteException ex) { 1520 } 1521 } 1522 } 1523 1524 @Override setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription)1525 public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, 1526 String contentDescription) { 1527 enforceStatusBar(); 1528 enforceValidCallingUser(); 1529 1530 synchronized (mIcons) { 1531 StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId, 1532 iconLevel, 0, contentDescription, StatusBarIcon.Type.SystemIcon); 1533 //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon); 1534 mIcons.put(slot, icon); 1535 1536 IStatusBar bar = mBar; 1537 if (bar != null) { 1538 try { 1539 bar.setIcon(slot, icon); 1540 } catch (RemoteException ex) { 1541 } 1542 } 1543 } 1544 } 1545 1546 @Override setIconVisibility(String slot, boolean visibility)1547 public void setIconVisibility(String slot, boolean visibility) { 1548 enforceStatusBar(); 1549 enforceValidCallingUser(); 1550 1551 synchronized (mIcons) { 1552 StatusBarIcon icon = mIcons.get(slot); 1553 if (icon == null) { 1554 return; 1555 } 1556 if (icon.visible != visibility) { 1557 icon.visible = visibility; 1558 1559 IStatusBar bar = mBar; 1560 if (bar != null) { 1561 try { 1562 bar.setIcon(slot, icon); 1563 } catch (RemoteException ex) { 1564 } 1565 } 1566 } 1567 } 1568 } 1569 1570 @Override removeIcon(String slot)1571 public void removeIcon(String slot) { 1572 enforceStatusBar(); 1573 enforceValidCallingUser(); 1574 1575 synchronized (mIcons) { 1576 mIcons.remove(slot); 1577 1578 IStatusBar bar = mBar; 1579 if (bar != null) { 1580 try { 1581 bar.removeIcon(slot); 1582 } catch (RemoteException ex) { 1583 } 1584 } 1585 } 1586 } 1587 1588 @Override setImeWindowStatus(int displayId, @ImeWindowVisibility final int vis, @BackDispositionMode final int backDisposition, final boolean showImeSwitcher)1589 public void setImeWindowStatus(int displayId, @ImeWindowVisibility final int vis, 1590 @BackDispositionMode final int backDisposition, final boolean showImeSwitcher) { 1591 enforceStatusBar(); 1592 enforceValidCallingUser(); 1593 1594 if (SPEW) { 1595 Slog.d(TAG, "setImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); 1596 } 1597 1598 synchronized(mLock) { 1599 // In case of IME change, we need to call up setImeWindowStatus() regardless of 1600 // mImeWindowVis because mImeWindowVis may not have been set to false when the 1601 // previous IME was destroyed. 1602 getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher); 1603 1604 mHandler.post(() -> { 1605 IStatusBar bar = mBar; 1606 if (bar != null) { 1607 try { 1608 bar.setImeWindowStatus(displayId, vis, backDisposition, showImeSwitcher); 1609 } catch (RemoteException ex) { 1610 } 1611 } 1612 }); 1613 } 1614 } 1615 setDisableFlags(int displayId, int flags, String cause)1616 private void setDisableFlags(int displayId, int flags, String cause) { 1617 if (isVisibleBackgroundUserOnDisplay(displayId)) { 1618 if (SPEW) { 1619 Slog.d(TAG, "Skipping setDisableFlags for visible background user " 1620 + mUserManagerInternal.getUserAssignedToDisplay(displayId)); 1621 } 1622 return; 1623 } 1624 // also allows calls from window manager which is in this process. 1625 enforceStatusBarService(); 1626 1627 final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK; 1628 if (unknownFlags != 0) { 1629 Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags), 1630 new RuntimeException()); 1631 } 1632 1633 if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")"); 1634 1635 synchronized (mLock) { 1636 disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1); 1637 } 1638 } 1639 1640 /** 1641 * @return {@link UiState} specified by {@code displayId}. 1642 * 1643 * <p> 1644 * Note: If {@link UiState} specified by {@code displayId} does not exist, {@link UiState} 1645 * will be allocated and {@code mDisplayUiState} will be updated accordingly. 1646 * <p/> 1647 */ getUiState(int displayId)1648 private UiState getUiState(int displayId) { 1649 UiState state = mDisplayUiState.get(displayId); 1650 if (state == null) { 1651 state = new UiState(); 1652 mDisplayUiState.put(displayId, state); 1653 } 1654 return state; 1655 } 1656 1657 private static class UiState { 1658 private @Appearance int mAppearance = 0; 1659 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; 1660 private @InsetsType int mTransientBarTypes; 1661 private boolean mNavbarColorManagedByIme = false; 1662 private @Behavior int mBehavior; 1663 private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible(); 1664 private String mPackageName = "none"; 1665 private int mDisabled1 = 0; 1666 private int mDisabled2 = 0; 1667 @ImeWindowVisibility 1668 private int mImeWindowVis = 0; 1669 @BackDispositionMode 1670 private int mImeBackDisposition = BACK_DISPOSITION_DEFAULT; 1671 private boolean mShowImeSwitcher = false; 1672 private LetterboxDetails[] mLetterboxDetails = new LetterboxDetails[0]; 1673 setBarAttributes(@ppearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)1674 private void setBarAttributes(@Appearance int appearance, 1675 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, 1676 @Behavior int behavior, @InsetsType int requestedVisibleTypes, 1677 String packageName, 1678 LetterboxDetails[] letterboxDetails) { 1679 mAppearance = appearance; 1680 mAppearanceRegions = appearanceRegions; 1681 mNavbarColorManagedByIme = navbarColorManagedByIme; 1682 mBehavior = behavior; 1683 mRequestedVisibleTypes = requestedVisibleTypes; 1684 mPackageName = packageName; 1685 mLetterboxDetails = letterboxDetails; 1686 } 1687 showTransient(@nsetsType int types)1688 private void showTransient(@InsetsType int types) { 1689 mTransientBarTypes |= types; 1690 } 1691 clearTransient(@nsetsType int types)1692 private void clearTransient(@InsetsType int types) { 1693 mTransientBarTypes &= ~types; 1694 } 1695 getDisabled1()1696 private int getDisabled1() { 1697 return mDisabled1; 1698 } 1699 getDisabled2()1700 private int getDisabled2() { 1701 return mDisabled2; 1702 } 1703 setDisabled(int disabled1, int disabled2)1704 private void setDisabled(int disabled1, int disabled2) { 1705 mDisabled1 = disabled1; 1706 mDisabled2 = disabled2; 1707 } 1708 disableEquals(int disabled1, int disabled2)1709 private boolean disableEquals(int disabled1, int disabled2) { 1710 return mDisabled1 == disabled1 && mDisabled2 == disabled2; 1711 } 1712 setImeWindowState(@meWindowVisibility final int vis, @BackDispositionMode final int backDisposition, final boolean showImeSwitcher)1713 private void setImeWindowState(@ImeWindowVisibility final int vis, 1714 @BackDispositionMode final int backDisposition, 1715 final boolean showImeSwitcher) { 1716 mImeWindowVis = vis; 1717 mImeBackDisposition = backDisposition; 1718 mShowImeSwitcher = showImeSwitcher; 1719 } 1720 } 1721 enforceStatusBarOrShell()1722 private void enforceStatusBarOrShell() { 1723 if (Binder.getCallingUid() == Process.SHELL_UID) { 1724 return; 1725 } 1726 enforceStatusBar(); 1727 } 1728 enforceStatusBar()1729 private void enforceStatusBar() { 1730 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR, 1731 "StatusBarManagerService"); 1732 } 1733 enforceExpandStatusBar()1734 private void enforceExpandStatusBar() { 1735 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.EXPAND_STATUS_BAR, 1736 "StatusBarManagerService"); 1737 } 1738 enforceStatusBarService()1739 private void enforceStatusBarService() { 1740 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 1741 "StatusBarManagerService"); 1742 } 1743 enforceBiometricDialog()1744 private void enforceBiometricDialog() { 1745 mContext.enforceCallingOrSelfPermission( 1746 android.Manifest.permission.MANAGE_BIOMETRIC_DIALOG, 1747 "StatusBarManagerService"); 1748 } 1749 enforceMediaContentControl()1750 private void enforceMediaContentControl() { 1751 mContext.enforceCallingOrSelfPermission( 1752 android.Manifest.permission.MEDIA_CONTENT_CONTROL, 1753 "StatusBarManagerService"); 1754 } 1755 1756 @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) enforceControlDeviceStatePermission()1757 private void enforceControlDeviceStatePermission() { 1758 mContext.enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "StatusBarManagerService"); 1759 } 1760 doesCallerHoldInteractAcrossUserPermission()1761 private boolean doesCallerHoldInteractAcrossUserPermission() { 1762 return mContext.checkCallingPermission(INTERACT_ACROSS_USERS_FULL) == PERMISSION_GRANTED 1763 || mContext.checkCallingPermission(INTERACT_ACROSS_USERS) == PERMISSION_GRANTED; 1764 } 1765 1766 /** 1767 * For targetSdk S+ we require STATUS_BAR. For targetSdk < S, we only require EXPAND_STATUS_BAR 1768 * but also require that it falls into one of the allowed use-cases to lock down abuse vector. 1769 */ checkCanCollapseStatusBar(String method)1770 private boolean checkCanCollapseStatusBar(String method) { 1771 int uid = Binder.getCallingUid(); 1772 int pid = Binder.getCallingPid(); 1773 if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) { 1774 enforceStatusBar(); 1775 } else { 1776 if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid) 1777 != PERMISSION_GRANTED) { 1778 enforceExpandStatusBar(); 1779 if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) { 1780 Slog.e(TAG, "Permission Denial: Method " + method + "() requires permission " 1781 + Manifest.permission.STATUS_BAR + ", ignoring call."); 1782 return false; 1783 } 1784 } 1785 } 1786 return true; 1787 } 1788 1789 // ================================================================================ 1790 // Callbacks from the status bar service. 1791 // ================================================================================ 1792 // TODO(b/118592525): refactor it as an IStatusBar API. 1793 @Override registerStatusBar(IStatusBar bar)1794 public RegisterStatusBarResult registerStatusBar(IStatusBar bar) { 1795 enforceStatusBarService(); 1796 enforceValidCallingUser(); 1797 1798 Slog.i(TAG, "registerStatusBar bar=" + bar); 1799 mBar = bar; 1800 mDeathRecipient.linkToDeath(); 1801 notifyBarAttachChanged(); 1802 final ArrayMap<String, StatusBarIcon> icons; 1803 synchronized (mIcons) { 1804 icons = new ArrayMap<>(mIcons); 1805 } 1806 synchronized (mLock) { 1807 final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY); 1808 return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1), 1809 state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis, 1810 state.mImeBackDisposition, state.mShowImeSwitcher, 1811 gatherDisableActionsLocked(mCurrentUserId, 2), 1812 state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes, 1813 state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails); 1814 } 1815 } 1816 1817 @Override registerStatusBarForAllDisplays(IStatusBar bar)1818 public Map<String, RegisterStatusBarResult> registerStatusBarForAllDisplays(IStatusBar bar) { 1819 enforceStatusBarService(); 1820 enforceValidCallingUser(); 1821 1822 Slog.i(TAG, "registerStatusBarForAllDisplays bar=" + bar); 1823 mBar = bar; 1824 mDeathRecipient.linkToDeath(); 1825 notifyBarAttachChanged(); 1826 1827 synchronized (mLock) { 1828 Map<String, RegisterStatusBarResult> results = new HashMap<>(); 1829 1830 for (int i = 0; i < mDisplayUiState.size(); i++) { 1831 final int displayId = mDisplayUiState.keyAt(i); 1832 final UiState state = mDisplayUiState.get(displayId); 1833 1834 final ArrayMap<String, StatusBarIcon> icons; 1835 synchronized (mIcons) { 1836 icons = new ArrayMap<>(mIcons); 1837 } 1838 1839 if (state != null) { 1840 results.put(String.valueOf(displayId), 1841 new RegisterStatusBarResult(icons, 1842 gatherDisableActionsLocked(mCurrentUserId, 1), 1843 state.mAppearance, state.mAppearanceRegions, 1844 state.mImeWindowVis, 1845 state.mImeBackDisposition, state.mShowImeSwitcher, 1846 gatherDisableActionsLocked(mCurrentUserId, 2), 1847 state.mNavbarColorManagedByIme, state.mBehavior, 1848 state.mRequestedVisibleTypes, 1849 state.mPackageName, state.mTransientBarTypes, 1850 state.mLetterboxDetails)); 1851 } 1852 } 1853 return results; 1854 } 1855 } 1856 notifyBarAttachChanged()1857 private void notifyBarAttachChanged() { 1858 UiThread.getHandler().post(() -> { 1859 if (mGlobalActionListener == null) return; 1860 mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null); 1861 }); 1862 // If StatusBarService dies, system_server doesn't get killed with it, so we need to make 1863 // sure the UDFPS callback is refreshed as well. Deferring to the handler just so to avoid 1864 // making registerStatusBar re-entrant. 1865 mHandler.post(() -> { 1866 synchronized (mLock) { 1867 setUdfpsRefreshRateCallback(mUdfpsRefreshRateRequestCallback); 1868 setBiometicContextListener(mBiometricContextListener); 1869 } 1870 }); 1871 } 1872 1873 @VisibleForTesting registerOverlayManager(IOverlayManager overlayManager)1874 void registerOverlayManager(IOverlayManager overlayManager) { 1875 mOverlayManager = overlayManager; 1876 } 1877 1878 /** 1879 * @param clearNotificationEffects whether to consider notifications as "shown" and stop 1880 * LED, vibration, and ringing 1881 */ 1882 @Override onPanelRevealed(boolean clearNotificationEffects, int numItems)1883 public void onPanelRevealed(boolean clearNotificationEffects, int numItems) { 1884 enforceStatusBarService(); 1885 enforceValidCallingUser(); 1886 1887 final long identity = Binder.clearCallingIdentity(); 1888 try { 1889 mNotificationDelegate.onPanelRevealed(clearNotificationEffects, numItems); 1890 } finally { 1891 Binder.restoreCallingIdentity(identity); 1892 } 1893 } 1894 1895 @Override clearNotificationEffects()1896 public void clearNotificationEffects() throws RemoteException { 1897 enforceStatusBarService(); 1898 enforceValidCallingUser(); 1899 1900 final long identity = Binder.clearCallingIdentity(); 1901 try { 1902 mNotificationDelegate.clearEffects(); 1903 } finally { 1904 Binder.restoreCallingIdentity(identity); 1905 } 1906 } 1907 1908 @Override onPanelHidden()1909 public void onPanelHidden() throws RemoteException { 1910 enforceStatusBarService(); 1911 enforceValidCallingUser(); 1912 1913 final long identity = Binder.clearCallingIdentity(); 1914 try { 1915 mNotificationDelegate.onPanelHidden(); 1916 } finally { 1917 Binder.restoreCallingIdentity(identity); 1918 } 1919 } 1920 1921 /** 1922 * Allows the status bar to shutdown the device. 1923 */ 1924 @Override shutdown()1925 public void shutdown() { 1926 enforceStatusBarService(); 1927 enforceValidCallingUser(); 1928 1929 String reason = PowerManager.SHUTDOWN_USER_REQUESTED; 1930 ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); 1931 final long identity = Binder.clearCallingIdentity(); 1932 try { 1933 mNotificationDelegate.prepareForPossibleShutdown(); 1934 // ShutdownThread displays UI, so give it a UI context. 1935 mHandler.post(() -> 1936 ShutdownThread.shutdown(getUiContext(), reason, false)); 1937 } finally { 1938 Binder.restoreCallingIdentity(identity); 1939 } 1940 } 1941 1942 /** 1943 * Allows the status bar to reboot the device. 1944 */ 1945 @Override reboot(boolean safeMode)1946 public void reboot(boolean safeMode) { 1947 enforceStatusBarService(); 1948 enforceValidCallingUser(); 1949 1950 String reason = safeMode 1951 ? PowerManager.REBOOT_SAFE_MODE 1952 : PowerManager.SHUTDOWN_USER_REQUESTED; 1953 ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); 1954 final long identity = Binder.clearCallingIdentity(); 1955 try { 1956 mNotificationDelegate.prepareForPossibleShutdown(); 1957 mHandler.post(() -> { 1958 // ShutdownThread displays UI, so give it a UI context. 1959 if (safeMode) { 1960 ShutdownThread.rebootSafeMode(getUiContext(), true); 1961 } else { 1962 ShutdownThread.reboot(getUiContext(), reason, false); 1963 } 1964 }); 1965 } finally { 1966 Binder.restoreCallingIdentity(identity); 1967 } 1968 } 1969 1970 /** 1971 * Allows the status bar to restart android (vs a full reboot). 1972 */ 1973 @Override restart()1974 public void restart() { 1975 enforceStatusBarService(); 1976 enforceValidCallingUser(); 1977 1978 final long identity = Binder.clearCallingIdentity(); 1979 try { 1980 mHandler.post(() -> { 1981 mActivityManagerInternal.restart(); 1982 }); 1983 } finally { 1984 Binder.restoreCallingIdentity(identity); 1985 } 1986 } 1987 1988 @Override onGlobalActionsShown()1989 public void onGlobalActionsShown() { 1990 enforceStatusBarService(); 1991 enforceValidCallingUser(); 1992 1993 final long identity = Binder.clearCallingIdentity(); 1994 try { 1995 if (mGlobalActionListener == null) return; 1996 mGlobalActionListener.onGlobalActionsShown(); 1997 } finally { 1998 Binder.restoreCallingIdentity(identity); 1999 } 2000 } 2001 2002 @Override onGlobalActionsHidden()2003 public void onGlobalActionsHidden() { 2004 enforceStatusBarService(); 2005 enforceValidCallingUser(); 2006 2007 final long identity = Binder.clearCallingIdentity(); 2008 try { 2009 if (mGlobalActionListener == null) return; 2010 mGlobalActionListener.onGlobalActionsDismissed(); 2011 } finally { 2012 Binder.restoreCallingIdentity(identity); 2013 } 2014 } 2015 2016 @Override onNotificationClick(String key, NotificationVisibility nv)2017 public void onNotificationClick(String key, NotificationVisibility nv) { 2018 // enforceValidCallingUser is not required here as the NotificationManagerService 2019 // will handle multi-user scenarios 2020 enforceStatusBarService(); 2021 final int callingUid = Binder.getCallingUid(); 2022 final int callingPid = Binder.getCallingPid(); 2023 final long identity = Binder.clearCallingIdentity(); 2024 try { 2025 mNotificationDelegate.onNotificationClick(callingUid, callingPid, key, nv); 2026 } finally { 2027 Binder.restoreCallingIdentity(identity); 2028 } 2029 } 2030 2031 @Override onNotificationActionClick( String key, int actionIndex, Notification.Action action, NotificationVisibility nv, boolean generatedByAssistant)2032 public void onNotificationActionClick( 2033 String key, int actionIndex, Notification.Action action, NotificationVisibility nv, 2034 boolean generatedByAssistant) { 2035 // enforceValidCallingUser is not required here as the NotificationManagerService 2036 // will handle multi-user scenarios 2037 enforceStatusBarService(); 2038 final int callingUid = Binder.getCallingUid(); 2039 final int callingPid = Binder.getCallingPid(); 2040 final long identity = Binder.clearCallingIdentity(); 2041 try { 2042 mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key, 2043 actionIndex, action, nv, generatedByAssistant); 2044 } finally { 2045 Binder.restoreCallingIdentity(identity); 2046 } 2047 } 2048 2049 @Override onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId)2050 public void onNotificationError(String pkg, String tag, int id, 2051 int uid, int initialPid, String message, int userId) { 2052 // enforceValidCallingUser is not required here as the NotificationManagerService 2053 // will handle multi-user scenarios 2054 enforceStatusBarService(); 2055 final int callingUid = Binder.getCallingUid(); 2056 final int callingPid = Binder.getCallingPid(); 2057 final long identity = Binder.clearCallingIdentity(); 2058 try { 2059 // WARNING: this will call back into us to do the remove. Don't hold any locks. 2060 mNotificationDelegate.onNotificationError(callingUid, callingPid, 2061 pkg, tag, id, uid, initialPid, message, userId); 2062 } finally { 2063 Binder.restoreCallingIdentity(identity); 2064 } 2065 } 2066 2067 @Override onNotificationClear(String pkg, int userId, String key, @NotificationStats.DismissalSurface int dismissalSurface, @NotificationStats.DismissalSentiment int dismissalSentiment, NotificationVisibility nv)2068 public void onNotificationClear(String pkg, int userId, String key, 2069 @NotificationStats.DismissalSurface int dismissalSurface, 2070 @NotificationStats.DismissalSentiment int dismissalSentiment, 2071 NotificationVisibility nv) { 2072 // enforceValidCallingUser is not required here as the NotificationManagerService 2073 // will handle multi-user scenarios 2074 enforceStatusBarService(); 2075 final int callingUid = Binder.getCallingUid(); 2076 final int callingPid = Binder.getCallingPid(); 2077 final long identity = Binder.clearCallingIdentity(); 2078 try { 2079 mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, userId, 2080 key, dismissalSurface, dismissalSentiment, nv); 2081 } finally { 2082 Binder.restoreCallingIdentity(identity); 2083 } 2084 } 2085 2086 @Override onNotificationVisibilityChanged( NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys)2087 public void onNotificationVisibilityChanged( 2088 NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys) 2089 throws RemoteException { 2090 enforceStatusBarService(); 2091 enforceValidCallingUser(); 2092 2093 final long identity = Binder.clearCallingIdentity(); 2094 try { 2095 mNotificationDelegate.onNotificationVisibilityChanged( 2096 newlyVisibleKeys, noLongerVisibleKeys); 2097 } finally { 2098 Binder.restoreCallingIdentity(identity); 2099 } 2100 } 2101 2102 @Override onNotificationExpansionChanged(String key, boolean userAction, boolean expanded, int location)2103 public void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded, 2104 int location) throws RemoteException { 2105 enforceStatusBarService(); 2106 enforceValidCallingUser(); 2107 2108 final long identity = Binder.clearCallingIdentity(); 2109 try { 2110 mNotificationDelegate.onNotificationExpansionChanged( 2111 key, userAction, expanded, location); 2112 } finally { 2113 Binder.restoreCallingIdentity(identity); 2114 } 2115 } 2116 2117 @Override onNotificationDirectReplied(String key)2118 public void onNotificationDirectReplied(String key) throws RemoteException { 2119 enforceStatusBarService(); 2120 enforceValidCallingUser(); 2121 2122 final long identity = Binder.clearCallingIdentity(); 2123 try { 2124 mNotificationDelegate.onNotificationDirectReplied(key); 2125 } finally { 2126 Binder.restoreCallingIdentity(identity); 2127 } 2128 } 2129 2130 @Override onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending)2131 public void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, 2132 int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending) { 2133 enforceStatusBarService(); 2134 enforceValidCallingUser(); 2135 2136 final long identity = Binder.clearCallingIdentity(); 2137 try { 2138 mNotificationDelegate.onNotificationSmartSuggestionsAdded(key, smartReplyCount, 2139 smartActionCount, generatedByAssistant, editBeforeSending); 2140 } finally { 2141 Binder.restoreCallingIdentity(identity); 2142 } 2143 } 2144 2145 @Override onNotificationSmartReplySent( String key, int replyIndex, CharSequence reply, int notificationLocation, boolean modifiedBeforeSending)2146 public void onNotificationSmartReplySent( 2147 String key, int replyIndex, CharSequence reply, int notificationLocation, 2148 boolean modifiedBeforeSending) throws RemoteException { 2149 enforceStatusBarService(); 2150 enforceValidCallingUser(); 2151 2152 final long identity = Binder.clearCallingIdentity(); 2153 try { 2154 mNotificationDelegate.onNotificationSmartReplySent(key, replyIndex, reply, 2155 notificationLocation, modifiedBeforeSending); 2156 } finally { 2157 Binder.restoreCallingIdentity(identity); 2158 } 2159 } 2160 2161 @Override onNotificationSettingsViewed(String key)2162 public void onNotificationSettingsViewed(String key) throws RemoteException { 2163 enforceStatusBarService(); 2164 enforceValidCallingUser(); 2165 2166 final long identity = Binder.clearCallingIdentity(); 2167 try { 2168 mNotificationDelegate.onNotificationSettingsViewed(key); 2169 } finally { 2170 Binder.restoreCallingIdentity(identity); 2171 } 2172 } 2173 2174 @Override onClearAllNotifications(int userId)2175 public void onClearAllNotifications(int userId) { 2176 enforceStatusBarService(); 2177 final int callingUid = Binder.getCallingUid(); 2178 final int callingPid = Binder.getCallingPid(); 2179 final long identity = Binder.clearCallingIdentity(); 2180 try { 2181 mNotificationDelegate.onClearAll(callingUid, callingPid, userId); 2182 } finally { 2183 Binder.restoreCallingIdentity(identity); 2184 } 2185 } 2186 2187 @Override onNotificationBubbleChanged(String key, boolean isBubble, int flags)2188 public void onNotificationBubbleChanged(String key, boolean isBubble, int flags) { 2189 enforceStatusBarService(); 2190 enforceValidCallingUser(); 2191 2192 final long identity = Binder.clearCallingIdentity(); 2193 try { 2194 mNotificationDelegate.onNotificationBubbleChanged(key, isBubble, flags); 2195 } finally { 2196 Binder.restoreCallingIdentity(identity); 2197 } 2198 } 2199 2200 @Override onBubbleMetadataFlagChanged(String key, int flags)2201 public void onBubbleMetadataFlagChanged(String key, int flags) { 2202 enforceStatusBarService(); 2203 enforceValidCallingUser(); 2204 2205 final long identity = Binder.clearCallingIdentity(); 2206 try { 2207 mNotificationDelegate.onBubbleMetadataFlagChanged(key, flags); 2208 } finally { 2209 Binder.restoreCallingIdentity(identity); 2210 } 2211 } 2212 2213 @Override hideCurrentInputMethodForBubbles(int displayId)2214 public void hideCurrentInputMethodForBubbles(int displayId) { 2215 enforceStatusBarService(); 2216 enforceValidCallingUser(); 2217 2218 final long token = Binder.clearCallingIdentity(); 2219 try { 2220 InputMethodManagerInternal.get().hideInputMethod( 2221 SoftInputShowHideReason.HIDE_BUBBLES, displayId); 2222 } finally { 2223 Binder.restoreCallingIdentity(token); 2224 } 2225 } 2226 2227 @Override grantInlineReplyUriPermission(String key, Uri uri, UserHandle user, String packageName)2228 public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user, 2229 String packageName) { 2230 enforceStatusBarService(); 2231 int callingUid = Binder.getCallingUid(); 2232 final long identity = Binder.clearCallingIdentity(); 2233 try { 2234 mNotificationDelegate.grantInlineReplyUriPermission(key, uri, user, packageName, 2235 callingUid); 2236 } finally { 2237 Binder.restoreCallingIdentity(identity); 2238 } 2239 } 2240 2241 @Override clearInlineReplyUriPermissions(String key)2242 public void clearInlineReplyUriPermissions(String key) { 2243 enforceStatusBarService(); 2244 int callingUid = Binder.getCallingUid(); 2245 final long identity = Binder.clearCallingIdentity(); 2246 try { 2247 mNotificationDelegate.clearInlineReplyUriPermissions(key, callingUid); 2248 } finally { 2249 Binder.restoreCallingIdentity(identity); 2250 } 2251 } 2252 2253 @Override onNotificationFeedbackReceived(String key, Bundle feedback)2254 public void onNotificationFeedbackReceived(String key, Bundle feedback) { 2255 enforceStatusBarService(); 2256 enforceValidCallingUser(); 2257 2258 final long identity = Binder.clearCallingIdentity(); 2259 try { 2260 mNotificationDelegate.onNotificationFeedbackReceived(key, feedback); 2261 } finally { 2262 Binder.restoreCallingIdentity(identity); 2263 } 2264 } 2265 2266 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2267 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 2268 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 2269 (new StatusBarShellCommand(this, mContext)).exec( 2270 this, in, out, err, args, callback, resultReceiver); 2271 } 2272 2273 @Override showInattentiveSleepWarning()2274 public void showInattentiveSleepWarning() { 2275 enforceStatusBarService(); 2276 enforceValidCallingUser(); 2277 2278 IStatusBar bar = mBar; 2279 if (bar != null) { 2280 try { 2281 bar.showInattentiveSleepWarning(); 2282 } catch (RemoteException ex) { 2283 } 2284 } 2285 } 2286 2287 @Override dismissInattentiveSleepWarning(boolean animated)2288 public void dismissInattentiveSleepWarning(boolean animated) { 2289 enforceStatusBarService(); 2290 enforceValidCallingUser(); 2291 2292 IStatusBar bar = mBar; 2293 if (bar != null) { 2294 try { 2295 bar.dismissInattentiveSleepWarning(animated); 2296 } catch (RemoteException ex) { 2297 } 2298 } 2299 } 2300 2301 @Override suppressAmbientDisplay(boolean suppress)2302 public void suppressAmbientDisplay(boolean suppress) { 2303 enforceStatusBarService(); 2304 enforceValidCallingUser(); 2305 2306 IStatusBar bar = mBar; 2307 if (bar != null) { 2308 try { 2309 bar.suppressAmbientDisplay(suppress); 2310 } catch (RemoteException ex) { 2311 } 2312 } 2313 } 2314 checkCallingUidPackage(String packageName, int callingUid, int userId)2315 private void checkCallingUidPackage(String packageName, int callingUid, int userId) { 2316 int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId); 2317 if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(packageUid)) { 2318 throw new SecurityException("Package " + packageName 2319 + " does not belong to the calling uid " + callingUid); 2320 } 2321 } 2322 isComponentValidTileService(ComponentName componentName, int userId)2323 private ResolveInfo isComponentValidTileService(ComponentName componentName, int userId) { 2324 Intent intent = new Intent(TileService.ACTION_QS_TILE); 2325 intent.setComponent(componentName); 2326 ResolveInfo r = mPackageManagerInternal.resolveService(intent, 2327 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 0, userId, 2328 Process.myUid()); 2329 int enabled = mPackageManagerInternal.getComponentEnabledSetting( 2330 componentName, Process.myUid(), userId); 2331 if (r != null 2332 && r.serviceInfo != null 2333 && resolveEnabledComponent(r.serviceInfo.enabled, enabled) 2334 && Manifest.permission.BIND_QUICK_SETTINGS_TILE.equals(r.serviceInfo.permission)) { 2335 return r; 2336 } else { 2337 return null; 2338 } 2339 } 2340 resolveEnabledComponent(boolean defaultValue, int pmResult)2341 private boolean resolveEnabledComponent(boolean defaultValue, int pmResult) { 2342 if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { 2343 return true; 2344 } 2345 if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 2346 return defaultValue; 2347 } 2348 return false; 2349 } 2350 2351 @Override requestTileServiceListeningState( @onNull ComponentName componentName, int userId )2352 public void requestTileServiceListeningState( 2353 @NonNull ComponentName componentName, 2354 int userId 2355 ) { 2356 int callingUid = Binder.getCallingUid(); 2357 String packageName = componentName.getPackageName(); 2358 2359 boolean mustPerformChecks = CompatChanges.isChangeEnabled( 2360 REQUEST_LISTENING_MUST_MATCH_PACKAGE, callingUid); 2361 2362 if (mustPerformChecks) { 2363 // Check calling user can act on behalf of current user 2364 userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, 2365 userId, false, ActivityManagerInternal.ALLOW_NON_FULL, 2366 "requestTileServiceListeningState", packageName); 2367 2368 // Check calling uid matches package 2369 checkCallingUidPackage(packageName, callingUid, userId); 2370 2371 int currentUser = mActivityManagerInternal.getCurrentUserId(); 2372 2373 // Check current user 2374 if (userId != currentUser) { 2375 if (CompatChanges.isChangeEnabled(REQUEST_LISTENING_OTHER_USER_NOOP, callingUid)) { 2376 return; 2377 } else { 2378 throw new IllegalArgumentException( 2379 "User " + userId + " is not the current user."); 2380 } 2381 } 2382 } 2383 IStatusBar bar = mBar; 2384 if (bar != null) { 2385 try { 2386 bar.requestTileServiceListeningState(componentName); 2387 } catch (RemoteException e) { 2388 Slog.e(TAG, "requestTileServiceListeningState", e); 2389 } 2390 } 2391 } 2392 2393 @Override requestAddTile( @onNull ComponentName componentName, @NonNull CharSequence label, @NonNull Icon icon, int userId, @NonNull IAddTileResultCallback callback )2394 public void requestAddTile( 2395 @NonNull ComponentName componentName, 2396 @NonNull CharSequence label, 2397 @NonNull Icon icon, 2398 int userId, 2399 @NonNull IAddTileResultCallback callback 2400 ) { 2401 int callingUid = Binder.getCallingUid(); 2402 String packageName = componentName.getPackageName(); 2403 2404 // Check calling user can act on behalf of current user 2405 mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, 2406 false, ActivityManagerInternal.ALLOW_NON_FULL, "requestAddTile", packageName); 2407 2408 // Check calling uid matches package 2409 checkCallingUidPackage(packageName, callingUid, userId); 2410 2411 int currentUser = mActivityManagerInternal.getCurrentUserId(); 2412 2413 // Check current user 2414 if (userId != currentUser) { 2415 try { 2416 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NOT_CURRENT_USER); 2417 } catch (RemoteException e) { 2418 Slog.e(TAG, "requestAddTile", e); 2419 } 2420 return; 2421 } 2422 2423 // We've checked that the package, component name and uid all match. 2424 ResolveInfo r = isComponentValidTileService(componentName, userId); 2425 if (r == null || !r.serviceInfo.exported) { 2426 try { 2427 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_BAD_COMPONENT); 2428 } catch (RemoteException e) { 2429 Slog.e(TAG, "requestAddTile", e); 2430 } 2431 return; 2432 } 2433 2434 final int procState = mActivityManagerInternal.getUidProcessState(callingUid); 2435 if (ActivityManager.RunningAppProcessInfo.procStateToImportance(procState) 2436 != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { 2437 try { 2438 callback.onTileRequest( 2439 StatusBarManager.TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND); 2440 } catch (RemoteException e) { 2441 Slog.e(TAG, "requestAddTile", e); 2442 } 2443 return; 2444 } 2445 2446 synchronized (mCurrentRequestAddTilePackages) { 2447 Long lastTime = mCurrentRequestAddTilePackages.get(packageName); 2448 final long currentTime = System.nanoTime(); 2449 if (lastTime != null && currentTime - lastTime < REQUEST_TIME_OUT) { 2450 try { 2451 callback.onTileRequest( 2452 StatusBarManager.TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS); 2453 } catch (RemoteException e) { 2454 Slog.e(TAG, "requestAddTile", e); 2455 } 2456 return; 2457 } else { 2458 if (lastTime != null) { 2459 cancelRequestAddTileInternal(packageName); 2460 } 2461 } 2462 2463 mCurrentRequestAddTilePackages.put(packageName, currentTime); 2464 } 2465 2466 if (mTileRequestTracker.shouldBeDenied(userId, componentName)) { 2467 if (clearTileAddRequest(packageName)) { 2468 try { 2469 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED); 2470 } catch (RemoteException e) { 2471 Slog.e(TAG, "requestAddTile - callback", e); 2472 } 2473 } 2474 return; 2475 } 2476 2477 IAddTileResultCallback proxyCallback = new IAddTileResultCallback.Stub() { 2478 @Override 2479 public void onTileRequest(int i) { 2480 if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED) { 2481 i = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED; 2482 } else if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED) { 2483 mTileRequestTracker.addDenial(userId, componentName); 2484 } else if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ADDED) { 2485 mTileRequestTracker.resetRequests(userId, componentName); 2486 } 2487 if (clearTileAddRequest(packageName)) { 2488 try { 2489 callback.onTileRequest(i); 2490 } catch (RemoteException e) { 2491 Slog.e(TAG, "requestAddTile - callback", e); 2492 } 2493 } 2494 } 2495 }; 2496 2497 CharSequence appName = r.serviceInfo.applicationInfo 2498 .loadLabel(mContext.getPackageManager()); 2499 IStatusBar bar = mBar; 2500 if (bar != null) { 2501 try { 2502 bar.requestAddTile(callingUid, componentName, appName, label, icon, proxyCallback); 2503 return; 2504 } catch (RemoteException e) { 2505 Slog.e(TAG, "requestAddTile", e); 2506 } 2507 } 2508 clearTileAddRequest(packageName); 2509 try { 2510 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE); 2511 } catch (RemoteException e) { 2512 Slog.e(TAG, "requestAddTile", e); 2513 } 2514 } 2515 2516 @Override cancelRequestAddTile(@onNull String packageName)2517 public void cancelRequestAddTile(@NonNull String packageName) { 2518 enforceStatusBar(); 2519 enforceValidCallingUser(); 2520 2521 cancelRequestAddTileInternal(packageName); 2522 } 2523 cancelRequestAddTileInternal(String packageName)2524 private void cancelRequestAddTileInternal(String packageName) { 2525 clearTileAddRequest(packageName); 2526 IStatusBar bar = mBar; 2527 if (bar != null) { 2528 try { 2529 bar.cancelRequestAddTile(packageName); 2530 } catch (RemoteException e) { 2531 Slog.e(TAG, "requestAddTile", e); 2532 } 2533 } 2534 } 2535 clearTileAddRequest(String packageName)2536 private boolean clearTileAddRequest(String packageName) { 2537 synchronized (mCurrentRequestAddTilePackages) { 2538 return mCurrentRequestAddTilePackages.remove(packageName) != null; 2539 } 2540 } 2541 2542 @Override onSessionStarted(@essionFlags int sessionType, InstanceId instance)2543 public void onSessionStarted(@SessionFlags int sessionType, InstanceId instance) { 2544 enforceValidCallingUser(); 2545 2546 mSessionMonitor.onSessionStarted(sessionType, instance); 2547 } 2548 2549 @Override onSessionEnded(@essionFlags int sessionType, InstanceId instance)2550 public void onSessionEnded(@SessionFlags int sessionType, InstanceId instance) { 2551 enforceValidCallingUser(); 2552 2553 mSessionMonitor.onSessionEnded(sessionType, instance); 2554 } 2555 2556 @Override registerSessionListener(@essionFlags int sessionFlags, ISessionListener listener)2557 public void registerSessionListener(@SessionFlags int sessionFlags, 2558 ISessionListener listener) { 2559 enforceValidCallingUser(); 2560 2561 mSessionMonitor.registerSessionListener(sessionFlags, listener); 2562 } 2563 2564 @Override unregisterSessionListener(@essionFlags int sessionFlags, ISessionListener listener)2565 public void unregisterSessionListener(@SessionFlags int sessionFlags, 2566 ISessionListener listener) { 2567 enforceValidCallingUser(); 2568 2569 mSessionMonitor.unregisterSessionListener(sessionFlags, listener); 2570 } 2571 getStatusBarIcons()2572 public String[] getStatusBarIcons() { 2573 return mContext.getResources().getStringArray(R.array.config_statusBarIcons); 2574 } 2575 2576 /** 2577 * Sets or removes the navigation bar mode. 2578 * 2579 * @param navBarMode the mode of the navigation bar to be set. 2580 */ setNavBarMode(@avBarMode int navBarMode)2581 public void setNavBarMode(@NavBarMode int navBarMode) { 2582 enforceStatusBar(); 2583 enforceValidCallingUser(); 2584 2585 if (navBarMode != NAV_BAR_MODE_DEFAULT && navBarMode != NAV_BAR_MODE_KIDS) { 2586 throw new IllegalArgumentException("Supplied navBarMode not supported: " + navBarMode); 2587 } 2588 2589 final int userId = mCurrentUserId; 2590 final int callingUserId = UserHandle.getUserId(Binder.getCallingUid()); 2591 if (mCurrentUserId != callingUserId && !doesCallerHoldInteractAcrossUserPermission()) { 2592 throw new SecurityException("Calling user id: " + callingUserId 2593 + ", cannot call on behalf of current user id: " + mCurrentUserId + "."); 2594 } 2595 2596 final long userIdentity = Binder.clearCallingIdentity(); 2597 try { 2598 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2599 Settings.Secure.NAV_BAR_KIDS_MODE, navBarMode, userId); 2600 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2601 Settings.Secure.NAV_BAR_FORCE_VISIBLE, navBarMode, userId); 2602 2603 IOverlayManager overlayManager = getOverlayManager(); 2604 if (overlayManager != null && navBarMode == NAV_BAR_MODE_KIDS 2605 && isPackageSupported(NAV_BAR_MODE_3BUTTON_OVERLAY)) { 2606 overlayManager.setEnabledExclusiveInCategory(NAV_BAR_MODE_3BUTTON_OVERLAY, userId); 2607 } 2608 } catch (RemoteException e) { 2609 throw e.rethrowFromSystemServer(); 2610 } finally { 2611 Binder.restoreCallingIdentity(userIdentity); 2612 } 2613 } 2614 2615 /** 2616 * Gets the navigation bar mode. Returns default value if no mode is set. 2617 * 2618 * @hide 2619 */ getNavBarMode()2620 public @NavBarMode int getNavBarMode() { 2621 enforceStatusBar(); 2622 2623 int navBarKidsMode = NAV_BAR_MODE_DEFAULT; 2624 final int userId = mCurrentUserId; 2625 final long userIdentity = Binder.clearCallingIdentity(); 2626 try { 2627 navBarKidsMode = Settings.Secure.getIntForUser(mContext.getContentResolver(), 2628 Settings.Secure.NAV_BAR_KIDS_MODE, userId); 2629 } catch (Settings.SettingNotFoundException ex) { 2630 return navBarKidsMode; 2631 } finally { 2632 Binder.restoreCallingIdentity(userIdentity); 2633 } 2634 return navBarKidsMode; 2635 } 2636 isPackageSupported(String packageName)2637 private boolean isPackageSupported(String packageName) { 2638 if (packageName == null) { 2639 return false; 2640 } 2641 try { 2642 return mContext.getPackageManager().getPackageInfo(packageName, 2643 PackageManager.PackageInfoFlags.of(0)) != null; 2644 } catch (PackageManager.NameNotFoundException ignored) { 2645 if (SPEW) { 2646 Slog.d(TAG, "Package not found: " + packageName); 2647 } 2648 } 2649 return false; 2650 } 2651 2652 /** 2653 * Notifies the system of a new media tap-to-transfer state for the *sender* device. See 2654 * {@link StatusBarManager.updateMediaTapToTransferSenderDisplay} for more information. 2655 * 2656 * @param undoCallback a callback that will be triggered if the user elects to undo a media 2657 * transfer. 2658 * 2659 * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL} 2660 * permission. 2661 */ 2662 @Override updateMediaTapToTransferSenderDisplay( @tatusBarManager.MediaTransferSenderState int displayState, @NonNull MediaRoute2Info routeInfo, @Nullable IUndoMediaTransferCallback undoCallback )2663 public void updateMediaTapToTransferSenderDisplay( 2664 @StatusBarManager.MediaTransferSenderState int displayState, 2665 @NonNull MediaRoute2Info routeInfo, 2666 @Nullable IUndoMediaTransferCallback undoCallback 2667 ) { 2668 enforceMediaContentControl(); 2669 enforceValidCallingUser(); 2670 2671 IStatusBar bar = mBar; 2672 if (bar != null) { 2673 try { 2674 bar.updateMediaTapToTransferSenderDisplay(displayState, routeInfo, undoCallback); 2675 } catch (RemoteException e) { 2676 Slog.e(TAG, "updateMediaTapToTransferSenderDisplay", e); 2677 } 2678 } 2679 } 2680 2681 /** 2682 * Notifies the system of a new media tap-to-transfer state for the *receiver* device. See 2683 * {@link StatusBarManager.updateMediaTapToTransferReceiverDisplay} for more information. 2684 * 2685 * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL} 2686 * permission. 2687 */ 2688 @Override updateMediaTapToTransferReceiverDisplay( @tatusBarManager.MediaTransferReceiverState int displayState, MediaRoute2Info routeInfo, @Nullable Icon appIcon, @Nullable CharSequence appName)2689 public void updateMediaTapToTransferReceiverDisplay( 2690 @StatusBarManager.MediaTransferReceiverState int displayState, 2691 MediaRoute2Info routeInfo, 2692 @Nullable Icon appIcon, 2693 @Nullable CharSequence appName) { 2694 enforceMediaContentControl(); 2695 enforceValidCallingUser(); 2696 2697 IStatusBar bar = mBar; 2698 if (bar != null) { 2699 try { 2700 bar.updateMediaTapToTransferReceiverDisplay( 2701 displayState, routeInfo, appIcon, appName); 2702 } catch (RemoteException e) { 2703 Slog.e(TAG, "updateMediaTapToTransferReceiverDisplay", e); 2704 } 2705 } 2706 } 2707 2708 /** 2709 * Registers a provider that gives information about nearby devices that are able to play media. 2710 * See {@link StatusBarmanager.registerNearbyMediaDevicesProvider}. 2711 * 2712 * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL} 2713 * permission. 2714 * 2715 * @param provider the nearby device information provider to register 2716 * 2717 * @hide 2718 */ 2719 @Override registerNearbyMediaDevicesProvider( @onNull INearbyMediaDevicesProvider provider )2720 public void registerNearbyMediaDevicesProvider( 2721 @NonNull INearbyMediaDevicesProvider provider 2722 ) { 2723 enforceMediaContentControl(); 2724 enforceValidCallingUser(); 2725 2726 IStatusBar bar = mBar; 2727 if (bar != null) { 2728 try { 2729 bar.registerNearbyMediaDevicesProvider(provider); 2730 } catch (RemoteException e) { 2731 Slog.e(TAG, "registerNearbyMediaDevicesProvider", e); 2732 } 2733 } 2734 } 2735 2736 /** 2737 * Unregisters a provider that gives information about nearby devices that are able to play 2738 * media. See {@link StatusBarmanager.unregisterNearbyMediaDevicesProvider}. 2739 * 2740 * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL} 2741 * permission. 2742 * 2743 * @param provider the nearby device information provider to unregister 2744 * 2745 * @hide 2746 */ 2747 @Override unregisterNearbyMediaDevicesProvider( @onNull INearbyMediaDevicesProvider provider )2748 public void unregisterNearbyMediaDevicesProvider( 2749 @NonNull INearbyMediaDevicesProvider provider 2750 ) { 2751 enforceMediaContentControl(); 2752 enforceValidCallingUser(); 2753 2754 IStatusBar bar = mBar; 2755 if (bar != null) { 2756 try { 2757 bar.unregisterNearbyMediaDevicesProvider(provider); 2758 } catch (RemoteException e) { 2759 Slog.e(TAG, "unregisterNearbyMediaDevicesProvider", e); 2760 } 2761 } 2762 } 2763 2764 @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) 2765 @Override showRearDisplayDialog(int currentState)2766 public void showRearDisplayDialog(int currentState) { 2767 enforceControlDeviceStatePermission(); 2768 enforceValidCallingUser(); 2769 2770 IStatusBar bar = mBar; 2771 if (bar != null) { 2772 try { 2773 bar.showRearDisplayDialog(currentState); 2774 } catch (RemoteException e) { 2775 Slog.e(TAG, "showRearDisplayDialog", e); 2776 } 2777 } 2778 } 2779 2780 /** @hide */ passThroughShellCommand(String[] args, FileDescriptor fd)2781 public void passThroughShellCommand(String[] args, FileDescriptor fd) { 2782 enforceStatusBarOrShell(); 2783 if (mBar == null) return; 2784 2785 try (TransferPipe tp = new TransferPipe()) { 2786 // Sending the command to the remote, which needs to execute async to avoid blocking 2787 // See Binder#dumpAsync() for inspiration 2788 tp.setBufferPrefix(" "); 2789 mBar.passThroughShellCommand(args, tp.getWriteFd()); 2790 // Times out after 5s 2791 tp.go(fd); 2792 } catch (Throwable t) { 2793 Slog.e(TAG, "Error sending command to IStatusBar", t); 2794 } 2795 } 2796 2797 // ================================================================================ 2798 // Can be called from any thread 2799 // ================================================================================ 2800 2801 // lock on mDisableRecords manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which)2802 void manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which) { 2803 if (SPEW) { 2804 Slog.d(TAG, "manageDisableList userId=" + userId 2805 + " what=0x" + Integer.toHexString(what) + " pkg=" + pkg); 2806 } 2807 2808 // Find matching record, if any 2809 Pair<Integer, DisableRecord> match = findMatchingRecordLocked(token, userId); 2810 int i = match.first; 2811 DisableRecord record = match.second; 2812 2813 // Remove record if binder is already dead 2814 if (!token.isBinderAlive()) { 2815 if (record != null) { 2816 mDisableRecords.remove(i); 2817 record.token.unlinkToDeath(record, 0); 2818 } 2819 return; 2820 } 2821 2822 // Update existing record 2823 if (record != null) { 2824 record.setFlags(what, which, pkg); 2825 if (record.isEmpty()) { 2826 mDisableRecords.remove(i); 2827 record.token.unlinkToDeath(record, 0); 2828 } 2829 return; 2830 } 2831 2832 // Record doesn't exist, so we create a new one 2833 record = new DisableRecord(userId, token); 2834 record.setFlags(what, which, pkg); 2835 mDisableRecords.add(record); 2836 } 2837 2838 @Nullable 2839 @GuardedBy("mLock") findMatchingRecordLocked(IBinder token, int userId)2840 private Pair<Integer, DisableRecord> findMatchingRecordLocked(IBinder token, int userId) { 2841 final int numRecords = mDisableRecords.size(); 2842 DisableRecord record = null; 2843 int i; 2844 for (i = 0; i < numRecords; i++) { 2845 DisableRecord r = mDisableRecords.get(i); 2846 if (r.token == token && r.userId == userId) { 2847 record = r; 2848 break; 2849 } 2850 } 2851 2852 return new Pair<Integer, DisableRecord>(i, record); 2853 } 2854 2855 // lock on mDisableRecords gatherDisableActionsLocked(int userId, int which)2856 int gatherDisableActionsLocked(int userId, int which) { 2857 final int N = mDisableRecords.size(); 2858 // gather the new net flags 2859 int net = 0; 2860 for (int i=0; i<N; i++) { 2861 final DisableRecord rec = mDisableRecords.get(i); 2862 if (rec.userId == userId) { 2863 net |= rec.getFlags(which); 2864 } 2865 } 2866 return net; 2867 } 2868 2869 // ================================================================================ 2870 // Always called from UI thread 2871 // ================================================================================ 2872 dump(FileDescriptor fd, PrintWriter pw, String[] args)2873 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2874 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 2875 boolean proto = false; 2876 for (int i = 0; i < args.length; i++) { 2877 if ("--proto".equals(args[i])) { 2878 proto = true; 2879 } 2880 } 2881 if (proto) { 2882 if (mBar == null) return; 2883 try (TransferPipe tp = new TransferPipe()) { 2884 // Sending the command to the remote, which needs to execute async to avoid blocking 2885 // See Binder#dumpAsync() for inspiration 2886 mBar.dumpProto(args, tp.getWriteFd()); 2887 // Times out after 5s 2888 tp.go(fd); 2889 } catch (Throwable t) { 2890 Slog.e(TAG, "Error sending command to IStatusBar", t); 2891 } 2892 return; 2893 } 2894 2895 synchronized (mLock) { 2896 for (int i = 0; i < mDisplayUiState.size(); i++) { 2897 final int key = mDisplayUiState.keyAt(i); 2898 final UiState state = mDisplayUiState.get(key); 2899 pw.println(" displayId=" + key); 2900 pw.println(" mDisabled1=0x" + Integer.toHexString(state.getDisabled1())); 2901 pw.println(" mDisabled2=0x" + Integer.toHexString(state.getDisabled2())); 2902 } 2903 final int N = mDisableRecords.size(); 2904 pw.println(" mDisableRecords.size=" + N); 2905 for (int i=0; i<N; i++) { 2906 DisableRecord tok = mDisableRecords.get(i); 2907 pw.println(" [" + i + "] " + tok); 2908 } 2909 pw.println(" mCurrentUserId=" + mCurrentUserId); 2910 pw.println(" mIcons="); 2911 for (String slot : mIcons.keySet()) { 2912 pw.println(" "); 2913 pw.print(slot); 2914 pw.print(" -> "); 2915 final StatusBarIcon icon = mIcons.get(slot); 2916 pw.print(icon); 2917 if (!TextUtils.isEmpty(icon.contentDescription)) { 2918 pw.print(" \""); 2919 pw.print(icon.contentDescription); 2920 pw.print("\""); 2921 } 2922 pw.println(); 2923 } 2924 ArrayList<String> requests; 2925 synchronized (mCurrentRequestAddTilePackages) { 2926 requests = new ArrayList<>(mCurrentRequestAddTilePackages.keySet()); 2927 } 2928 pw.println(" mCurrentRequestAddTilePackages=["); 2929 final int reqN = requests.size(); 2930 for (int i = 0; i < reqN; i++) { 2931 pw.println(" " + requests.get(i) + ","); 2932 } 2933 pw.println(" ]"); 2934 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 2935 mTileRequestTracker.dump(fd, ipw.increaseIndent(), args); 2936 } 2937 } 2938 getUiContext()2939 private static final Context getUiContext() { 2940 return ActivityThread.currentActivityThread().getSystemUiContext(); 2941 } 2942 2943 /** 2944 * This method validates whether the calling user is allowed to control the status bar 2945 * on a device that enables visible background users. 2946 * Only system or current user or the user that belongs to the same profile group as the 2947 * current user is permitted to control the status bar. 2948 */ enforceValidCallingUser()2949 private void enforceValidCallingUser() { 2950 if (!mVisibleBackgroundUsersEnabled) { 2951 return; 2952 } 2953 2954 int callingUserId = getCallingUserId(); 2955 if (callingUserId == USER_SYSTEM || callingUserId == mCurrentUserId) { 2956 return; 2957 } 2958 if (!isVisibleBackgroundUser(callingUserId)) { 2959 return; 2960 } 2961 2962 throw new SecurityException("User " + callingUserId 2963 + " is not permitted to use this method"); 2964 } 2965 isVisibleBackgroundUser(int userId)2966 private boolean isVisibleBackgroundUser(int userId) { 2967 if (!mVisibleBackgroundUsersEnabled) { 2968 return false; 2969 } 2970 // The main use case for visible background users is the Automotive multi-display 2971 // configuration where a passenger can use a secondary display while the driver is 2972 // using the main display. 2973 // TODO(b/341604160) - Support visible background users properly and remove carve outs 2974 return mUserManagerInternal.isVisibleBackgroundFullUser(userId); 2975 } 2976 isVisibleBackgroundUserOnDisplay(int displayId)2977 private boolean isVisibleBackgroundUserOnDisplay(int displayId) { 2978 if (!mVisibleBackgroundUsersEnabled) { 2979 return false; 2980 } 2981 int userId = mUserManagerInternal.getUserAssignedToDisplay(displayId); 2982 return isVisibleBackgroundUser(userId); 2983 } 2984 }