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