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