StatusBarManagerService.java revision f2efdd8c7ca65745245a0ac26c681a8d376adb87
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 17package com.android.server.statusbar; 18 19import android.app.StatusBarManager; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.pm.PackageManager; 23import android.graphics.Rect; 24import android.os.Binder; 25import android.os.Bundle; 26import android.os.Handler; 27import android.os.IBinder; 28import android.os.Process; 29import android.os.RemoteException; 30import android.os.ResultReceiver; 31import android.os.UserHandle; 32import android.util.ArrayMap; 33import android.util.Slog; 34import com.android.internal.statusbar.IStatusBar; 35import com.android.internal.statusbar.IStatusBarService; 36import com.android.internal.statusbar.NotificationVisibility; 37import com.android.internal.statusbar.StatusBarIcon; 38import com.android.internal.util.FastPrintWriter; 39import com.android.server.LocalServices; 40import com.android.server.notification.NotificationDelegate; 41import com.android.server.wm.WindowManagerService; 42 43import java.io.FileDescriptor; 44import java.io.FileOutputStream; 45import java.io.PrintWriter; 46import java.util.ArrayList; 47import java.util.List; 48 49 50/** 51 * A note on locking: We rely on the fact that calls onto mBar are oneway or 52 * if they are local, that they just enqueue messages to not deadlock. 53 */ 54public class StatusBarManagerService extends IStatusBarService.Stub { 55 private static final String TAG = "StatusBarManagerService"; 56 private static final boolean SPEW = false; 57 58 private final Context mContext; 59 private final WindowManagerService mWindowManager; 60 private Handler mHandler = new Handler(); 61 private NotificationDelegate mNotificationDelegate; 62 private volatile IStatusBar mBar; 63 private ArrayMap<String, StatusBarIcon> mIcons = new ArrayMap<>(); 64 65 // for disabling the status bar 66 private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); 67 private IBinder mSysUiVisToken = new Binder(); 68 private int mDisabled1 = 0; 69 private int mDisabled2 = 0; 70 71 private final Object mLock = new Object(); 72 // encompasses lights-out mode and other flags defined on View 73 private int mSystemUiVisibility = 0; 74 private int mFullscreenStackSysUiVisibility; 75 private int mDockedStackSysUiVisibility; 76 private final Rect mFullscreenStackBounds = new Rect(); 77 private final Rect mDockedStackBounds = new Rect(); 78 private boolean mMenuVisible = false; 79 private int mImeWindowVis = 0; 80 private int mImeBackDisposition; 81 private boolean mShowImeSwitcher; 82 private IBinder mImeToken = null; 83 private int mCurrentUserId; 84 85 private class DisableRecord implements IBinder.DeathRecipient { 86 int userId; 87 String pkg; 88 int what1; 89 int what2; 90 IBinder token; 91 92 public void binderDied() { 93 Slog.i(TAG, "binder died for pkg=" + pkg); 94 disableForUser(0, token, pkg, userId); 95 disable2ForUser(0, token, pkg, userId); 96 token.unlinkToDeath(this, 0); 97 } 98 } 99 100 /** 101 * Construct the service, add the status bar view to the window manager 102 */ 103 public StatusBarManagerService(Context context, WindowManagerService windowManager) { 104 mContext = context; 105 mWindowManager = windowManager; 106 107 LocalServices.addService(StatusBarManagerInternal.class, mInternalService); 108 } 109 110 /** 111 * Private API used by NotificationManagerService. 112 */ 113 private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { 114 private boolean mNotificationLightOn; 115 116 @Override 117 public void setNotificationDelegate(NotificationDelegate delegate) { 118 mNotificationDelegate = delegate; 119 } 120 121 @Override 122 public void buzzBeepBlinked() { 123 if (mBar != null) { 124 try { 125 mBar.buzzBeepBlinked(); 126 } catch (RemoteException ex) { 127 } 128 } 129 } 130 131 @Override 132 public void notificationLightPulse(int argb, int onMillis, int offMillis) { 133 mNotificationLightOn = true; 134 if (mBar != null) { 135 try { 136 mBar.notificationLightPulse(argb, onMillis, offMillis); 137 } catch (RemoteException ex) { 138 } 139 } 140 } 141 142 @Override 143 public void notificationLightOff() { 144 if (mNotificationLightOn) { 145 mNotificationLightOn = false; 146 if (mBar != null) { 147 try { 148 mBar.notificationLightOff(); 149 } catch (RemoteException ex) { 150 } 151 } 152 } 153 } 154 155 @Override 156 public void showScreenPinningRequest(int taskId) { 157 if (mBar != null) { 158 try { 159 mBar.showScreenPinningRequest(taskId); 160 } catch (RemoteException e) { 161 } 162 } 163 } 164 165 @Override 166 public void showAssistDisclosure() { 167 if (mBar != null) { 168 try { 169 mBar.showAssistDisclosure(); 170 } catch (RemoteException e) { 171 } 172 } 173 } 174 175 @Override 176 public void startAssist(Bundle args) { 177 if (mBar != null) { 178 try { 179 mBar.startAssist(args); 180 } catch (RemoteException e) { 181 } 182 } 183 } 184 185 @Override 186 public void onCameraLaunchGestureDetected(int source) { 187 if (mBar != null) { 188 try { 189 mBar.onCameraLaunchGestureDetected(source); 190 } catch (RemoteException e) { 191 } 192 } 193 } 194 195 @Override 196 public void topAppWindowChanged(boolean menuVisible) { 197 StatusBarManagerService.this.topAppWindowChanged(menuVisible); 198 } 199 200 @Override 201 public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, 202 int mask, 203 Rect fullscreenBounds, Rect dockedBounds, String cause) { 204 StatusBarManagerService.this.setSystemUiVisibility(vis, fullscreenStackVis, 205 dockedStackVis, mask, fullscreenBounds, dockedBounds, cause); 206 } 207 208 @Override 209 public void toggleSplitScreen() { 210 enforceStatusBarService(); 211 if (mBar != null) { 212 try { 213 mBar.toggleSplitScreen(); 214 } catch (RemoteException ex) {} 215 } 216 } 217 218 public void appTransitionFinished() { 219 enforceStatusBarService(); 220 if (mBar != null) { 221 try { 222 mBar.appTransitionFinished(); 223 } catch (RemoteException ex) {} 224 } 225 } 226 227 @Override 228 public void toggleRecentApps() { 229 if (mBar != null) { 230 try { 231 mBar.toggleRecentApps(); 232 } catch (RemoteException ex) {} 233 } 234 } 235 236 @Override 237 public void setCurrentUser(int newUserId) { 238 if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId); 239 mCurrentUserId = newUserId; 240 } 241 242 243 @Override 244 public void preloadRecentApps() { 245 if (mBar != null) { 246 try { 247 mBar.preloadRecentApps(); 248 } catch (RemoteException ex) {} 249 } 250 } 251 252 @Override 253 public void cancelPreloadRecentApps() { 254 if (mBar != null) { 255 try { 256 mBar.cancelPreloadRecentApps(); 257 } catch (RemoteException ex) {} 258 } 259 } 260 261 @Override 262 public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 263 if (mBar != null) { 264 try { 265 mBar.showRecentApps(triggeredFromAltTab, fromHome); 266 } catch (RemoteException ex) {} 267 } 268 } 269 270 @Override 271 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 272 if (mBar != null) { 273 try { 274 mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey); 275 } catch (RemoteException ex) {} 276 } 277 } 278 279 @Override 280 public void toggleKeyboardShortcutsMenu(int deviceId) { 281 if (mBar != null) { 282 try { 283 mBar.toggleKeyboardShortcutsMenu(deviceId); 284 } catch (RemoteException ex) {} 285 } 286 } 287 288 @Override 289 public void requestTvPictureInPicture() { 290 if (mBar != null) { 291 try { 292 mBar.requestTvPictureInPicture(); 293 } catch (RemoteException ex) {} 294 } 295 } 296 297 @Override 298 public void setWindowState(int window, int state) { 299 if (mBar != null) { 300 try { 301 mBar.setWindowState(window, state); 302 } catch (RemoteException ex) {} 303 } 304 } 305 306 @Override 307 public void appTransitionPending() { 308 if (mBar != null) { 309 try { 310 mBar.appTransitionPending(); 311 } catch (RemoteException ex) {} 312 } 313 } 314 315 @Override 316 public void appTransitionCancelled() { 317 if (mBar != null) { 318 try { 319 mBar.appTransitionCancelled(); 320 } catch (RemoteException ex) {} 321 } 322 } 323 324 @Override 325 public void appTransitionStarting(long statusBarAnimationsStartTime, 326 long statusBarAnimationsDuration) { 327 if (mBar != null) { 328 try { 329 mBar.appTransitionStarting( 330 statusBarAnimationsStartTime, statusBarAnimationsDuration); 331 } catch (RemoteException ex) {} 332 } 333 } 334 }; 335 336 // ================================================================================ 337 // From IStatusBarService 338 // ================================================================================ 339 @Override 340 public void expandNotificationsPanel() { 341 enforceExpandStatusBar(); 342 343 if (mBar != null) { 344 try { 345 mBar.animateExpandNotificationsPanel(); 346 } catch (RemoteException ex) { 347 } 348 } 349 } 350 351 @Override 352 public void collapsePanels() { 353 enforceExpandStatusBar(); 354 355 if (mBar != null) { 356 try { 357 mBar.animateCollapsePanels(); 358 } catch (RemoteException ex) { 359 } 360 } 361 } 362 363 @Override 364 public void expandSettingsPanel(String subPanel) { 365 enforceExpandStatusBar(); 366 367 if (mBar != null) { 368 try { 369 mBar.animateExpandSettingsPanel(subPanel); 370 } catch (RemoteException ex) { 371 } 372 } 373 } 374 375 public void addTile(ComponentName component) { 376 enforceStatusBarOrShell(); 377 378 if (mBar != null) { 379 try { 380 mBar.addQsTile(component); 381 } catch (RemoteException ex) { 382 } 383 } 384 } 385 386 public void remTile(ComponentName component) { 387 enforceStatusBarOrShell(); 388 389 if (mBar != null) { 390 try { 391 mBar.remQsTile(component); 392 } catch (RemoteException ex) { 393 } 394 } 395 } 396 397 public void clickTile(ComponentName component) { 398 enforceStatusBarOrShell(); 399 400 if (mBar != null) { 401 try { 402 mBar.clickQsTile(component); 403 } catch (RemoteException ex) { 404 } 405 } 406 } 407 408 @Override 409 public void disable(int what, IBinder token, String pkg) { 410 disableForUser(what, token, pkg, mCurrentUserId); 411 } 412 413 @Override 414 public void disableForUser(int what, IBinder token, String pkg, int userId) { 415 enforceStatusBar(); 416 417 synchronized (mLock) { 418 disableLocked(userId, what, token, pkg, 1); 419 } 420 } 421 422 /** 423 * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. 424 * To re-enable everything, pass {@link #DISABLE_NONE}. 425 * 426 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 427 */ 428 @Override 429 public void disable2(int what, IBinder token, String pkg) { 430 disable2ForUser(what, token, pkg, mCurrentUserId); 431 } 432 433 /** 434 * Disable additional status bar features for a given user. Pass the bitwise-or of the 435 * DISABLE2_* flags. To re-enable everything, pass {@link #DISABLE_NONE}. 436 * 437 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 438 */ 439 @Override 440 public void disable2ForUser(int what, IBinder token, String pkg, int userId) { 441 enforceStatusBar(); 442 443 synchronized (mLock) { 444 disableLocked(userId, what, token, pkg, 2); 445 } 446 } 447 448 private void disableLocked(int userId, int what, IBinder token, String pkg, int whichFlag) { 449 // It's important that the the callback and the call to mBar get done 450 // in the same order when multiple threads are calling this function 451 // so they are paired correctly. The messages on the handler will be 452 // handled in the order they were enqueued, but will be outside the lock. 453 manageDisableListLocked(userId, what, token, pkg, whichFlag); 454 455 // Ensure state for the current user is applied, even if passed a non-current user. 456 final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1); 457 final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2); 458 if (net1 != mDisabled1 || net2 != mDisabled2) { 459 mDisabled1 = net1; 460 mDisabled2 = net2; 461 mHandler.post(new Runnable() { 462 public void run() { 463 mNotificationDelegate.onSetDisabled(net1); 464 } 465 }); 466 if (mBar != null) { 467 try { 468 mBar.disable(net1, net2); 469 } catch (RemoteException ex) { 470 } 471 } 472 } 473 } 474 475 @Override 476 public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, 477 String contentDescription) { 478 enforceStatusBar(); 479 480 synchronized (mIcons) { 481 StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId, 482 iconLevel, 0, contentDescription); 483 //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon); 484 mIcons.put(slot, icon); 485 486 if (mBar != null) { 487 try { 488 mBar.setIcon(slot, icon); 489 } catch (RemoteException ex) { 490 } 491 } 492 } 493 } 494 495 @Override 496 public void setIconVisibility(String slot, boolean visibility) { 497 enforceStatusBar(); 498 499 synchronized (mIcons) { 500 StatusBarIcon icon = mIcons.get(slot); 501 if (icon == null) { 502 return; 503 } 504 if (icon.visible != visibility) { 505 icon.visible = visibility; 506 507 if (mBar != null) { 508 try { 509 mBar.setIcon(slot, icon); 510 } catch (RemoteException ex) { 511 } 512 } 513 } 514 } 515 } 516 517 @Override 518 public void removeIcon(String slot) { 519 enforceStatusBar(); 520 521 synchronized (mIcons) { 522 mIcons.remove(slot); 523 524 if (mBar != null) { 525 try { 526 mBar.removeIcon(slot); 527 } catch (RemoteException ex) { 528 } 529 } 530 } 531 } 532 533 /** 534 * Hide or show the on-screen Menu key. Only call this from the window manager, typically in 535 * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set 536 * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}. 537 */ 538 private void topAppWindowChanged(final boolean menuVisible) { 539 enforceStatusBar(); 540 541 if (SPEW) Slog.d(TAG, (menuVisible?"showing":"hiding") + " MENU key"); 542 543 synchronized(mLock) { 544 mMenuVisible = menuVisible; 545 mHandler.post(new Runnable() { 546 public void run() { 547 if (mBar != null) { 548 try { 549 mBar.topAppWindowChanged(menuVisible); 550 } catch (RemoteException ex) { 551 } 552 } 553 } 554 }); 555 } 556 } 557 558 @Override 559 public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition, 560 final boolean showImeSwitcher) { 561 enforceStatusBar(); 562 563 if (SPEW) { 564 Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); 565 } 566 567 synchronized(mLock) { 568 // In case of IME change, we need to call up setImeWindowStatus() regardless of 569 // mImeWindowVis because mImeWindowVis may not have been set to false when the 570 // previous IME was destroyed. 571 mImeWindowVis = vis; 572 mImeBackDisposition = backDisposition; 573 mImeToken = token; 574 mShowImeSwitcher = showImeSwitcher; 575 mHandler.post(new Runnable() { 576 public void run() { 577 if (mBar != null) { 578 try { 579 mBar.setImeWindowStatus(token, vis, backDisposition, showImeSwitcher); 580 } catch (RemoteException ex) { 581 } 582 } 583 } 584 }); 585 } 586 } 587 588 @Override 589 public void setSystemUiVisibility(int vis, int mask, String cause) { 590 setSystemUiVisibility(vis, 0, 0, mask, mFullscreenStackBounds, mDockedStackBounds, cause); 591 } 592 593 private void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, 594 Rect fullscreenBounds, Rect dockedBounds, String cause) { 595 // also allows calls from window manager which is in this process. 596 enforceStatusBarService(); 597 598 if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")"); 599 600 synchronized (mLock) { 601 updateUiVisibilityLocked(vis, fullscreenStackVis, dockedStackVis, mask, 602 fullscreenBounds, dockedBounds); 603 disableLocked( 604 mCurrentUserId, 605 vis & StatusBarManager.DISABLE_MASK, 606 mSysUiVisToken, 607 cause, 1); 608 } 609 } 610 611 private void updateUiVisibilityLocked(final int vis, 612 final int fullscreenStackVis, final int dockedStackVis, final int mask, 613 final Rect fullscreenBounds, final Rect dockedBounds) { 614 if (mSystemUiVisibility != vis 615 || mFullscreenStackSysUiVisibility != fullscreenStackVis 616 || mDockedStackSysUiVisibility != dockedStackVis 617 || !mFullscreenStackBounds.equals(fullscreenBounds) 618 || !mDockedStackBounds.equals(dockedBounds)) { 619 mSystemUiVisibility = vis; 620 mFullscreenStackSysUiVisibility = fullscreenStackVis; 621 mDockedStackSysUiVisibility = dockedStackVis; 622 mFullscreenStackBounds.set(fullscreenBounds); 623 mDockedStackBounds.set(dockedBounds); 624 mHandler.post(new Runnable() { 625 public void run() { 626 if (mBar != null) { 627 try { 628 mBar.setSystemUiVisibility(vis, fullscreenStackVis, dockedStackVis, 629 mask, fullscreenBounds, dockedBounds); 630 } catch (RemoteException ex) { 631 } 632 } 633 } 634 }); 635 } 636 } 637 638 private void enforceStatusBarOrShell() { 639 if (Binder.getCallingUid() == Process.SHELL_UID) { 640 return; 641 } 642 enforceStatusBar(); 643 } 644 645 private void enforceStatusBar() { 646 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR, 647 "StatusBarManagerService"); 648 } 649 650 private void enforceExpandStatusBar() { 651 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.EXPAND_STATUS_BAR, 652 "StatusBarManagerService"); 653 } 654 655 private void enforceStatusBarService() { 656 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 657 "StatusBarManagerService"); 658 } 659 660 // ================================================================================ 661 // Callbacks from the status bar service. 662 // ================================================================================ 663 @Override 664 public void registerStatusBar(IStatusBar bar, List<String> iconSlots, 665 List<StatusBarIcon> iconList, int switches[], List<IBinder> binders, 666 Rect fullscreenStackBounds, Rect dockedStackBounds) { 667 enforceStatusBarService(); 668 669 Slog.i(TAG, "registerStatusBar bar=" + bar); 670 mBar = bar; 671 synchronized (mIcons) { 672 for (String slot : mIcons.keySet()) { 673 iconSlots.add(slot); 674 iconList.add(mIcons.get(slot)); 675 } 676 } 677 synchronized (mLock) { 678 switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1); 679 switches[1] = mSystemUiVisibility; 680 switches[2] = mMenuVisible ? 1 : 0; 681 switches[3] = mImeWindowVis; 682 switches[4] = mImeBackDisposition; 683 switches[5] = mShowImeSwitcher ? 1 : 0; 684 switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2); 685 switches[7] = mFullscreenStackSysUiVisibility; 686 switches[8] = mDockedStackSysUiVisibility; 687 binders.add(mImeToken); 688 fullscreenStackBounds.set(mFullscreenStackBounds); 689 dockedStackBounds.set(mDockedStackBounds); 690 } 691 } 692 693 /** 694 * @param clearNotificationEffects whether to consider notifications as "shown" and stop 695 * LED, vibration, and ringing 696 */ 697 @Override 698 public void onPanelRevealed(boolean clearNotificationEffects, int numItems) { 699 enforceStatusBarService(); 700 long identity = Binder.clearCallingIdentity(); 701 try { 702 mNotificationDelegate.onPanelRevealed(clearNotificationEffects, numItems); 703 } finally { 704 Binder.restoreCallingIdentity(identity); 705 } 706 } 707 708 @Override 709 public void clearNotificationEffects() throws RemoteException { 710 enforceStatusBarService(); 711 long identity = Binder.clearCallingIdentity(); 712 try { 713 mNotificationDelegate.clearEffects(); 714 } finally { 715 Binder.restoreCallingIdentity(identity); 716 } 717 } 718 719 @Override 720 public void onPanelHidden() throws RemoteException { 721 enforceStatusBarService(); 722 long identity = Binder.clearCallingIdentity(); 723 try { 724 mNotificationDelegate.onPanelHidden(); 725 } finally { 726 Binder.restoreCallingIdentity(identity); 727 } 728 } 729 730 @Override 731 public void onNotificationClick(String key) { 732 enforceStatusBarService(); 733 final int callingUid = Binder.getCallingUid(); 734 final int callingPid = Binder.getCallingPid(); 735 long identity = Binder.clearCallingIdentity(); 736 try { 737 mNotificationDelegate.onNotificationClick(callingUid, callingPid, key); 738 } finally { 739 Binder.restoreCallingIdentity(identity); 740 } 741 } 742 743 @Override 744 public void onNotificationActionClick(String key, int actionIndex) { 745 enforceStatusBarService(); 746 final int callingUid = Binder.getCallingUid(); 747 final int callingPid = Binder.getCallingPid(); 748 long identity = Binder.clearCallingIdentity(); 749 try { 750 mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key, 751 actionIndex); 752 } finally { 753 Binder.restoreCallingIdentity(identity); 754 } 755 } 756 757 @Override 758 public void onNotificationError(String pkg, String tag, int id, 759 int uid, int initialPid, String message, int userId) { 760 enforceStatusBarService(); 761 final int callingUid = Binder.getCallingUid(); 762 final int callingPid = Binder.getCallingPid(); 763 long identity = Binder.clearCallingIdentity(); 764 try { 765 // WARNING: this will call back into us to do the remove. Don't hold any locks. 766 mNotificationDelegate.onNotificationError(callingUid, callingPid, 767 pkg, tag, id, uid, initialPid, message, userId); 768 } finally { 769 Binder.restoreCallingIdentity(identity); 770 } 771 } 772 773 @Override 774 public void onNotificationClear(String pkg, String tag, int id, int userId) { 775 enforceStatusBarService(); 776 final int callingUid = Binder.getCallingUid(); 777 final int callingPid = Binder.getCallingPid(); 778 long identity = Binder.clearCallingIdentity(); 779 try { 780 mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId); 781 } finally { 782 Binder.restoreCallingIdentity(identity); 783 } 784 } 785 786 @Override 787 public void onNotificationVisibilityChanged( 788 NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys) 789 throws RemoteException { 790 enforceStatusBarService(); 791 long identity = Binder.clearCallingIdentity(); 792 try { 793 mNotificationDelegate.onNotificationVisibilityChanged( 794 newlyVisibleKeys, noLongerVisibleKeys); 795 } finally { 796 Binder.restoreCallingIdentity(identity); 797 } 798 } 799 800 @Override 801 public void onNotificationExpansionChanged(String key, boolean userAction, 802 boolean expanded) throws RemoteException { 803 enforceStatusBarService(); 804 long identity = Binder.clearCallingIdentity(); 805 try { 806 mNotificationDelegate.onNotificationExpansionChanged( 807 key, userAction, expanded); 808 } finally { 809 Binder.restoreCallingIdentity(identity); 810 } 811 } 812 813 @Override 814 public void onClearAllNotifications(int userId) { 815 enforceStatusBarService(); 816 final int callingUid = Binder.getCallingUid(); 817 final int callingPid = Binder.getCallingPid(); 818 long identity = Binder.clearCallingIdentity(); 819 try { 820 mNotificationDelegate.onClearAll(callingUid, callingPid, userId); 821 } finally { 822 Binder.restoreCallingIdentity(identity); 823 } 824 } 825 826 @Override 827 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 828 String[] args, ResultReceiver resultReceiver) throws RemoteException { 829 (new StatusBarShellCommand(this)).exec( 830 this, in, out, err, args, resultReceiver); 831 } 832 833 // ================================================================================ 834 // Can be called from any thread 835 // ================================================================================ 836 837 // lock on mDisableRecords 838 void manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which) { 839 if (SPEW) { 840 Slog.d(TAG, "manageDisableList userId=" + userId 841 + " what=0x" + Integer.toHexString(what) + " pkg=" + pkg); 842 } 843 // update the list 844 final int N = mDisableRecords.size(); 845 DisableRecord tok = null; 846 int i; 847 for (i=0; i<N; i++) { 848 DisableRecord t = mDisableRecords.get(i); 849 if (t.token == token && t.userId == userId) { 850 tok = t; 851 break; 852 } 853 } 854 if (what == 0 || !token.isBinderAlive()) { 855 if (tok != null) { 856 mDisableRecords.remove(i); 857 tok.token.unlinkToDeath(tok, 0); 858 } 859 } else { 860 if (tok == null) { 861 tok = new DisableRecord(); 862 tok.userId = userId; 863 try { 864 token.linkToDeath(tok, 0); 865 } 866 catch (RemoteException ex) { 867 return; // give up 868 } 869 mDisableRecords.add(tok); 870 } 871 if (which == 1) { 872 tok.what1 = what; 873 } else { 874 tok.what2 = what; 875 } 876 tok.token = token; 877 tok.pkg = pkg; 878 } 879 } 880 881 // lock on mDisableRecords 882 int gatherDisableActionsLocked(int userId, int which) { 883 final int N = mDisableRecords.size(); 884 // gather the new net flags 885 int net = 0; 886 for (int i=0; i<N; i++) { 887 final DisableRecord rec = mDisableRecords.get(i); 888 if (rec.userId == userId) { 889 net |= (which == 1) ? rec.what1 : rec.what2; 890 } 891 } 892 return net; 893 } 894 895 // ================================================================================ 896 // Always called from UI thread 897 // ================================================================================ 898 899 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 900 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 901 != PackageManager.PERMISSION_GRANTED) { 902 pw.println("Permission Denial: can't dump StatusBar from from pid=" 903 + Binder.getCallingPid() 904 + ", uid=" + Binder.getCallingUid()); 905 return; 906 } 907 908 synchronized (mLock) { 909 pw.println(" mDisabled1=0x" + Integer.toHexString(mDisabled1)); 910 pw.println(" mDisabled2=0x" + Integer.toHexString(mDisabled2)); 911 final int N = mDisableRecords.size(); 912 pw.println(" mDisableRecords.size=" + N); 913 for (int i=0; i<N; i++) { 914 DisableRecord tok = mDisableRecords.get(i); 915 pw.println(" [" + i + "] userId=" + tok.userId 916 + " what1=0x" + Integer.toHexString(tok.what1) 917 + " what2=0x" + Integer.toHexString(tok.what2) 918 + " pkg=" + tok.pkg 919 + " token=" + tok.token); 920 } 921 pw.println(" mCurrentUserId=" + mCurrentUserId); 922 } 923 } 924} 925