PhoneStatusBar.java revision d5483c3157a28e2ebc05a0c918df8a2be0a7fc89
1/* 2 * Copyright (C) 2010 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.systemui.statusbar.phone; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.AnimatorSet; 22import android.animation.ObjectAnimator; 23import android.animation.TimeInterpolator; 24import android.app.ActivityManager; 25import android.app.ActivityManagerNative; 26import android.app.Notification; 27import android.app.PendingIntent; 28import android.app.StatusBarManager; 29import android.content.BroadcastReceiver; 30import android.content.Context; 31import android.content.Intent; 32import android.content.IntentFilter; 33import android.content.SharedPreferences; 34import android.content.res.Resources; 35import android.database.ContentObserver; 36import android.graphics.Canvas; 37import android.graphics.ColorFilter; 38import android.graphics.PixelFormat; 39import android.graphics.Point; 40import android.graphics.PorterDuff; 41import android.graphics.Rect; 42import android.graphics.drawable.Drawable; 43import android.graphics.drawable.NinePatchDrawable; 44import android.inputmethodservice.InputMethodService; 45import android.os.Handler; 46import android.os.IBinder; 47import android.os.Message; 48import android.os.RemoteException; 49import android.os.ServiceManager; 50import android.os.SystemClock; 51import android.os.UserHandle; 52import android.provider.Settings; 53import android.service.dreams.DreamService; 54import android.service.dreams.IDreamManager; 55import android.util.DisplayMetrics; 56import android.util.Log; 57import android.util.Slog; 58import android.view.Display; 59import android.view.Gravity; 60import android.view.MotionEvent; 61import android.view.VelocityTracker; 62import android.view.View; 63import android.view.ViewGroup; 64import android.view.ViewGroup.LayoutParams; 65import android.view.ViewPropertyAnimator; 66import android.view.ViewStub; 67import android.view.WindowManager; 68import android.view.animation.AccelerateInterpolator; 69import android.view.animation.Animation; 70import android.view.animation.AnimationUtils; 71import android.view.animation.DecelerateInterpolator; 72import android.widget.FrameLayout; 73import android.widget.ImageView; 74import android.widget.LinearLayout; 75import android.widget.ScrollView; 76import android.widget.TextView; 77 78import com.android.internal.statusbar.StatusBarIcon; 79import com.android.internal.statusbar.StatusBarNotification; 80import com.android.systemui.R; 81import com.android.systemui.statusbar.BaseStatusBar; 82import com.android.systemui.statusbar.CommandQueue; 83import com.android.systemui.statusbar.GestureRecorder; 84import com.android.systemui.statusbar.NotificationData; 85import com.android.systemui.statusbar.NotificationData.Entry; 86import com.android.systemui.statusbar.SignalClusterView; 87import com.android.systemui.statusbar.StatusBarIconView; 88import com.android.systemui.statusbar.policy.BatteryController; 89import com.android.systemui.statusbar.policy.BluetoothController; 90import com.android.systemui.statusbar.policy.DateView; 91import com.android.systemui.statusbar.policy.IntruderAlertView; 92import com.android.systemui.statusbar.policy.LocationController; 93import com.android.systemui.statusbar.policy.NetworkController; 94import com.android.systemui.statusbar.policy.NotificationRowLayout; 95import com.android.systemui.statusbar.policy.OnSizeChangedListener; 96import com.android.systemui.statusbar.policy.Prefs; 97 98import java.io.FileDescriptor; 99import java.io.PrintWriter; 100import java.util.ArrayList; 101 102public class PhoneStatusBar extends BaseStatusBar { 103 static final String TAG = "PhoneStatusBar"; 104 public static final boolean DEBUG = BaseStatusBar.DEBUG; 105 public static final boolean SPEW = DEBUG; 106 public static final boolean DUMPTRUCK = true; // extra dumpsys info 107 public static final boolean DEBUG_GESTURES = false; 108 109 public static final boolean DEBUG_CLINGS = false; 110 111 public static final boolean ENABLE_NOTIFICATION_PANEL_CLING = false; 112 113 public static final boolean SETTINGS_DRAG_SHORTCUT = true; 114 115 // additional instrumentation for testing purposes; intended to be left on during development 116 public static final boolean CHATTY = DEBUG; 117 118 public static final String ACTION_STATUSBAR_START 119 = "com.android.internal.policy.statusbar.START"; 120 121 private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; 122 private static final int MSG_CLOSE_PANELS = 1001; 123 private static final int MSG_OPEN_SETTINGS_PANEL = 1002; 124 // 1020-1030 reserved for BaseStatusBar 125 126 // will likely move to a resource or other tunable param at some point 127 private static final int INTRUDER_ALERT_DECAY_MS = 0; // disabled, was 10000; 128 129 private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; 130 131 private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService 132 private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER; 133 134 // fling gesture tuning parameters, scaled to display density 135 private float mSelfExpandVelocityPx; // classic value: 2000px/s 136 private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up") 137 private float mFlingExpandMinVelocityPx; // classic value: 200px/s 138 private float mFlingCollapseMinVelocityPx; // classic value: 200px/s 139 private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1) 140 private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand) 141 private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s 142 143 private float mExpandAccelPx; // classic value: 2000px/s/s 144 private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up") 145 146 private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little 147 // faster than mSelfCollapseVelocityPx) 148 149 PhoneStatusBarPolicy mIconPolicy; 150 151 // These are no longer handled by the policy, because we need custom strategies for them 152 BluetoothController mBluetoothController; 153 BatteryController mBatteryController; 154 LocationController mLocationController; 155 NetworkController mNetworkController; 156 157 int mNaturalBarHeight = -1; 158 int mIconSize = -1; 159 int mIconHPadding = -1; 160 Display mDisplay; 161 Point mCurrentDisplaySize = new Point(); 162 163 IDreamManager mDreamManager; 164 165 StatusBarWindowView mStatusBarWindow; 166 PhoneStatusBarView mStatusBarView; 167 168 int mPixelFormat; 169 Object mQueueLock = new Object(); 170 171 // viewgroup containing the normal contents of the statusbar 172 LinearLayout mStatusBarContents; 173 174 // right-hand icons 175 LinearLayout mSystemIconArea; 176 177 // left-hand icons 178 LinearLayout mStatusIcons; 179 // the icons themselves 180 IconMerger mNotificationIcons; 181 // [+> 182 View mMoreIcon; 183 184 // expanded notifications 185 NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window 186 ScrollView mScrollView; 187 View mExpandedContents; 188 int mNotificationPanelGravity; 189 int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx; 190 float mNotificationPanelMinHeightFrac; 191 boolean mNotificationPanelIsFullScreenWidth; 192 TextView mNotificationPanelDebugText; 193 194 // settings 195 QuickSettings mQS; 196 boolean mHasSettingsPanel, mHasFlipSettings; 197 SettingsPanelView mSettingsPanel; 198 View mFlipSettingsView; 199 QuickSettingsContainerView mSettingsContainer; 200 int mSettingsPanelGravity; 201 202 // top bar 203 View mNotificationPanelHeader; 204 View mDateTimeView; 205 View mClearButton; 206 ImageView mSettingsButton, mNotificationButton; 207 208 // carrier/wifi label 209 private TextView mCarrierLabel; 210 private boolean mCarrierLabelVisible = false; 211 private int mCarrierLabelHeight; 212 private TextView mEmergencyCallLabel; 213 private int mNotificationHeaderHeight; 214 215 private boolean mShowCarrierInPanel = false; 216 217 // position 218 int[] mPositionTmp = new int[2]; 219 boolean mExpandedVisible; 220 221 // the date view 222 DateView mDateView; 223 224 // for immersive activities 225 private IntruderAlertView mIntruderAlertView; 226 227 // on-screen navigation buttons 228 private NavigationBarView mNavigationBarView = null; 229 230 // the tracker view 231 int mTrackingPosition; // the position of the top of the tracking view. 232 233 // ticker 234 private Ticker mTicker; 235 private View mTickerView; 236 private boolean mTicking; 237 238 // Tracking finger for opening/closing. 239 int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore 240 boolean mTracking; 241 VelocityTracker mVelocityTracker; 242 243 // help screen 244 private boolean mClingShown; 245 private ViewGroup mCling; 246 private boolean mSuppressStatusBarDrags; // while a cling is up, briefly deaden the bar to give things time to settle 247 248 boolean mAnimating; 249 boolean mClosing; // only valid when mAnimating; indicates the initial acceleration 250 float mAnimY; 251 float mAnimVel; 252 float mAnimAccel; 253 long mAnimLastTimeNanos; 254 boolean mAnimatingReveal = false; 255 int mViewDelta; 256 float mFlingVelocity; 257 int mFlingY; 258 int[] mAbsPos = new int[2]; 259 Runnable mPostCollapseCleanup = null; 260 261 private Animator mLightsOutAnimation; 262 private Animator mLightsOnAnimation; 263 264 // for disabling the status bar 265 int mDisabled = 0; 266 267 // tracking calls to View.setSystemUiVisibility() 268 int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 269 270 DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 271 272 // XXX: gesture research 273 private final GestureRecorder mGestureRec = DEBUG_GESTURES 274 ? new GestureRecorder("/sdcard/statusbar_gestures.dat") 275 : null; 276 277 private int mNavigationIconHints = 0; 278 private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() { 279 @Override 280 public void onAnimationEnd(Animator animation) { 281 // double-check to avoid races 282 if (mStatusBarContents.getAlpha() == 0) { 283 Slog.d(TAG, "makeIconsInvisible"); 284 mStatusBarContents.setVisibility(View.INVISIBLE); 285 } 286 } 287 }; 288 289 // ensure quick settings is disabled until the current user makes it through the setup wizard 290 private boolean mUserSetup = false; 291 private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) { 292 @Override 293 public void onChange(boolean selfChange) { 294 final boolean userSetup = 0 != Settings.Secure.getIntForUser( 295 mContext.getContentResolver(), 296 Settings.Secure.USER_SETUP_COMPLETE, 297 0 /*default */, 298 mCurrentUserId); 299 if (MULTIUSER_DEBUG) Slog.d(TAG, String.format("User setup changed: " + 300 "selfChange=%s userSetup=%s mUserSetup=%s", 301 selfChange, userSetup, mUserSetup)); 302 if (mSettingsButton != null && !mHasSettingsPanel) { 303 mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE); 304 } 305 if (mSettingsPanel != null) { 306 mSettingsPanel.setEnabled(userSetup); 307 } 308 if (userSetup != mUserSetup) { 309 mUserSetup = userSetup; 310 if (!mUserSetup && mStatusBarView != null) 311 animateCollapseQuickSettings(); 312 } 313 } 314 }; 315 316 @Override 317 public void start() { 318 mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) 319 .getDefaultDisplay(); 320 321 mDreamManager = IDreamManager.Stub.asInterface( 322 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 323 324 super.start(); // calls createAndAddWindows() 325 326 addNavigationBar(); 327 328 if (ENABLE_INTRUDERS) addIntruderView(); 329 330 // Lastly, call to the icon policy to install/update all the icons. 331 mIconPolicy = new PhoneStatusBarPolicy(mContext); 332 } 333 334 // ================================================================================ 335 // Constructing the view 336 // ================================================================================ 337 protected PhoneStatusBarView makeStatusBarView() { 338 final Context context = mContext; 339 340 Resources res = context.getResources(); 341 342 updateDisplaySize(); // populates mDisplayMetrics 343 loadDimens(); 344 345 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size); 346 347 mStatusBarWindow = (StatusBarWindowView) View.inflate(context, 348 R.layout.super_status_bar, null); 349 mStatusBarWindow.mService = this; 350 mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() { 351 @Override 352 public boolean onTouch(View v, MotionEvent event) { 353 if (event.getAction() == MotionEvent.ACTION_DOWN) { 354 if (mExpandedVisible && !mAnimating) { 355 animateCollapsePanels(); 356 } 357 } 358 return mStatusBarWindow.onTouchEvent(event); 359 }}); 360 361 mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); 362 mStatusBarView.setBar(this); 363 364 365 PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); 366 mStatusBarView.setPanelHolder(holder); 367 368 mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel); 369 mNotificationPanel.setStatusBar(this); 370 mNotificationPanelIsFullScreenWidth = 371 (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT); 372 373 // make the header non-responsive to clicks 374 mNotificationPanel.findViewById(R.id.header).setOnTouchListener( 375 new View.OnTouchListener() { 376 @Override 377 public boolean onTouch(View v, MotionEvent event) { 378 return true; // e eats everything 379 } 380 }); 381 382 if (!ActivityManager.isHighEndGfx()) { 383 mStatusBarWindow.setBackground(null); 384 mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor( 385 R.color.notification_panel_solid_background))); 386 } 387 if (ENABLE_INTRUDERS) { 388 mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null); 389 mIntruderAlertView.setVisibility(View.GONE); 390 mIntruderAlertView.setBar(this); 391 } 392 if (MULTIUSER_DEBUG) { 393 mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(R.id.header_debug_info); 394 mNotificationPanelDebugText.setVisibility(View.VISIBLE); 395 } 396 397 updateShowSearchHoldoff(); 398 399 try { 400 boolean showNav = mWindowManagerService.hasNavigationBar(); 401 if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav); 402 if (showNav) { 403 mNavigationBarView = 404 (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null); 405 406 mNavigationBarView.setDisabledFlags(mDisabled); 407 mNavigationBarView.setBar(this); 408 } 409 } catch (RemoteException ex) { 410 // no window manager? good luck with that 411 } 412 413 // figure out which pixel-format to use for the status bar. 414 mPixelFormat = PixelFormat.OPAQUE; 415 416 mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area); 417 mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons); 418 mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons); 419 mNotificationIcons.setOverflowIndicator(mMoreIcon); 420 mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents); 421 mTickerView = mStatusBarView.findViewById(R.id.ticker); 422 423 mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems); 424 mPile.setLayoutTransitionsEnabled(false); 425 mPile.setLongPressListener(getNotificationLongClicker()); 426 mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout); 427 428 mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header); 429 430 mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button); 431 mClearButton.setOnClickListener(mClearButtonListener); 432 mClearButton.setAlpha(0f); 433 mClearButton.setVisibility(View.INVISIBLE); 434 mClearButton.setEnabled(false); 435 mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date); 436 437 mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel); 438 mHasFlipSettings = res.getBoolean(R.bool.config_hasFlipSettingsPanel); 439 440 mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime); 441 if (mHasFlipSettings) { 442 mDateTimeView.setOnClickListener(mClockClickListener); 443 mDateTimeView.setEnabled(true); 444 } 445 446 mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button); 447 if (mSettingsButton != null) { 448 mSettingsButton.setOnClickListener(mSettingsButtonListener); 449 if (mHasSettingsPanel) { 450 if (mStatusBarView.hasFullWidthNotifications()) { 451 // the settings panel is hiding behind this button 452 mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); 453 mSettingsButton.setVisibility(View.VISIBLE); 454 } else { 455 // there is a settings panel, but it's on the other side of the (large) screen 456 mSettingsButton.setVisibility(View.GONE); 457 } 458 } else { 459 // no settings panel, go straight to settings 460 mSettingsButton.setVisibility(View.VISIBLE); 461 mSettingsButton.setImageResource(R.drawable.ic_notify_settings); 462 } 463 } 464 if (mHasFlipSettings) { 465 mNotificationButton = (ImageView) mStatusBarWindow.findViewById(R.id.notification_button); 466 if (mNotificationButton != null) { 467 mNotificationButton.setOnClickListener(mNotificationButtonListener); 468 } 469 } 470 471 mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll); 472 mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns 473 if (!mNotificationPanelIsFullScreenWidth) { 474 mScrollView.setSystemUiVisibility( 475 View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER | 476 View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS | 477 View.STATUS_BAR_DISABLE_CLOCK); 478 } 479 480 mTicker = new MyTicker(context, mStatusBarView); 481 482 TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText); 483 tickerView.mTicker = mTicker; 484 485 mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore); 486 487 // set the inital view visibility 488 setAreThereNotifications(); 489 490 // Other icons 491 mLocationController = new LocationController(mContext); // will post a notification 492 mBatteryController = new BatteryController(mContext); 493 mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery)); 494 mNetworkController = new NetworkController(mContext); 495 mBluetoothController = new BluetoothController(mContext); 496 final SignalClusterView signalCluster = 497 (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster); 498 499 500 mNetworkController.addSignalCluster(signalCluster); 501 signalCluster.setNetworkController(mNetworkController); 502 503 mEmergencyCallLabel = (TextView)mStatusBarWindow.findViewById(R.id.emergency_calls_only); 504 if (mEmergencyCallLabel != null) { 505 mNetworkController.addEmergencyLabelView(mEmergencyCallLabel); 506 mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() { 507 public void onClick(View v) { }}); 508 mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 509 @Override 510 public void onLayoutChange(View v, int left, int top, int right, int bottom, 511 int oldLeft, int oldTop, int oldRight, int oldBottom) { 512 updateCarrierLabelVisibility(false); 513 }}); 514 } 515 516 mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label); 517 mShowCarrierInPanel = (mCarrierLabel != null); 518 Slog.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel); 519 if (mShowCarrierInPanel) { 520 mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE); 521 522 // for mobile devices, we always show mobile connection info here (SPN/PLMN) 523 // for other devices, we show whatever network is connected 524 if (mNetworkController.hasMobileDataFeature()) { 525 mNetworkController.addMobileLabelView(mCarrierLabel); 526 } else { 527 mNetworkController.addCombinedLabelView(mCarrierLabel); 528 } 529 530 // set up the dynamic hide/show of the label 531 mPile.setOnSizeChangedListener(new OnSizeChangedListener() { 532 @Override 533 public void onSizeChanged(View view, int w, int h, int oldw, int oldh) { 534 updateCarrierLabelVisibility(false); 535 } 536 }); 537 } 538 539 // Quick Settings (where available, some restrictions apply) 540 if (mHasSettingsPanel) { 541 // first, figure out where quick settings should be inflated 542 final View settings_stub; 543 if (mHasFlipSettings) { 544 // a version of quick settings that flips around behind the notifications 545 settings_stub = mStatusBarWindow.findViewById(R.id.flip_settings_stub); 546 if (settings_stub != null) { 547 mFlipSettingsView = ((ViewStub)settings_stub).inflate(); 548 mFlipSettingsView.setVisibility(View.GONE); 549 mFlipSettingsView.setVerticalScrollBarEnabled(false); 550 } 551 } else { 552 // full quick settings panel 553 settings_stub = mStatusBarWindow.findViewById(R.id.quick_settings_stub); 554 if (settings_stub != null) { 555 mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate(); 556 } else { 557 mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel); 558 } 559 560 if (mSettingsPanel != null) { 561 if (!ActivityManager.isHighEndGfx()) { 562 mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor( 563 R.color.notification_panel_solid_background))); 564 } 565 } 566 } 567 568 // wherever you find it, Quick Settings needs a container to survive 569 mSettingsContainer = (QuickSettingsContainerView) 570 mStatusBarWindow.findViewById(R.id.quick_settings_container); 571 if (mSettingsContainer != null) { 572 mQS = new QuickSettings(mContext, mSettingsContainer); 573 if (!mNotificationPanelIsFullScreenWidth) { 574 mSettingsContainer.setSystemUiVisibility( 575 View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER 576 | View.STATUS_BAR_DISABLE_SYSTEM_INFO); 577 } 578 if (mSettingsPanel != null) { 579 mSettingsPanel.setQuickSettings(mQS); 580 } 581 mQS.setService(this); 582 mQS.setBar(mStatusBarView); 583 mQS.setup(mNetworkController, mBluetoothController, mBatteryController, 584 mLocationController); 585 } else { 586 mQS = null; // fly away, be free 587 } 588 } 589 590 mClingShown = ! (DEBUG_CLINGS 591 || !Prefs.read(mContext).getBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, false)); 592 593 if (!ENABLE_NOTIFICATION_PANEL_CLING || ActivityManager.isRunningInTestHarness()) { 594 mClingShown = true; 595 } 596 597// final ImageView wimaxRSSI = 598// (ImageView)sb.findViewById(R.id.wimax_signal); 599// if (wimaxRSSI != null) { 600// mNetworkController.addWimaxIconView(wimaxRSSI); 601// } 602 603 // receive broadcasts 604 IntentFilter filter = new IntentFilter(); 605 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 606 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 607 filter.addAction(Intent.ACTION_SCREEN_OFF); 608 filter.addAction(Intent.ACTION_SCREEN_ON); 609 context.registerReceiver(mBroadcastReceiver, filter); 610 611 // listen for USER_SETUP_COMPLETE setting (per-user) 612 resetUserSetupObserver(); 613 614 return mStatusBarView; 615 } 616 617 @Override 618 protected View getStatusBarView() { 619 return mStatusBarView; 620 } 621 622 @Override 623 protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) { 624 boolean opaque = false; 625 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 626 layoutParams.width, 627 layoutParams.height, 628 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, 629 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 630 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 631 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 632 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT)); 633 if (ActivityManager.isHighEndGfx()) { 634 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 635 } else { 636 lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND; 637 lp.dimAmount = 0.75f; 638 } 639 lp.gravity = Gravity.BOTTOM | Gravity.LEFT; 640 lp.setTitle("RecentsPanel"); 641 lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications; 642 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED 643 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 644 return lp; 645 } 646 647 @Override 648 protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) { 649 boolean opaque = false; 650 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 651 LayoutParams.MATCH_PARENT, 652 LayoutParams.MATCH_PARENT, 653 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, 654 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 655 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 656 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 657 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT)); 658 if (ActivityManager.isHighEndGfx()) { 659 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 660 } 661 lp.gravity = Gravity.BOTTOM | Gravity.LEFT; 662 lp.setTitle("SearchPanel"); 663 // TODO: Define custom animation for Search panel 664 lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications; 665 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED 666 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 667 return lp; 668 } 669 670 @Override 671 protected void updateSearchPanel() { 672 super.updateSearchPanel(); 673 mSearchPanelView.setStatusBarView(mNavigationBarView); 674 mNavigationBarView.setDelegateView(mSearchPanelView); 675 } 676 677 @Override 678 public void showSearchPanel() { 679 super.showSearchPanel(); 680 681 // we want to freeze the sysui state wherever it is 682 mSearchPanelView.setSystemUiVisibility(mSystemUiVisibility); 683 684 WindowManager.LayoutParams lp = 685 (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams(); 686 lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 687 mWindowManager.updateViewLayout(mNavigationBarView, lp); 688 } 689 690 @Override 691 public void hideSearchPanel() { 692 super.hideSearchPanel(); 693 WindowManager.LayoutParams lp = 694 (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams(); 695 lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 696 mWindowManager.updateViewLayout(mNavigationBarView, lp); 697 } 698 699 protected int getStatusBarGravity() { 700 return Gravity.TOP | Gravity.FILL_HORIZONTAL; 701 } 702 703 public int getStatusBarHeight() { 704 if (mNaturalBarHeight < 0) { 705 final Resources res = mContext.getResources(); 706 mNaturalBarHeight = 707 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 708 } 709 return mNaturalBarHeight; 710 } 711 712 private View.OnClickListener mRecentsClickListener = new View.OnClickListener() { 713 public void onClick(View v) { 714 toggleRecentApps(); 715 } 716 }; 717 718 private int mShowSearchHoldoff = 0; 719 private Runnable mShowSearchPanel = new Runnable() { 720 public void run() { 721 showSearchPanel(); 722 awakenDreams(); 723 } 724 }; 725 726 View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() { 727 public boolean onTouch(View v, MotionEvent event) { 728 switch(event.getAction()) { 729 case MotionEvent.ACTION_DOWN: 730 if (!shouldDisableNavbarGestures()) { 731 mHandler.removeCallbacks(mShowSearchPanel); 732 mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff); 733 } 734 break; 735 736 case MotionEvent.ACTION_UP: 737 case MotionEvent.ACTION_CANCEL: 738 mHandler.removeCallbacks(mShowSearchPanel); 739 awakenDreams(); 740 break; 741 } 742 return false; 743 } 744 }; 745 746 private void awakenDreams() { 747 if (mDreamManager != null) { 748 try { 749 mDreamManager.awaken(); 750 } catch (RemoteException e) { 751 // fine, stay asleep then 752 } 753 } 754 } 755 756 private void prepareNavigationBarView() { 757 mNavigationBarView.reorient(); 758 759 mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener); 760 mNavigationBarView.getRecentsButton().setOnTouchListener(getRecentTasksLoader()); 761 mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener); 762 updateSearchPanel(); 763 } 764 765 // For small-screen devices (read: phones) that lack hardware navigation buttons 766 private void addNavigationBar() { 767 if (DEBUG) Slog.v(TAG, "addNavigationBar: about to add " + mNavigationBarView); 768 if (mNavigationBarView == null) return; 769 770 prepareNavigationBarView(); 771 772 mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams()); 773 } 774 775 private void repositionNavigationBar() { 776 if (mNavigationBarView == null) return; 777 778 prepareNavigationBarView(); 779 780 mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams()); 781 } 782 783 private WindowManager.LayoutParams getNavigationBarLayoutParams() { 784 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 785 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 786 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, 787 0 788 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 789 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 790 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 791 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 792 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 793 PixelFormat.OPAQUE); 794 // this will allow the navbar to run in an overlay on devices that support this 795 if (ActivityManager.isHighEndGfx()) { 796 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 797 } 798 799 lp.setTitle("NavigationBar"); 800 lp.windowAnimations = 0; 801 return lp; 802 } 803 804 private void addIntruderView() { 805 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 806 ViewGroup.LayoutParams.MATCH_PARENT, 807 ViewGroup.LayoutParams.WRAP_CONTENT, 808 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, // above the status bar! 809 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 810 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 811 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 812 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 813 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 814 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 815 PixelFormat.TRANSLUCENT); 816 lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; 817 //lp.y += height * 1.5; // FIXME 818 lp.setTitle("IntruderAlert"); 819 lp.packageName = mContext.getPackageName(); 820 lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert; 821 822 mWindowManager.addView(mIntruderAlertView, lp); 823 } 824 825 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { 826 if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex 827 + " icon=" + icon); 828 StatusBarIconView view = new StatusBarIconView(mContext, slot, null); 829 view.set(icon); 830 mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize)); 831 } 832 833 public void updateIcon(String slot, int index, int viewIndex, 834 StatusBarIcon old, StatusBarIcon icon) { 835 if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex 836 + " old=" + old + " icon=" + icon); 837 StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex); 838 view.set(icon); 839 } 840 841 public void removeIcon(String slot, int index, int viewIndex) { 842 if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex); 843 mStatusIcons.removeViewAt(viewIndex); 844 } 845 846 public void addNotification(IBinder key, StatusBarNotification notification) { 847 /* if (DEBUG) */ Slog.d(TAG, "addNotification score=" + notification.score); 848 StatusBarIconView iconView = addNotificationViews(key, notification); 849 if (iconView == null) return; 850 851 boolean immersive = false; 852 try { 853 immersive = ActivityManagerNative.getDefault().isTopActivityImmersive(); 854 if (DEBUG) { 855 Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive")); 856 } 857 } catch (RemoteException ex) { 858 } 859 860 /* 861 * DISABLED due to missing API 862 if (ENABLE_INTRUDERS && ( 863 // TODO(dsandler): Only if the screen is on 864 notification.notification.intruderView != null)) { 865 Slog.d(TAG, "Presenting high-priority notification"); 866 // special new transient ticker mode 867 // 1. Populate mIntruderAlertView 868 869 if (notification.notification.intruderView == null) { 870 Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null"); 871 return; 872 } 873 874 // bind the click event to the content area 875 PendingIntent contentIntent = notification.notification.contentIntent; 876 final View.OnClickListener listener = (contentIntent != null) 877 ? new NotificationClicker(contentIntent, 878 notification.pkg, notification.tag, notification.id) 879 : null; 880 881 mIntruderAlertView.applyIntruderContent(notification.notification.intruderView, listener); 882 883 mCurrentlyIntrudingNotification = notification; 884 885 // 2. Animate mIntruderAlertView in 886 mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER); 887 888 // 3. Set alarm to age the notification off (TODO) 889 mHandler.removeMessages(MSG_HIDE_INTRUDER); 890 if (INTRUDER_ALERT_DECAY_MS > 0) { 891 mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS); 892 } 893 } else 894 */ 895 896 if (notification.notification.fullScreenIntent != null) { 897 // Stop screensaver if the notification has a full-screen intent. 898 // (like an incoming phone call) 899 awakenDreams(); 900 901 // not immersive & a full-screen alert should be shown 902 Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); 903 try { 904 notification.notification.fullScreenIntent.send(); 905 } catch (PendingIntent.CanceledException e) { 906 } 907 } else { 908 // usual case: status bar visible & not immersive 909 910 // show the ticker if there isn't an intruder too 911 if (mCurrentlyIntrudingNotification == null) { 912 tick(null, notification, true); 913 } 914 } 915 916 // Recalculate the position of the sliding windows and the titles. 917 setAreThereNotifications(); 918 updateExpandedViewPos(EXPANDED_LEAVE_ALONE); 919 } 920 921 public void removeNotification(IBinder key) { 922 StatusBarNotification old = removeNotificationViews(key); 923 if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old); 924 925 if (old != null) { 926 // Cancel the ticker if it's still running 927 mTicker.removeEntry(old); 928 929 // Recalculate the position of the sliding windows and the titles. 930 updateExpandedViewPos(EXPANDED_LEAVE_ALONE); 931 932 if (ENABLE_INTRUDERS && old == mCurrentlyIntrudingNotification) { 933 mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER); 934 } 935 936 if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) { 937 animateCollapsePanels(); 938 } 939 } 940 941 setAreThereNotifications(); 942 } 943 944 private void updateShowSearchHoldoff() { 945 mShowSearchHoldoff = mContext.getResources().getInteger( 946 R.integer.config_show_search_delay); 947 } 948 949 private void loadNotificationShade() { 950 if (mPile == null) return; 951 952 int N = mNotificationData.size(); 953 954 ArrayList<View> toShow = new ArrayList<View>(); 955 956 final boolean provisioned = isDeviceProvisioned(); 957 // If the device hasn't been through Setup, we only show system notifications 958 for (int i=0; i<N; i++) { 959 Entry ent = mNotificationData.get(N-i-1); 960 if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue; 961 if (!notificationIsForCurrentUser(ent.notification)) continue; 962 toShow.add(ent.row); 963 } 964 965 ArrayList<View> toRemove = new ArrayList<View>(); 966 for (int i=0; i<mPile.getChildCount(); i++) { 967 View child = mPile.getChildAt(i); 968 if (!toShow.contains(child)) { 969 toRemove.add(child); 970 } 971 } 972 973 for (View remove : toRemove) { 974 mPile.removeView(remove); 975 } 976 977 for (int i=0; i<toShow.size(); i++) { 978 View v = toShow.get(i); 979 if (v.getParent() == null) { 980 mPile.addView(v, i); 981 } 982 } 983 984 if (mSettingsButton != null) { 985 mSettingsButton.setEnabled(isDeviceProvisioned()); 986 } 987 } 988 989 @Override 990 protected void updateNotificationIcons() { 991 if (mNotificationIcons == null) return; 992 993 loadNotificationShade(); 994 995 final LinearLayout.LayoutParams params 996 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight); 997 998 int N = mNotificationData.size(); 999 1000 if (DEBUG) { 1001 Slog.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + mNotificationIcons); 1002 } 1003 1004 ArrayList<View> toShow = new ArrayList<View>(); 1005 1006 final boolean provisioned = isDeviceProvisioned(); 1007 // If the device hasn't been through Setup, we only show system notifications 1008 for (int i=0; i<N; i++) { 1009 Entry ent = mNotificationData.get(N-i-1); 1010 if (!((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE) 1011 || showNotificationEvenIfUnprovisioned(ent.notification))) continue; 1012 if (!notificationIsForCurrentUser(ent.notification)) continue; 1013 toShow.add(ent.icon); 1014 } 1015 1016 ArrayList<View> toRemove = new ArrayList<View>(); 1017 for (int i=0; i<mNotificationIcons.getChildCount(); i++) { 1018 View child = mNotificationIcons.getChildAt(i); 1019 if (!toShow.contains(child)) { 1020 toRemove.add(child); 1021 } 1022 } 1023 1024 for (View remove : toRemove) { 1025 mNotificationIcons.removeView(remove); 1026 } 1027 1028 for (int i=0; i<toShow.size(); i++) { 1029 View v = toShow.get(i); 1030 if (v.getParent() == null) { 1031 mNotificationIcons.addView(v, i, params); 1032 } 1033 } 1034 } 1035 1036 protected void updateCarrierLabelVisibility(boolean force) { 1037 if (!mShowCarrierInPanel) return; 1038 // The idea here is to only show the carrier label when there is enough room to see it, 1039 // i.e. when there aren't enough notifications to fill the panel. 1040 if (DEBUG) { 1041 Slog.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d", 1042 mPile.getHeight(), mScrollView.getHeight(), mCarrierLabelHeight)); 1043 } 1044 1045 final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null; 1046 final boolean makeVisible = 1047 !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly()) 1048 && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight) 1049 && mScrollView.getVisibility() == View.VISIBLE; 1050 1051 if (force || mCarrierLabelVisible != makeVisible) { 1052 mCarrierLabelVisible = makeVisible; 1053 if (DEBUG) { 1054 Slog.d(TAG, "making carrier label " + (makeVisible?"visible":"invisible")); 1055 } 1056 mCarrierLabel.animate().cancel(); 1057 if (makeVisible) { 1058 mCarrierLabel.setVisibility(View.VISIBLE); 1059 } 1060 mCarrierLabel.animate() 1061 .alpha(makeVisible ? 1f : 0f) 1062 //.setStartDelay(makeVisible ? 500 : 0) 1063 //.setDuration(makeVisible ? 750 : 100) 1064 .setDuration(150) 1065 .setListener(makeVisible ? null : new AnimatorListenerAdapter() { 1066 @Override 1067 public void onAnimationEnd(Animator animation) { 1068 if (!mCarrierLabelVisible) { // race 1069 mCarrierLabel.setVisibility(View.INVISIBLE); 1070 mCarrierLabel.setAlpha(0f); 1071 } 1072 } 1073 }) 1074 .start(); 1075 } 1076 } 1077 1078 @Override 1079 protected void setAreThereNotifications() { 1080 final boolean any = mNotificationData.size() > 0; 1081 1082 final boolean clearable = any && mNotificationData.hasClearableItems(); 1083 1084 if (DEBUG) { 1085 Slog.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size() 1086 + " any=" + any + " clearable=" + clearable); 1087 } 1088 1089 if (mHasFlipSettings 1090 && mFlipSettingsView != null 1091 && mFlipSettingsView.getVisibility() == View.VISIBLE 1092 && mScrollView.getVisibility() != View.VISIBLE) { 1093 // the flip settings panel is unequivocally showing; we should not be shown 1094 mClearButton.setVisibility(View.INVISIBLE); 1095 } else if (mClearButton.isShown()) { 1096 if (clearable != (mClearButton.getAlpha() == 1.0f)) { 1097 ObjectAnimator clearAnimation = ObjectAnimator.ofFloat( 1098 mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250); 1099 clearAnimation.addListener(new AnimatorListenerAdapter() { 1100 @Override 1101 public void onAnimationEnd(Animator animation) { 1102 if (mClearButton.getAlpha() <= 0.0f) { 1103 mClearButton.setVisibility(View.INVISIBLE); 1104 } 1105 } 1106 1107 @Override 1108 public void onAnimationStart(Animator animation) { 1109 if (mClearButton.getAlpha() <= 0.0f) { 1110 mClearButton.setVisibility(View.VISIBLE); 1111 } 1112 } 1113 }); 1114 clearAnimation.start(); 1115 } 1116 } else { 1117 mClearButton.setAlpha(clearable ? 1.0f : 0.0f); 1118 mClearButton.setVisibility(clearable ? View.VISIBLE : View.INVISIBLE); 1119 } 1120 mClearButton.setEnabled(clearable); 1121 1122 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); 1123 final boolean showDot = (any&&!areLightsOn()); 1124 if (showDot != (nlo.getAlpha() == 1.0f)) { 1125 if (showDot) { 1126 nlo.setAlpha(0f); 1127 nlo.setVisibility(View.VISIBLE); 1128 } 1129 nlo.animate() 1130 .alpha(showDot?1:0) 1131 .setDuration(showDot?750:250) 1132 .setInterpolator(new AccelerateInterpolator(2.0f)) 1133 .setListener(showDot ? null : new AnimatorListenerAdapter() { 1134 @Override 1135 public void onAnimationEnd(Animator _a) { 1136 nlo.setVisibility(View.GONE); 1137 } 1138 }) 1139 .start(); 1140 } 1141 1142 updateCarrierLabelVisibility(false); 1143 } 1144 1145 public void showClock(boolean show) { 1146 if (mStatusBarView == null) return; 1147 View clock = mStatusBarView.findViewById(R.id.clock); 1148 if (clock != null) { 1149 clock.setVisibility(show ? View.VISIBLE : View.GONE); 1150 } 1151 } 1152 1153 /** 1154 * State is one or more of the DISABLE constants from StatusBarManager. 1155 */ 1156 public void disable(int state) { 1157 final int old = mDisabled; 1158 final int diff = state ^ old; 1159 mDisabled = state; 1160 1161 if (DEBUG) { 1162 Slog.d(TAG, String.format("disable: 0x%08x -> 0x%08x (diff: 0x%08x)", 1163 old, state, diff)); 1164 } 1165 1166 StringBuilder flagdbg = new StringBuilder(); 1167 flagdbg.append("disable: < "); 1168 flagdbg.append(((state & StatusBarManager.DISABLE_EXPAND) != 0) ? "EXPAND" : "expand"); 1169 flagdbg.append(((diff & StatusBarManager.DISABLE_EXPAND) != 0) ? "* " : " "); 1170 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "ICONS" : "icons"); 1171 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " "); 1172 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts"); 1173 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " "); 1174 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "TICKER" : "ticker"); 1175 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "* " : " "); 1176 flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info"); 1177 flagdbg.append(((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " "); 1178 flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back"); 1179 flagdbg.append(((diff & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " "); 1180 flagdbg.append(((state & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home"); 1181 flagdbg.append(((diff & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " "); 1182 flagdbg.append(((state & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent"); 1183 flagdbg.append(((diff & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " "); 1184 flagdbg.append(((state & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock"); 1185 flagdbg.append(((diff & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " "); 1186 flagdbg.append(((state & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search"); 1187 flagdbg.append(((diff & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " "); 1188 flagdbg.append(">"); 1189 Slog.d(TAG, flagdbg.toString()); 1190 1191 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { 1192 mSystemIconArea.animate().cancel(); 1193 if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { 1194 mSystemIconArea.animate() 1195 .alpha(0f) 1196 .translationY(mNaturalBarHeight*0.5f) 1197 .setDuration(175) 1198 .setInterpolator(new DecelerateInterpolator(1.5f)) 1199 .setListener(mMakeIconsInvisible) 1200 .start(); 1201 } else { 1202 mSystemIconArea.setVisibility(View.VISIBLE); 1203 mSystemIconArea.animate() 1204 .alpha(1f) 1205 .translationY(0) 1206 .setStartDelay(0) 1207 .setInterpolator(new DecelerateInterpolator(1.5f)) 1208 .setDuration(175) 1209 .start(); 1210 } 1211 } 1212 1213 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) { 1214 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0; 1215 showClock(show); 1216 } 1217 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) { 1218 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) { 1219 animateCollapsePanels(); 1220 } 1221 } 1222 1223 if ((diff & (StatusBarManager.DISABLE_HOME 1224 | StatusBarManager.DISABLE_RECENT 1225 | StatusBarManager.DISABLE_BACK 1226 | StatusBarManager.DISABLE_SEARCH)) != 0) { 1227 // the nav bar will take care of these 1228 if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state); 1229 1230 if ((state & StatusBarManager.DISABLE_RECENT) != 0) { 1231 // close recents if it's visible 1232 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL); 1233 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL); 1234 } 1235 } 1236 1237 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { 1238 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { 1239 if (mTicking) { 1240 haltTicker(); 1241 } 1242 1243 mNotificationIcons.animate() 1244 .alpha(0f) 1245 .translationY(mNaturalBarHeight*0.5f) 1246 .setDuration(175) 1247 .setInterpolator(new DecelerateInterpolator(1.5f)) 1248 .setListener(mMakeIconsInvisible) 1249 .start(); 1250 } else { 1251 mNotificationIcons.setVisibility(View.VISIBLE); 1252 mNotificationIcons.animate() 1253 .alpha(1f) 1254 .translationY(0) 1255 .setStartDelay(0) 1256 .setInterpolator(new DecelerateInterpolator(1.5f)) 1257 .setDuration(175) 1258 .start(); 1259 } 1260 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { 1261 if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { 1262 haltTicker(); 1263 } 1264 } 1265 } 1266 1267 @Override 1268 protected BaseStatusBar.H createHandler() { 1269 return new PhoneStatusBar.H(); 1270 } 1271 1272 /** 1273 * All changes to the status bar and notifications funnel through here and are batched. 1274 */ 1275 private class H extends BaseStatusBar.H { 1276 public void handleMessage(Message m) { 1277 super.handleMessage(m); 1278 switch (m.what) { 1279 case MSG_OPEN_NOTIFICATION_PANEL: 1280 animateExpandNotificationsPanel(); 1281 break; 1282 case MSG_OPEN_SETTINGS_PANEL: 1283 animateExpandSettingsPanel(); 1284 break; 1285 case MSG_CLOSE_PANELS: 1286 animateCollapsePanels(); 1287 break; 1288 case MSG_SHOW_INTRUDER: 1289 setIntruderAlertVisibility(true); 1290 break; 1291 case MSG_HIDE_INTRUDER: 1292 setIntruderAlertVisibility(false); 1293 mCurrentlyIntrudingNotification = null; 1294 break; 1295 } 1296 } 1297 } 1298 1299 public Handler getHandler() { 1300 return mHandler; 1301 } 1302 1303 View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() { 1304 public void onFocusChange(View v, boolean hasFocus) { 1305 // Because 'v' is a ViewGroup, all its children will be (un)selected 1306 // too, which allows marqueeing to work. 1307 v.setSelected(hasFocus); 1308 } 1309 }; 1310 1311 void makeExpandedVisible(boolean revealAfterDraw) { 1312 if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); 1313 if (mExpandedVisible) { 1314 return; 1315 } 1316 1317 mExpandedVisible = true; 1318 mPile.setLayoutTransitionsEnabled(true); 1319 if (mNavigationBarView != null) 1320 mNavigationBarView.setSlippery(true); 1321 1322 updateCarrierLabelVisibility(true); 1323 1324 updateExpandedViewPos(EXPANDED_LEAVE_ALONE); 1325 1326 // Expand the window to encompass the full screen in anticipation of the drag. 1327 // This is only possible to do atomically because the status bar is at the top of the screen! 1328 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams(); 1329 lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 1330 lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 1331 lp.height = ViewGroup.LayoutParams.MATCH_PARENT; 1332 mWindowManager.updateViewLayout(mStatusBarWindow, lp); 1333 1334 // Updating the window layout will force an expensive traversal/redraw. 1335 // Kick off the reveal animation after this is complete to avoid animation latency. 1336 if (revealAfterDraw) { 1337// mHandler.post(mStartRevealAnimation); 1338 } 1339 1340 visibilityChanged(true); 1341 } 1342 1343 public void animateCollapsePanels() { 1344 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 1345 } 1346 1347 public void animateCollapsePanels(int flags) { 1348 if (SPEW) { 1349 Slog.d(TAG, "animateCollapse():" 1350 + " mExpandedVisible=" + mExpandedVisible 1351 + " mAnimating=" + mAnimating 1352 + " mAnimatingReveal=" + mAnimatingReveal 1353 + " mAnimY=" + mAnimY 1354 + " mAnimVel=" + mAnimVel 1355 + " flags=" + flags); 1356 } 1357 1358 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) { 1359 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL); 1360 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL); 1361 } 1362 1363 if ((flags & CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL) == 0) { 1364 mHandler.removeMessages(MSG_CLOSE_SEARCH_PANEL); 1365 mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL); 1366 } 1367 1368 mStatusBarView.collapseAllPanels(true); 1369 } 1370 1371 public ViewPropertyAnimator setVisibilityWhenDone( 1372 final ViewPropertyAnimator a, final View v, final int vis) { 1373 a.setListener(new AnimatorListenerAdapter() { 1374 @Override 1375 public void onAnimationEnd(Animator animation) { 1376 v.setVisibility(vis); 1377 a.setListener(null); // oneshot 1378 } 1379 }); 1380 return a; 1381 } 1382 1383 public Animator setVisibilityWhenDone( 1384 final Animator a, final View v, final int vis) { 1385 a.addListener(new AnimatorListenerAdapter() { 1386 @Override 1387 public void onAnimationEnd(Animator animation) { 1388 v.setVisibility(vis); 1389 } 1390 }); 1391 return a; 1392 } 1393 1394 public Animator interpolator(TimeInterpolator ti, Animator a) { 1395 a.setInterpolator(ti); 1396 return a; 1397 } 1398 1399 public Animator startDelay(int d, Animator a) { 1400 a.setStartDelay(d); 1401 return a; 1402 } 1403 1404 public Animator start(Animator a) { 1405 a.start(); 1406 return a; 1407 } 1408 1409 final TimeInterpolator mAccelerateInterpolator = new AccelerateInterpolator(); 1410 final TimeInterpolator mDecelerateInterpolator = new DecelerateInterpolator(); 1411 final int FLIP_DURATION_OUT = 125; 1412 final int FLIP_DURATION_IN = 225; 1413 final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT); 1414 1415 Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim, 1416 mSettingsButtonAnim, mClearButtonAnim; 1417 1418 @Override 1419 public void animateExpandNotificationsPanel() { 1420 if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 1421 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) { 1422 return ; 1423 } 1424 1425 mNotificationPanel.expand(); 1426 if (mHasFlipSettings && mScrollView.getVisibility() != View.VISIBLE) { 1427 flipToNotifications(); 1428 } 1429 1430 if (false) postStartTracing(); 1431 } 1432 1433 public void flipToNotifications() { 1434 if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel(); 1435 if (mScrollViewAnim != null) mScrollViewAnim.cancel(); 1436 if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); 1437 if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); 1438 if (mClearButtonAnim != null) mClearButtonAnim.cancel(); 1439 1440 mScrollView.setVisibility(View.VISIBLE); 1441 mScrollViewAnim = start( 1442 startDelay(FLIP_DURATION_OUT, 1443 interpolator(mDecelerateInterpolator, 1444 ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f) 1445 .setDuration(FLIP_DURATION_IN) 1446 ))); 1447 mFlipSettingsViewAnim = start( 1448 setVisibilityWhenDone( 1449 interpolator(mAccelerateInterpolator, 1450 ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f) 1451 ) 1452 .setDuration(FLIP_DURATION_OUT), 1453 mFlipSettingsView, View.INVISIBLE)); 1454 mNotificationButtonAnim = start( 1455 setVisibilityWhenDone( 1456 ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f) 1457 .setDuration(FLIP_DURATION), 1458 mNotificationButton, View.INVISIBLE)); 1459 mSettingsButton.setVisibility(View.VISIBLE); 1460 mSettingsButtonAnim = start( 1461 ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f) 1462 .setDuration(FLIP_DURATION)); 1463 mClearButton.setVisibility(View.VISIBLE); 1464 mClearButton.setAlpha(0f); 1465 setAreThereNotifications(); // this will show/hide the button as necessary 1466 mNotificationPanel.postDelayed(new Runnable() { 1467 public void run() { 1468 updateCarrierLabelVisibility(false); 1469 } 1470 }, FLIP_DURATION - 150); 1471 } 1472 1473 @Override 1474 public void animateExpandSettingsPanel() { 1475 if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 1476 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) { 1477 return; 1478 } 1479 1480 if (mHasFlipSettings) { 1481 mNotificationPanel.expand(); 1482 if (mFlipSettingsView.getVisibility() != View.VISIBLE) { 1483 flipToSettings(); 1484 } 1485 } else if (mSettingsPanel != null) { 1486 mSettingsPanel.expand(); 1487 } 1488 1489 if (false) postStartTracing(); 1490 } 1491 1492 public void switchToSettings() { 1493 mFlipSettingsView.setScaleX(1f); 1494 mFlipSettingsView.setVisibility(View.VISIBLE); 1495 mSettingsButton.setVisibility(View.GONE); 1496 mScrollView.setVisibility(View.GONE); 1497 mScrollView.setScaleX(0f); 1498 mNotificationButton.setVisibility(View.VISIBLE); 1499 mNotificationButton.setAlpha(1f); 1500 mClearButton.setVisibility(View.GONE); 1501 } 1502 1503 public void flipToSettings() { 1504 if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel(); 1505 if (mScrollViewAnim != null) mScrollViewAnim.cancel(); 1506 if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); 1507 if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); 1508 if (mClearButtonAnim != null) mClearButtonAnim.cancel(); 1509 1510 mFlipSettingsView.setVisibility(View.VISIBLE); 1511 mFlipSettingsView.setScaleX(0f); 1512 mFlipSettingsViewAnim = start( 1513 startDelay(FLIP_DURATION_OUT, 1514 interpolator(mDecelerateInterpolator, 1515 ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f) 1516 .setDuration(FLIP_DURATION_IN) 1517 ))); 1518 mScrollViewAnim = start( 1519 setVisibilityWhenDone( 1520 interpolator(mAccelerateInterpolator, 1521 ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f) 1522 ) 1523 .setDuration(FLIP_DURATION_OUT), 1524 mScrollView, View.INVISIBLE)); 1525 mSettingsButtonAnim = start( 1526 setVisibilityWhenDone( 1527 ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f) 1528 .setDuration(FLIP_DURATION), 1529 mScrollView, View.INVISIBLE)); 1530 mNotificationButton.setVisibility(View.VISIBLE); 1531 mNotificationButtonAnim = start( 1532 ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f) 1533 .setDuration(FLIP_DURATION)); 1534 mClearButtonAnim = start( 1535 setVisibilityWhenDone( 1536 ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f) 1537 .setDuration(FLIP_DURATION), 1538 mClearButton, View.INVISIBLE)); 1539 mNotificationPanel.postDelayed(new Runnable() { 1540 public void run() { 1541 updateCarrierLabelVisibility(false); 1542 } 1543 }, FLIP_DURATION - 150); 1544 } 1545 1546 public void flipPanels() { 1547 if (mHasFlipSettings) { 1548 if (mFlipSettingsView.getVisibility() != View.VISIBLE) { 1549 flipToSettings(); 1550 } else { 1551 flipToNotifications(); 1552 } 1553 } 1554 } 1555 1556 public void animateCollapseQuickSettings() { 1557 mStatusBarView.collapseAllPanels(true); 1558 } 1559 1560 void makeExpandedInvisibleSoon() { 1561 mHandler.postDelayed(new Runnable() { public void run() { makeExpandedInvisible(); }}, 50); 1562 } 1563 1564 void makeExpandedInvisible() { 1565 if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible 1566 + " mExpandedVisible=" + mExpandedVisible); 1567 1568 if (!mExpandedVisible) { 1569 return; 1570 } 1571 1572 // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) 1573 mStatusBarView.collapseAllPanels(/*animate=*/ false); 1574 1575 if (mHasFlipSettings) { 1576 // reset things to their proper state 1577 mScrollView.setScaleX(1f); 1578 mScrollView.setVisibility(View.VISIBLE); 1579 mSettingsButton.setAlpha(1f); 1580 mSettingsButton.setVisibility(View.VISIBLE); 1581 mNotificationPanel.setVisibility(View.GONE); 1582 mFlipSettingsView.setVisibility(View.GONE); 1583 mNotificationButton.setVisibility(View.GONE); 1584 setAreThereNotifications(); // show the clear button 1585 } 1586 1587 mExpandedVisible = false; 1588 mPile.setLayoutTransitionsEnabled(false); 1589 if (mNavigationBarView != null) 1590 mNavigationBarView.setSlippery(false); 1591 visibilityChanged(false); 1592 1593 // Shrink the window to the size of the status bar only 1594 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams(); 1595 lp.height = getStatusBarHeight(); 1596 lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 1597 lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 1598 mWindowManager.updateViewLayout(mStatusBarWindow, lp); 1599 1600 if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) { 1601 setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in); 1602 } 1603 1604 // Close any "App info" popups that might have snuck on-screen 1605 dismissPopups(); 1606 1607 if (mPostCollapseCleanup != null) { 1608 mPostCollapseCleanup.run(); 1609 mPostCollapseCleanup = null; 1610 } 1611 } 1612 1613 /** 1614 * Enables or disables layers on the children of the notifications pile. 1615 * 1616 * When layers are enabled, this method attempts to enable layers for the minimal 1617 * number of children. Only children visible when the notification area is fully 1618 * expanded will receive a layer. The technique used in this method might cause 1619 * more children than necessary to get a layer (at most one extra child with the 1620 * current UI.) 1621 * 1622 * @param layerType {@link View#LAYER_TYPE_NONE} or {@link View#LAYER_TYPE_HARDWARE} 1623 */ 1624 private void setPileLayers(int layerType) { 1625 final int count = mPile.getChildCount(); 1626 1627 switch (layerType) { 1628 case View.LAYER_TYPE_NONE: 1629 for (int i = 0; i < count; i++) { 1630 mPile.getChildAt(i).setLayerType(layerType, null); 1631 } 1632 break; 1633 case View.LAYER_TYPE_HARDWARE: 1634 final int[] location = new int[2]; 1635 mNotificationPanel.getLocationInWindow(location); 1636 1637 final int left = location[0]; 1638 final int top = location[1]; 1639 final int right = left + mNotificationPanel.getWidth(); 1640 final int bottom = top + getExpandedViewMaxHeight(); 1641 1642 final Rect childBounds = new Rect(); 1643 1644 for (int i = 0; i < count; i++) { 1645 final View view = mPile.getChildAt(i); 1646 view.getLocationInWindow(location); 1647 1648 childBounds.set(location[0], location[1], 1649 location[0] + view.getWidth(), location[1] + view.getHeight()); 1650 1651 if (childBounds.intersects(left, top, right, bottom)) { 1652 view.setLayerType(layerType, null); 1653 } 1654 } 1655 1656 break; 1657 } 1658 } 1659 1660 public boolean isClinging() { 1661 return mCling != null && mCling.getVisibility() == View.VISIBLE; 1662 } 1663 1664 public void hideCling() { 1665 if (isClinging()) { 1666 mCling.animate().alpha(0f).setDuration(250).start(); 1667 mCling.setVisibility(View.GONE); 1668 mSuppressStatusBarDrags = false; 1669 } 1670 } 1671 1672 public void showCling() { 1673 // lazily inflate this to accommodate orientation change 1674 final ViewStub stub = (ViewStub) mStatusBarWindow.findViewById(R.id.status_bar_cling_stub); 1675 if (stub == null) { 1676 mClingShown = true; 1677 return; // no clings on this device 1678 } 1679 1680 mSuppressStatusBarDrags = true; 1681 1682 mHandler.postDelayed(new Runnable() { 1683 @Override 1684 public void run() { 1685 mCling = (ViewGroup) stub.inflate(); 1686 1687 mCling.setOnTouchListener(new View.OnTouchListener() { 1688 @Override 1689 public boolean onTouch(View v, MotionEvent event) { 1690 return true; // e eats everything 1691 }}); 1692 mCling.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() { 1693 @Override 1694 public void onClick(View v) { 1695 hideCling(); 1696 }}); 1697 1698 mCling.setAlpha(0f); 1699 mCling.setVisibility(View.VISIBLE); 1700 mCling.animate().alpha(1f); 1701 1702 mClingShown = true; 1703 SharedPreferences.Editor editor = Prefs.edit(mContext); 1704 editor.putBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, true); 1705 editor.apply(); 1706 1707 makeExpandedVisible(true); // enforce visibility in case the shade is still animating closed 1708 animateExpandNotificationsPanel(); 1709 1710 mSuppressStatusBarDrags = false; 1711 } 1712 }, 500); 1713 1714 animateExpandNotificationsPanel(); 1715 } 1716 1717 public boolean interceptTouchEvent(MotionEvent event) { 1718 if (SPEW) { 1719 Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled=" 1720 + mDisabled + " mTracking=" + mTracking); 1721 } else if (CHATTY) { 1722 if (event.getAction() != MotionEvent.ACTION_MOVE) { 1723 Slog.d(TAG, String.format( 1724 "panel: %s at (%f, %f) mDisabled=0x%08x", 1725 MotionEvent.actionToString(event.getAction()), 1726 event.getRawX(), event.getRawY(), mDisabled)); 1727 } 1728 } 1729 1730 if (DEBUG_GESTURES) { 1731 mGestureRec.add(event); 1732 } 1733 1734 // Cling (first-run help) handling. 1735 // The cling is supposed to show the first time you drag, or even tap, the status bar. 1736 // It should show the notification panel, then fade in after half a second, giving you 1737 // an explanation of what just happened, as well as teach you how to access quick 1738 // settings (another drag). The user can dismiss the cling by clicking OK or by 1739 // dragging quick settings into view. 1740 final int act = event.getActionMasked(); 1741 if (mSuppressStatusBarDrags) { 1742 return true; 1743 } else if (act == MotionEvent.ACTION_UP && !mClingShown) { 1744 showCling(); 1745 } else { 1746 hideCling(); 1747 } 1748 1749 return false; 1750 } 1751 1752 public GestureRecorder getGestureRecorder() { 1753 return mGestureRec; 1754 } 1755 1756 @Override // CommandQueue 1757 public void setNavigationIconHints(int hints) { 1758 if (hints == mNavigationIconHints) return; 1759 1760 mNavigationIconHints = hints; 1761 1762 if (mNavigationBarView != null) { 1763 mNavigationBarView.setNavigationIconHints(hints); 1764 } 1765 } 1766 1767 @Override // CommandQueue 1768 public void setSystemUiVisibility(int vis, int mask) { 1769 final int oldVal = mSystemUiVisibility; 1770 final int newVal = (oldVal&~mask) | (vis&mask); 1771 final int diff = newVal ^ oldVal; 1772 1773 if (diff != 0) { 1774 mSystemUiVisibility = newVal; 1775 1776 if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) { 1777 final boolean lightsOut = (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)); 1778 if (lightsOut) { 1779 animateCollapsePanels(); 1780 if (mTicking) { 1781 haltTicker(); 1782 } 1783 } 1784 1785 if (mNavigationBarView != null) { 1786 mNavigationBarView.setLowProfile(lightsOut); 1787 } 1788 1789 setStatusBarLowProfile(lightsOut); 1790 } 1791 1792 notifyUiVisibilityChanged(); 1793 } 1794 } 1795 1796 private void setStatusBarLowProfile(boolean lightsOut) { 1797 if (mLightsOutAnimation == null) { 1798 final View notifications = mStatusBarView.findViewById(R.id.notification_icon_area); 1799 final View systemIcons = mStatusBarView.findViewById(R.id.statusIcons); 1800 final View signal = mStatusBarView.findViewById(R.id.signal_cluster); 1801 final View battery = mStatusBarView.findViewById(R.id.battery); 1802 final View clock = mStatusBarView.findViewById(R.id.clock); 1803 1804 final AnimatorSet lightsOutAnim = new AnimatorSet(); 1805 lightsOutAnim.playTogether( 1806 ObjectAnimator.ofFloat(notifications, View.ALPHA, 0), 1807 ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 0), 1808 ObjectAnimator.ofFloat(signal, View.ALPHA, 0), 1809 ObjectAnimator.ofFloat(battery, View.ALPHA, 0.5f), 1810 ObjectAnimator.ofFloat(clock, View.ALPHA, 0.5f) 1811 ); 1812 lightsOutAnim.setDuration(750); 1813 1814 final AnimatorSet lightsOnAnim = new AnimatorSet(); 1815 lightsOnAnim.playTogether( 1816 ObjectAnimator.ofFloat(notifications, View.ALPHA, 1), 1817 ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 1), 1818 ObjectAnimator.ofFloat(signal, View.ALPHA, 1), 1819 ObjectAnimator.ofFloat(battery, View.ALPHA, 1), 1820 ObjectAnimator.ofFloat(clock, View.ALPHA, 1) 1821 ); 1822 lightsOnAnim.setDuration(250); 1823 1824 mLightsOutAnimation = lightsOutAnim; 1825 mLightsOnAnimation = lightsOnAnim; 1826 } 1827 1828 mLightsOutAnimation.cancel(); 1829 mLightsOnAnimation.cancel(); 1830 1831 final Animator a = lightsOut ? mLightsOutAnimation : mLightsOnAnimation; 1832 a.start(); 1833 1834 setAreThereNotifications(); 1835 } 1836 1837 private boolean areLightsOn() { 1838 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); 1839 } 1840 1841 public void setLightsOn(boolean on) { 1842 Log.v(TAG, "setLightsOn(" + on + ")"); 1843 if (on) { 1844 setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE); 1845 } else { 1846 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE); 1847 } 1848 } 1849 1850 private void notifyUiVisibilityChanged() { 1851 try { 1852 mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility); 1853 } catch (RemoteException ex) { 1854 } 1855 } 1856 1857 public void topAppWindowChanged(boolean showMenu) { 1858 if (DEBUG) { 1859 Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button"); 1860 } 1861 if (mNavigationBarView != null) { 1862 mNavigationBarView.setMenuVisibility(showMenu); 1863 } 1864 1865 // See above re: lights-out policy for legacy apps. 1866 if (showMenu) setLightsOn(true); 1867 } 1868 1869 @Override 1870 public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { 1871 boolean altBack = (backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) 1872 || ((vis & InputMethodService.IME_VISIBLE) != 0); 1873 1874 mCommandQueue.setNavigationIconHints( 1875 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT) 1876 : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT)); 1877 if (mQS != null) mQS.setImeWindowStatus(vis > 0); 1878 } 1879 1880 @Override 1881 public void setHardKeyboardStatus(boolean available, boolean enabled) {} 1882 1883 @Override 1884 protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) { 1885 // no ticking in lights-out mode 1886 if (!areLightsOn()) return; 1887 1888 // no ticking in Setup 1889 if (!isDeviceProvisioned()) return; 1890 1891 // not for you 1892 if (!notificationIsForCurrentUser(n)) return; 1893 1894 // Show the ticker if one is requested. Also don't do this 1895 // until status bar window is attached to the window manager, 1896 // because... well, what's the point otherwise? And trying to 1897 // run a ticker without being attached will crash! 1898 if (n.notification.tickerText != null && mStatusBarWindow.getWindowToken() != null) { 1899 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS 1900 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) { 1901 mTicker.addEntry(n); 1902 } 1903 } 1904 } 1905 1906 private class MyTicker extends Ticker { 1907 MyTicker(Context context, View sb) { 1908 super(context, sb); 1909 } 1910 1911 @Override 1912 public void tickerStarting() { 1913 mTicking = true; 1914 mStatusBarContents.setVisibility(View.GONE); 1915 mTickerView.setVisibility(View.VISIBLE); 1916 mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_up_in, null)); 1917 mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null)); 1918 } 1919 1920 @Override 1921 public void tickerDone() { 1922 mStatusBarContents.setVisibility(View.VISIBLE); 1923 mTickerView.setVisibility(View.GONE); 1924 mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null)); 1925 mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_down_out, 1926 mTickingDoneListener)); 1927 } 1928 1929 public void tickerHalting() { 1930 mStatusBarContents.setVisibility(View.VISIBLE); 1931 mTickerView.setVisibility(View.GONE); 1932 mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null)); 1933 // we do not animate the ticker away at this point, just get rid of it (b/6992707) 1934 } 1935 } 1936 1937 Animation.AnimationListener mTickingDoneListener = new Animation.AnimationListener() {; 1938 public void onAnimationEnd(Animation animation) { 1939 mTicking = false; 1940 } 1941 public void onAnimationRepeat(Animation animation) { 1942 } 1943 public void onAnimationStart(Animation animation) { 1944 } 1945 }; 1946 1947 private Animation loadAnim(int id, Animation.AnimationListener listener) { 1948 Animation anim = AnimationUtils.loadAnimation(mContext, id); 1949 if (listener != null) { 1950 anim.setAnimationListener(listener); 1951 } 1952 return anim; 1953 } 1954 1955 public static String viewInfo(View v) { 1956 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() 1957 + ") " + v.getWidth() + "x" + v.getHeight() + "]"; 1958 } 1959 1960 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1961 synchronized (mQueueLock) { 1962 pw.println("Current Status Bar state:"); 1963 pw.println(" mExpandedVisible=" + mExpandedVisible 1964 + ", mTrackingPosition=" + mTrackingPosition); 1965 pw.println(" mTicking=" + mTicking); 1966 pw.println(" mTracking=" + mTracking); 1967 pw.println(" mNotificationPanel=" + 1968 ((mNotificationPanel == null) 1969 ? "null" 1970 : (mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug("")))); 1971 pw.println(" mAnimating=" + mAnimating 1972 + ", mAnimY=" + mAnimY + ", mAnimVel=" + mAnimVel 1973 + ", mAnimAccel=" + mAnimAccel); 1974 pw.println(" mAnimLastTimeNanos=" + mAnimLastTimeNanos); 1975 pw.println(" mAnimatingReveal=" + mAnimatingReveal 1976 + " mViewDelta=" + mViewDelta); 1977 pw.println(" mDisplayMetrics=" + mDisplayMetrics); 1978 pw.println(" mPile: " + viewInfo(mPile)); 1979 pw.println(" mTickerView: " + viewInfo(mTickerView)); 1980 pw.println(" mScrollView: " + viewInfo(mScrollView) 1981 + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY()); 1982 } 1983 1984 pw.print(" mNavigationBarView="); 1985 if (mNavigationBarView == null) { 1986 pw.println("null"); 1987 } else { 1988 mNavigationBarView.dump(fd, pw, args); 1989 } 1990 1991 if (DUMPTRUCK) { 1992 synchronized (mNotificationData) { 1993 int N = mNotificationData.size(); 1994 pw.println(" notification icons: " + N); 1995 for (int i=0; i<N; i++) { 1996 NotificationData.Entry e = mNotificationData.get(i); 1997 pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon); 1998 StatusBarNotification n = e.notification; 1999 pw.println(" pkg=" + n.pkg + " id=" + n.id + " score=" + n.score); 2000 pw.println(" notification=" + n.notification); 2001 pw.println(" tickerText=\"" + n.notification.tickerText + "\""); 2002 } 2003 } 2004 2005 int N = mStatusIcons.getChildCount(); 2006 pw.println(" system icons: " + N); 2007 for (int i=0; i<N; i++) { 2008 StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i); 2009 pw.println(" [" + i + "] icon=" + ic); 2010 } 2011 2012 if (false) { 2013 pw.println("see the logcat for a dump of the views we have created."); 2014 // must happen on ui thread 2015 mHandler.post(new Runnable() { 2016 public void run() { 2017 mStatusBarView.getLocationOnScreen(mAbsPos); 2018 Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] 2019 + ") " + mStatusBarView.getWidth() + "x" 2020 + getStatusBarHeight()); 2021 mStatusBarView.debug(); 2022 } 2023 }); 2024 } 2025 } 2026 2027 if (DEBUG_GESTURES) { 2028 pw.print(" status bar gestures: "); 2029 mGestureRec.dump(fd, pw, args); 2030 } 2031 2032 mNetworkController.dump(fd, pw, args); 2033 } 2034 2035 @Override 2036 public void createAndAddWindows() { 2037 addStatusBarWindow(); 2038 } 2039 2040 private void addStatusBarWindow() { 2041 // Put up the view 2042 final int height = getStatusBarHeight(); 2043 2044 // Now that the status bar window encompasses the sliding panel and its 2045 // translucent backdrop, the entire thing is made TRANSLUCENT and is 2046 // hardware-accelerated. 2047 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 2048 ViewGroup.LayoutParams.MATCH_PARENT, 2049 height, 2050 WindowManager.LayoutParams.TYPE_STATUS_BAR, 2051 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2052 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 2053 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 2054 PixelFormat.TRANSLUCENT); 2055 2056 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 2057 2058 lp.gravity = getStatusBarGravity(); 2059 lp.setTitle("StatusBar"); 2060 lp.packageName = mContext.getPackageName(); 2061 2062 makeStatusBarView(); 2063 mWindowManager.addView(mStatusBarWindow, lp); 2064 } 2065 2066 void setNotificationIconVisibility(boolean visible, int anim) { 2067 int old = mNotificationIcons.getVisibility(); 2068 int v = visible ? View.VISIBLE : View.INVISIBLE; 2069 if (old != v) { 2070 mNotificationIcons.setVisibility(v); 2071 mNotificationIcons.startAnimation(loadAnim(anim, null)); 2072 } 2073 } 2074 2075 void updateExpandedInvisiblePosition() { 2076 mTrackingPosition = -mDisplayMetrics.heightPixels; 2077 } 2078 2079 static final float saturate(float a) { 2080 return a < 0f ? 0f : (a > 1f ? 1f : a); 2081 } 2082 2083 @Override 2084 protected int getExpandedViewMaxHeight() { 2085 return mDisplayMetrics.heightPixels - mNotificationPanelMarginBottomPx; 2086 } 2087 2088 @Override 2089 public void updateExpandedViewPos(int thingy) { 2090 if (DEBUG) Slog.v(TAG, "updateExpandedViewPos"); 2091 2092 // on larger devices, the notification panel is propped open a bit 2093 mNotificationPanel.setMinimumHeight( 2094 (int)(mNotificationPanelMinHeightFrac * mCurrentDisplaySize.y)); 2095 2096 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams(); 2097 lp.gravity = mNotificationPanelGravity; 2098 lp.leftMargin = mNotificationPanelMarginPx; 2099 mNotificationPanel.setLayoutParams(lp); 2100 2101 if (mSettingsPanel != null) { 2102 lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams(); 2103 lp.gravity = mSettingsPanelGravity; 2104 lp.rightMargin = mNotificationPanelMarginPx; 2105 mSettingsPanel.setLayoutParams(lp); 2106 } 2107 2108 updateCarrierLabelVisibility(false); 2109 } 2110 2111 // called by makeStatusbar and also by PhoneStatusBarView 2112 void updateDisplaySize() { 2113 mDisplay.getMetrics(mDisplayMetrics); 2114 if (DEBUG_GESTURES) { 2115 mGestureRec.tag("display", 2116 String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); 2117 } 2118 } 2119 2120 private View.OnClickListener mClearButtonListener = new View.OnClickListener() { 2121 public void onClick(View v) { 2122 synchronized (mNotificationData) { 2123 // animate-swipe all dismissable notifications, then animate the shade closed 2124 int numChildren = mPile.getChildCount(); 2125 2126 int scrollTop = mScrollView.getScrollY(); 2127 int scrollBottom = scrollTop + mScrollView.getHeight(); 2128 final ArrayList<View> snapshot = new ArrayList<View>(numChildren); 2129 for (int i=0; i<numChildren; i++) { 2130 final View child = mPile.getChildAt(i); 2131 if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop && 2132 child.getTop() < scrollBottom) { 2133 snapshot.add(child); 2134 } 2135 } 2136 if (snapshot.isEmpty()) { 2137 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 2138 return; 2139 } 2140 new Thread(new Runnable() { 2141 @Override 2142 public void run() { 2143 // Decrease the delay for every row we animate to give the sense of 2144 // accelerating the swipes 2145 final int ROW_DELAY_DECREMENT = 10; 2146 int currentDelay = 140; 2147 int totalDelay = 0; 2148 2149 // Set the shade-animating state to avoid doing other work during 2150 // all of these animations. In particular, avoid layout and 2151 // redrawing when collapsing the shade. 2152 mPile.setViewRemoval(false); 2153 2154 mPostCollapseCleanup = new Runnable() { 2155 @Override 2156 public void run() { 2157 if (DEBUG) { 2158 Slog.v(TAG, "running post-collapse cleanup"); 2159 } 2160 try { 2161 mPile.setViewRemoval(true); 2162 mBarService.onClearAllNotifications(); 2163 } catch (Exception ex) { } 2164 } 2165 }; 2166 2167 View sampleView = snapshot.get(0); 2168 int width = sampleView.getWidth(); 2169 final int velocity = width * 8; // 1000/8 = 125 ms duration 2170 for (final View _v : snapshot) { 2171 mHandler.postDelayed(new Runnable() { 2172 @Override 2173 public void run() { 2174 mPile.dismissRowAnimated(_v, velocity); 2175 } 2176 }, totalDelay); 2177 currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT); 2178 totalDelay += currentDelay; 2179 } 2180 // Delay the collapse animation until after all swipe animations have 2181 // finished. Provide some buffer because there may be some extra delay 2182 // before actually starting each swipe animation. Ideally, we'd 2183 // synchronize the end of those animations with the start of the collaps 2184 // exactly. 2185 mHandler.postDelayed(new Runnable() { 2186 @Override 2187 public void run() { 2188 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 2189 } 2190 }, totalDelay + 225); 2191 } 2192 }).start(); 2193 } 2194 } 2195 }; 2196 2197 public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { 2198 if (onlyProvisioned && !isDeviceProvisioned()) return; 2199 try { 2200 // Dismiss the lock screen when Settings starts. 2201 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); 2202 } catch (RemoteException e) { 2203 } 2204 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2205 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 2206 animateCollapsePanels(); 2207 } 2208 2209 private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() { 2210 public void onClick(View v) { 2211 if (mHasSettingsPanel) { 2212 animateExpandSettingsPanel(); 2213 } else { 2214 startActivityDismissingKeyguard( 2215 new Intent(android.provider.Settings.ACTION_SETTINGS), true); 2216 } 2217 } 2218 }; 2219 2220 private View.OnClickListener mClockClickListener = new View.OnClickListener() { 2221 public void onClick(View v) { 2222 startActivityDismissingKeyguard( 2223 new Intent(Intent.ACTION_QUICK_CLOCK), true); // have fun, everyone 2224 } 2225 }; 2226 2227 private View.OnClickListener mNotificationButtonListener = new View.OnClickListener() { 2228 public void onClick(View v) { 2229 animateExpandNotificationsPanel(); 2230 } 2231 }; 2232 2233 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 2234 public void onReceive(Context context, Intent intent) { 2235 Slog.v(TAG, "onReceive: " + intent); 2236 String action = intent.getAction(); 2237 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { 2238 int flags = CommandQueue.FLAG_EXCLUDE_NONE; 2239 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { 2240 String reason = intent.getStringExtra("reason"); 2241 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { 2242 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; 2243 } 2244 } 2245 animateCollapsePanels(flags); 2246 } 2247 else if (Intent.ACTION_SCREEN_OFF.equals(action)) { 2248 // no waiting! 2249 makeExpandedInvisible(); 2250 } 2251 else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 2252 if (DEBUG) { 2253 Slog.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); 2254 } 2255 mDisplay.getSize(mCurrentDisplaySize); 2256 2257 updateResources(); 2258 repositionNavigationBar(); 2259 updateExpandedViewPos(EXPANDED_LEAVE_ALONE); 2260 updateShowSearchHoldoff(); 2261 } 2262 else if (Intent.ACTION_SCREEN_ON.equals(action)) { 2263 // work around problem where mDisplay.getRotation() is not stable while screen is off (bug 7086018) 2264 repositionNavigationBar(); 2265 } 2266 } 2267 }; 2268 2269 @Override 2270 public void userSwitched(int newUserId) { 2271 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId); 2272 animateCollapsePanels(); 2273 updateNotificationIcons(); 2274 resetUserSetupObserver(); 2275 } 2276 2277 private void resetUserSetupObserver() { 2278 mContext.getContentResolver().unregisterContentObserver(mUserSetupObserver); 2279 mUserSetupObserver.onChange(false); 2280 mContext.getContentResolver().registerContentObserver( 2281 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true, 2282 mUserSetupObserver, 2283 mCurrentUserId); 2284 } 2285 2286 private void setIntruderAlertVisibility(boolean vis) { 2287 if (!ENABLE_INTRUDERS) return; 2288 if (DEBUG) { 2289 Slog.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window"); 2290 } 2291 mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE); 2292 } 2293 2294 public void dismissIntruder() { 2295 if (mCurrentlyIntrudingNotification == null) return; 2296 2297 try { 2298 mBarService.onNotificationClear( 2299 mCurrentlyIntrudingNotification.pkg, 2300 mCurrentlyIntrudingNotification.tag, 2301 mCurrentlyIntrudingNotification.id); 2302 } catch (android.os.RemoteException ex) { 2303 // oh well 2304 } 2305 } 2306 2307 /** 2308 * Reload some of our resources when the configuration changes. 2309 * 2310 * We don't reload everything when the configuration changes -- we probably 2311 * should, but getting that smooth is tough. Someday we'll fix that. In the 2312 * meantime, just update the things that we know change. 2313 */ 2314 void updateResources() { 2315 final Context context = mContext; 2316 final Resources res = context.getResources(); 2317 2318 if (mClearButton instanceof TextView) { 2319 ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button)); 2320 } 2321 2322 // Update the QuickSettings container 2323 if (mQS != null) mQS.updateResources(); 2324 2325 loadDimens(); 2326 } 2327 2328 protected void loadDimens() { 2329 final Resources res = mContext.getResources(); 2330 2331 mNaturalBarHeight = res.getDimensionPixelSize( 2332 com.android.internal.R.dimen.status_bar_height); 2333 2334 int newIconSize = res.getDimensionPixelSize( 2335 com.android.internal.R.dimen.status_bar_icon_size); 2336 int newIconHPadding = res.getDimensionPixelSize( 2337 R.dimen.status_bar_icon_padding); 2338 2339 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) { 2340// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding); 2341 mIconHPadding = newIconHPadding; 2342 mIconSize = newIconSize; 2343 //reloadAllNotificationIcons(); // reload the tray 2344 } 2345 2346 mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore); 2347 2348 mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity); 2349 mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity); 2350 mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity); 2351 mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity); 2352 2353 mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1); 2354 mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1); 2355 2356 mExpandAccelPx = res.getDimension(R.dimen.expand_accel); 2357 mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel); 2358 2359 mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity); 2360 2361 mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity); 2362 2363 mNotificationPanelMarginBottomPx 2364 = (int) res.getDimension(R.dimen.notification_panel_margin_bottom); 2365 mNotificationPanelMarginPx 2366 = (int) res.getDimension(R.dimen.notification_panel_margin_left); 2367 mNotificationPanelGravity = res.getInteger(R.integer.notification_panel_layout_gravity); 2368 if (mNotificationPanelGravity <= 0) { 2369 mNotificationPanelGravity = Gravity.LEFT | Gravity.TOP; 2370 } 2371 mSettingsPanelGravity = res.getInteger(R.integer.settings_panel_layout_gravity); 2372 if (mSettingsPanelGravity <= 0) { 2373 mSettingsPanelGravity = Gravity.RIGHT | Gravity.TOP; 2374 } 2375 2376 mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height); 2377 mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height); 2378 2379 mNotificationPanelMinHeightFrac = res.getFraction(R.dimen.notification_panel_min_height_frac, 1, 1); 2380 if (mNotificationPanelMinHeightFrac < 0f || mNotificationPanelMinHeightFrac > 1f) { 2381 mNotificationPanelMinHeightFrac = 0f; 2382 } 2383 2384 if (false) Slog.v(TAG, "updateResources"); 2385 } 2386 2387 // 2388 // tracing 2389 // 2390 2391 void postStartTracing() { 2392 mHandler.postDelayed(mStartTracing, 3000); 2393 } 2394 2395 void vibrate() { 2396 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService( 2397 Context.VIBRATOR_SERVICE); 2398 vib.vibrate(250); 2399 } 2400 2401 Runnable mStartTracing = new Runnable() { 2402 public void run() { 2403 vibrate(); 2404 SystemClock.sleep(250); 2405 Slog.d(TAG, "startTracing"); 2406 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace"); 2407 mHandler.postDelayed(mStopTracing, 10000); 2408 } 2409 }; 2410 2411 Runnable mStopTracing = new Runnable() { 2412 public void run() { 2413 android.os.Debug.stopMethodTracing(); 2414 Slog.d(TAG, "stopTracing"); 2415 vibrate(); 2416 } 2417 }; 2418 2419 @Override 2420 protected void haltTicker() { 2421 mTicker.halt(); 2422 } 2423 2424 @Override 2425 protected boolean shouldDisableNavbarGestures() { 2426 return !isDeviceProvisioned() 2427 || mExpandedVisible 2428 || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0; 2429 } 2430 2431 private static class FastColorDrawable extends Drawable { 2432 private final int mColor; 2433 2434 public FastColorDrawable(int color) { 2435 mColor = 0xff000000 | color; 2436 } 2437 2438 @Override 2439 public void draw(Canvas canvas) { 2440 canvas.drawColor(mColor, PorterDuff.Mode.SRC); 2441 } 2442 2443 @Override 2444 public void setAlpha(int alpha) { 2445 } 2446 2447 @Override 2448 public void setColorFilter(ColorFilter cf) { 2449 } 2450 2451 @Override 2452 public int getOpacity() { 2453 return PixelFormat.OPAQUE; 2454 } 2455 2456 @Override 2457 public void setBounds(int left, int top, int right, int bottom) { 2458 } 2459 2460 @Override 2461 public void setBounds(Rect bounds) { 2462 } 2463 } 2464} 2465