StatusBarManagerService.java revision 681fc7b2670542aae0f3b9ef8f6c7a88db984ea9
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 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 228 // ================================================================================ 229 // From IStatusBarService 230 // ================================================================================ 231 @Override 232 public void expandNotificationsPanel() { 233 enforceExpandStatusBar(); 234 235 if (mBar != null) { 236 try { 237 mBar.animateExpandNotificationsPanel(); 238 } catch (RemoteException ex) { 239 } 240 } 241 } 242 243 @Override 244 public void collapsePanels() { 245 enforceExpandStatusBar(); 246 247 if (mBar != null) { 248 try { 249 mBar.animateCollapsePanels(); 250 } catch (RemoteException ex) { 251 } 252 } 253 } 254 255 @Override 256 public void expandSettingsPanel(String subPanel) { 257 enforceExpandStatusBar(); 258 259 if (mBar != null) { 260 try { 261 mBar.animateExpandSettingsPanel(subPanel); 262 } catch (RemoteException ex) { 263 } 264 } 265 } 266 267 public void addTile(ComponentName component) { 268 enforceStatusBarOrShell(); 269 270 if (mBar != null) { 271 try { 272 mBar.addQsTile(component); 273 } catch (RemoteException ex) { 274 } 275 } 276 } 277 278 public void remTile(ComponentName component) { 279 enforceStatusBarOrShell(); 280 281 if (mBar != null) { 282 try { 283 mBar.remQsTile(component); 284 } catch (RemoteException ex) { 285 } 286 } 287 } 288 289 public void clickTile(ComponentName component) { 290 enforceStatusBarOrShell(); 291 292 if (mBar != null) { 293 try { 294 mBar.clickQsTile(component); 295 } catch (RemoteException ex) { 296 } 297 } 298 } 299 300 @Override 301 public void disable(int what, IBinder token, String pkg) { 302 disableForUser(what, token, pkg, mCurrentUserId); 303 } 304 305 @Override 306 public void disableForUser(int what, IBinder token, String pkg, int userId) { 307 enforceStatusBar(); 308 309 synchronized (mLock) { 310 disableLocked(userId, what, token, pkg, 1); 311 } 312 } 313 314 /** 315 * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. 316 * To re-enable everything, pass {@link #DISABLE_NONE}. 317 * 318 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 319 */ 320 @Override 321 public void disable2(int what, IBinder token, String pkg) { 322 disable2ForUser(what, token, pkg, mCurrentUserId); 323 } 324 325 /** 326 * Disable additional status bar features for a given user. Pass the bitwise-or of the 327 * DISABLE2_* flags. To re-enable everything, pass {@link #DISABLE_NONE}. 328 * 329 * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. 330 */ 331 @Override 332 public void disable2ForUser(int what, IBinder token, String pkg, int userId) { 333 enforceStatusBar(); 334 335 synchronized (mLock) { 336 disableLocked(userId, what, token, pkg, 2); 337 } 338 } 339 340 private void disableLocked(int userId, int what, IBinder token, String pkg, int whichFlag) { 341 // It's important that the the callback and the call to mBar get done 342 // in the same order when multiple threads are calling this function 343 // so they are paired correctly. The messages on the handler will be 344 // handled in the order they were enqueued, but will be outside the lock. 345 manageDisableListLocked(userId, what, token, pkg, whichFlag); 346 347 // Ensure state for the current user is applied, even if passed a non-current user. 348 final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1); 349 final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2); 350 if (net1 != mDisabled1 || net2 != mDisabled2) { 351 mDisabled1 = net1; 352 mDisabled2 = net2; 353 mHandler.post(new Runnable() { 354 public void run() { 355 mNotificationDelegate.onSetDisabled(net1); 356 } 357 }); 358 if (mBar != null) { 359 try { 360 mBar.disable(net1, net2); 361 } catch (RemoteException ex) { 362 } 363 } 364 } 365 } 366 367 @Override 368 public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, 369 String contentDescription) { 370 enforceStatusBar(); 371 372 synchronized (mIcons) { 373 StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId, 374 iconLevel, 0, contentDescription); 375 //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon); 376 mIcons.put(slot, icon); 377 378 if (mBar != null) { 379 try { 380 mBar.setIcon(slot, icon); 381 } catch (RemoteException ex) { 382 } 383 } 384 } 385 } 386 387 @Override 388 public void setIconVisibility(String slot, boolean visibility) { 389 enforceStatusBar(); 390 391 synchronized (mIcons) { 392 StatusBarIcon icon = mIcons.get(slot); 393 if (icon == null) { 394 return; 395 } 396 if (icon.visible != visibility) { 397 icon.visible = visibility; 398 399 if (mBar != null) { 400 try { 401 mBar.setIcon(slot, icon); 402 } catch (RemoteException ex) { 403 } 404 } 405 } 406 } 407 } 408 409 @Override 410 public void removeIcon(String slot) { 411 enforceStatusBar(); 412 413 synchronized (mIcons) { 414 mIcons.remove(slot); 415 416 if (mBar != null) { 417 try { 418 mBar.removeIcon(slot); 419 } catch (RemoteException ex) { 420 } 421 } 422 } 423 } 424 425 /** 426 * Hide or show the on-screen Menu key. Only call this from the window manager, typically in 427 * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set 428 * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}. 429 */ 430 private void topAppWindowChanged(final boolean menuVisible) { 431 enforceStatusBar(); 432 433 if (SPEW) Slog.d(TAG, (menuVisible?"showing":"hiding") + " MENU key"); 434 435 synchronized(mLock) { 436 mMenuVisible = menuVisible; 437 mHandler.post(new Runnable() { 438 public void run() { 439 if (mBar != null) { 440 try { 441 mBar.topAppWindowChanged(menuVisible); 442 } catch (RemoteException ex) { 443 } 444 } 445 } 446 }); 447 } 448 } 449 450 @Override 451 public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition, 452 final boolean showImeSwitcher) { 453 enforceStatusBar(); 454 455 if (SPEW) { 456 Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); 457 } 458 459 synchronized(mLock) { 460 // In case of IME change, we need to call up setImeWindowStatus() regardless of 461 // mImeWindowVis because mImeWindowVis may not have been set to false when the 462 // previous IME was destroyed. 463 mImeWindowVis = vis; 464 mImeBackDisposition = backDisposition; 465 mImeToken = token; 466 mShowImeSwitcher = showImeSwitcher; 467 mHandler.post(new Runnable() { 468 public void run() { 469 if (mBar != null) { 470 try { 471 mBar.setImeWindowStatus(token, vis, backDisposition, showImeSwitcher); 472 } catch (RemoteException ex) { 473 } 474 } 475 } 476 }); 477 } 478 } 479 480 @Override 481 public void setSystemUiVisibility(int vis, int mask, String cause) { 482 setSystemUiVisibility(vis, 0, 0, mask, mFullscreenStackBounds, mDockedStackBounds, cause); 483 } 484 485 private void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, 486 Rect fullscreenBounds, Rect dockedBounds, String cause) { 487 // also allows calls from window manager which is in this process. 488 enforceStatusBarService(); 489 490 if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")"); 491 492 synchronized (mLock) { 493 updateUiVisibilityLocked(vis, fullscreenStackVis, dockedStackVis, mask, 494 fullscreenBounds, dockedBounds); 495 disableLocked( 496 mCurrentUserId, 497 vis & StatusBarManager.DISABLE_MASK, 498 mSysUiVisToken, 499 cause, 1); 500 } 501 } 502 503 private void updateUiVisibilityLocked(final int vis, 504 final int fullscreenStackVis, final int dockedStackVis, final int mask, 505 final Rect fullscreenBounds, final Rect dockedBounds) { 506 if (mSystemUiVisibility != vis 507 || mFullscreenStackSysUiVisibility != fullscreenStackVis 508 || mDockedStackSysUiVisibility != dockedStackVis 509 || !mFullscreenStackBounds.equals(fullscreenBounds) 510 || !mDockedStackBounds.equals(dockedBounds)) { 511 mSystemUiVisibility = vis; 512 mFullscreenStackSysUiVisibility = fullscreenStackVis; 513 mDockedStackSysUiVisibility = dockedStackVis; 514 mFullscreenStackBounds.set(fullscreenBounds); 515 mDockedStackBounds.set(dockedBounds); 516 mHandler.post(new Runnable() { 517 public void run() { 518 if (mBar != null) { 519 try { 520 mBar.setSystemUiVisibility(vis, fullscreenStackVis, dockedStackVis, 521 mask, fullscreenBounds, dockedBounds); 522 } catch (RemoteException ex) { 523 } 524 } 525 } 526 }); 527 } 528 } 529 530 @Override 531 public void toggleRecentApps() { 532 if (mBar != null) { 533 try { 534 mBar.toggleRecentApps(); 535 } catch (RemoteException ex) {} 536 } 537 } 538 539 @Override 540 public void preloadRecentApps() { 541 if (mBar != null) { 542 try { 543 mBar.preloadRecentApps(); 544 } catch (RemoteException ex) {} 545 } 546 } 547 548 @Override 549 public void cancelPreloadRecentApps() { 550 if (mBar != null) { 551 try { 552 mBar.cancelPreloadRecentApps(); 553 } catch (RemoteException ex) {} 554 } 555 } 556 557 @Override 558 public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 559 if (mBar != null) { 560 try { 561 mBar.showRecentApps(triggeredFromAltTab, fromHome); 562 } catch (RemoteException ex) {} 563 } 564 } 565 566 @Override 567 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 568 if (mBar != null) { 569 try { 570 mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey); 571 } catch (RemoteException ex) {} 572 } 573 } 574 575 @Override 576 public void toggleKeyboardShortcutsMenu(int deviceId) { 577 if (mBar != null) { 578 try { 579 mBar.toggleKeyboardShortcutsMenu(deviceId); 580 } catch (RemoteException ex) {} 581 } 582 } 583 584 @Override 585 public void requestTvPictureInPicture() { 586 if (mBar != null) { 587 try { 588 mBar.requestTvPictureInPicture(); 589 } catch (RemoteException ex) {} 590 } 591 } 592 593 @Override 594 public void setCurrentUser(int newUserId) { 595 if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId); 596 mCurrentUserId = newUserId; 597 } 598 599 @Override 600 public void setWindowState(int window, int state) { 601 if (mBar != null) { 602 try { 603 mBar.setWindowState(window, state); 604 } catch (RemoteException ex) {} 605 } 606 } 607 608 @Override 609 public void appTransitionPending() { 610 if (mBar != null) { 611 try { 612 mBar.appTransitionPending(); 613 } catch (RemoteException ex) {} 614 } 615 } 616 617 @Override 618 public void appTransitionCancelled() { 619 if (mBar != null) { 620 try { 621 mBar.appTransitionCancelled(); 622 } catch (RemoteException ex) {} 623 } 624 } 625 626 @Override 627 public void appTransitionStarting(long statusBarAnimationsStartTime, 628 long statusBarAnimationsDuration) { 629 if (mBar != null) { 630 try { 631 mBar.appTransitionStarting( 632 statusBarAnimationsStartTime, statusBarAnimationsDuration); 633 } catch (RemoteException ex) {} 634 } 635 } 636 637 @Override 638 public void startAssist(Bundle args) { 639 if (mBar != null) { 640 try { 641 mBar.startAssist(args); 642 } catch (RemoteException ex) {} 643 } 644 } 645 646 private void enforceStatusBarOrShell() { 647 if (Binder.getCallingUid() == Process.SHELL_UID) { 648 return; 649 } 650 enforceStatusBar(); 651 } 652 653 private void enforceStatusBar() { 654 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR, 655 "StatusBarManagerService"); 656 } 657 658 private void enforceExpandStatusBar() { 659 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.EXPAND_STATUS_BAR, 660 "StatusBarManagerService"); 661 } 662 663 private void enforceStatusBarService() { 664 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 665 "StatusBarManagerService"); 666 } 667 668 // ================================================================================ 669 // Callbacks from the status bar service. 670 // ================================================================================ 671 @Override 672 public void registerStatusBar(IStatusBar bar, List<String> iconSlots, 673 List<StatusBarIcon> iconList, int switches[], List<IBinder> binders, 674 Rect fullscreenStackBounds, Rect dockedStackBounds) { 675 enforceStatusBarService(); 676 677 Slog.i(TAG, "registerStatusBar bar=" + bar); 678 mBar = bar; 679 synchronized (mIcons) { 680 for (String slot : mIcons.keySet()) { 681 iconSlots.add(slot); 682 iconList.add(mIcons.get(slot)); 683 } 684 } 685 synchronized (mLock) { 686 switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1); 687 switches[1] = mSystemUiVisibility; 688 switches[2] = mMenuVisible ? 1 : 0; 689 switches[3] = mImeWindowVis; 690 switches[4] = mImeBackDisposition; 691 switches[5] = mShowImeSwitcher ? 1 : 0; 692 switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2); 693 switches[7] = mFullscreenStackSysUiVisibility; 694 switches[8] = mDockedStackSysUiVisibility; 695 binders.add(mImeToken); 696 fullscreenStackBounds.set(mFullscreenStackBounds); 697 dockedStackBounds.set(mDockedStackBounds); 698 } 699 } 700 701 /** 702 * @param clearNotificationEffects whether to consider notifications as "shown" and stop 703 * LED, vibration, and ringing 704 */ 705 @Override 706 public void onPanelRevealed(boolean clearNotificationEffects, int numItems) { 707 enforceStatusBarService(); 708 long identity = Binder.clearCallingIdentity(); 709 try { 710 mNotificationDelegate.onPanelRevealed(clearNotificationEffects, numItems); 711 } finally { 712 Binder.restoreCallingIdentity(identity); 713 } 714 } 715 716 @Override 717 public void clearNotificationEffects() throws RemoteException { 718 enforceStatusBarService(); 719 long identity = Binder.clearCallingIdentity(); 720 try { 721 mNotificationDelegate.clearEffects(); 722 } finally { 723 Binder.restoreCallingIdentity(identity); 724 } 725 } 726 727 @Override 728 public void onPanelHidden() throws RemoteException { 729 enforceStatusBarService(); 730 long identity = Binder.clearCallingIdentity(); 731 try { 732 mNotificationDelegate.onPanelHidden(); 733 } finally { 734 Binder.restoreCallingIdentity(identity); 735 } 736 } 737 738 @Override 739 public void onNotificationClick(String key) { 740 enforceStatusBarService(); 741 final int callingUid = Binder.getCallingUid(); 742 final int callingPid = Binder.getCallingPid(); 743 long identity = Binder.clearCallingIdentity(); 744 try { 745 mNotificationDelegate.onNotificationClick(callingUid, callingPid, key); 746 } finally { 747 Binder.restoreCallingIdentity(identity); 748 } 749 } 750 751 @Override 752 public void onNotificationActionClick(String key, int actionIndex) { 753 enforceStatusBarService(); 754 final int callingUid = Binder.getCallingUid(); 755 final int callingPid = Binder.getCallingPid(); 756 long identity = Binder.clearCallingIdentity(); 757 try { 758 mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key, 759 actionIndex); 760 } finally { 761 Binder.restoreCallingIdentity(identity); 762 } 763 } 764 765 @Override 766 public void onNotificationError(String pkg, String tag, int id, 767 int uid, int initialPid, String message, int userId) { 768 enforceStatusBarService(); 769 final int callingUid = Binder.getCallingUid(); 770 final int callingPid = Binder.getCallingPid(); 771 long identity = Binder.clearCallingIdentity(); 772 try { 773 // WARNING: this will call back into us to do the remove. Don't hold any locks. 774 mNotificationDelegate.onNotificationError(callingUid, callingPid, 775 pkg, tag, id, uid, initialPid, message, userId); 776 } finally { 777 Binder.restoreCallingIdentity(identity); 778 } 779 } 780 781 @Override 782 public void onNotificationClear(String pkg, String tag, int id, int userId) { 783 enforceStatusBarService(); 784 final int callingUid = Binder.getCallingUid(); 785 final int callingPid = Binder.getCallingPid(); 786 long identity = Binder.clearCallingIdentity(); 787 try { 788 mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId); 789 } finally { 790 Binder.restoreCallingIdentity(identity); 791 } 792 } 793 794 @Override 795 public void onNotificationVisibilityChanged( 796 NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys) 797 throws RemoteException { 798 enforceStatusBarService(); 799 long identity = Binder.clearCallingIdentity(); 800 try { 801 mNotificationDelegate.onNotificationVisibilityChanged( 802 newlyVisibleKeys, noLongerVisibleKeys); 803 } finally { 804 Binder.restoreCallingIdentity(identity); 805 } 806 } 807 808 @Override 809 public void onNotificationExpansionChanged(String key, boolean userAction, 810 boolean expanded) throws RemoteException { 811 enforceStatusBarService(); 812 long identity = Binder.clearCallingIdentity(); 813 try { 814 mNotificationDelegate.onNotificationExpansionChanged( 815 key, userAction, expanded); 816 } finally { 817 Binder.restoreCallingIdentity(identity); 818 } 819 } 820 821 @Override 822 public void onClearAllNotifications(int userId) { 823 enforceStatusBarService(); 824 final int callingUid = Binder.getCallingUid(); 825 final int callingPid = Binder.getCallingPid(); 826 long identity = Binder.clearCallingIdentity(); 827 try { 828 mNotificationDelegate.onClearAll(callingUid, callingPid, userId); 829 } finally { 830 Binder.restoreCallingIdentity(identity); 831 } 832 } 833 834 @Override 835 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 836 String[] args, ResultReceiver resultReceiver) throws RemoteException { 837 (new StatusBarShellCommand(this)).exec( 838 this, in, out, err, args, resultReceiver); 839 } 840 841 // ================================================================================ 842 // Can be called from any thread 843 // ================================================================================ 844 845 // lock on mDisableRecords 846 void manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which) { 847 if (SPEW) { 848 Slog.d(TAG, "manageDisableList userId=" + userId 849 + " what=0x" + Integer.toHexString(what) + " pkg=" + pkg); 850 } 851 // update the list 852 final int N = mDisableRecords.size(); 853 DisableRecord tok = null; 854 int i; 855 for (i=0; i<N; i++) { 856 DisableRecord t = mDisableRecords.get(i); 857 if (t.token == token && t.userId == userId) { 858 tok = t; 859 break; 860 } 861 } 862 if (what == 0 || !token.isBinderAlive()) { 863 if (tok != null) { 864 mDisableRecords.remove(i); 865 tok.token.unlinkToDeath(tok, 0); 866 } 867 } else { 868 if (tok == null) { 869 tok = new DisableRecord(); 870 tok.userId = userId; 871 try { 872 token.linkToDeath(tok, 0); 873 } 874 catch (RemoteException ex) { 875 return; // give up 876 } 877 mDisableRecords.add(tok); 878 } 879 if (which == 1) { 880 tok.what1 = what; 881 } else { 882 tok.what2 = what; 883 } 884 tok.token = token; 885 tok.pkg = pkg; 886 } 887 } 888 889 // lock on mDisableRecords 890 int gatherDisableActionsLocked(int userId, int which) { 891 final int N = mDisableRecords.size(); 892 // gather the new net flags 893 int net = 0; 894 for (int i=0; i<N; i++) { 895 final DisableRecord rec = mDisableRecords.get(i); 896 if (rec.userId == userId) { 897 net |= (which == 1) ? rec.what1 : rec.what2; 898 } 899 } 900 return net; 901 } 902 903 // ================================================================================ 904 // Always called from UI thread 905 // ================================================================================ 906 907 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 908 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 909 != PackageManager.PERMISSION_GRANTED) { 910 pw.println("Permission Denial: can't dump StatusBar from from pid=" 911 + Binder.getCallingPid() 912 + ", uid=" + Binder.getCallingUid()); 913 return; 914 } 915 916 synchronized (mLock) { 917 pw.println(" mDisabled1=0x" + Integer.toHexString(mDisabled1)); 918 pw.println(" mDisabled2=0x" + Integer.toHexString(mDisabled2)); 919 final int N = mDisableRecords.size(); 920 pw.println(" mDisableRecords.size=" + N); 921 for (int i=0; i<N; i++) { 922 DisableRecord tok = mDisableRecords.get(i); 923 pw.println(" [" + i + "] userId=" + tok.userId 924 + " what1=0x" + Integer.toHexString(tok.what1) 925 + " what2=0x" + Integer.toHexString(tok.what2) 926 + " pkg=" + tok.pkg 927 + " token=" + tok.token); 928 } 929 } 930 } 931} 932