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 17 package com.android.systemui.statusbar.phone; 18 19 20 import android.animation.Animator; 21 import android.animation.AnimatorListenerAdapter; 22 import android.annotation.NonNull; 23 import android.app.ActivityManager; 24 import android.app.ActivityManagerNative; 25 import android.app.IActivityManager; 26 import android.app.Notification; 27 import android.app.PendingIntent; 28 import android.app.StatusBarManager; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentCallbacks2; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.pm.IPackageManager; 35 import android.content.res.Configuration; 36 import android.content.res.Resources; 37 import android.database.ContentObserver; 38 import android.graphics.Bitmap; 39 import android.graphics.Canvas; 40 import android.graphics.ColorFilter; 41 import android.graphics.PixelFormat; 42 import android.graphics.Point; 43 import android.graphics.PointF; 44 import android.graphics.PorterDuff; 45 import android.graphics.PorterDuffXfermode; 46 import android.graphics.Rect; 47 import android.graphics.drawable.ColorDrawable; 48 import android.graphics.drawable.Drawable; 49 import android.inputmethodservice.InputMethodService; 50 import android.media.AudioAttributes; 51 import android.media.MediaMetadata; 52 import android.media.session.MediaController; 53 import android.media.session.MediaSession; 54 import android.media.session.MediaSessionManager; 55 import android.media.session.PlaybackState; 56 import android.os.AsyncTask; 57 import android.os.Bundle; 58 import android.os.Handler; 59 import android.os.HandlerThread; 60 import android.os.IBinder; 61 import android.os.Message; 62 import android.os.PowerManager; 63 import android.os.Process; 64 import android.os.RemoteException; 65 import android.os.ServiceManager; 66 import android.os.SystemClock; 67 import android.os.UserHandle; 68 import android.os.UserManager; 69 import android.provider.Settings; 70 import android.service.notification.NotificationListenerService; 71 import android.service.notification.NotificationListenerService.RankingMap; 72 import android.service.notification.StatusBarNotification; 73 import android.util.ArraySet; 74 import android.util.DisplayMetrics; 75 import android.util.EventLog; 76 import android.util.Log; 77 import android.view.Display; 78 import android.view.KeyEvent; 79 import android.view.LayoutInflater; 80 import android.view.MotionEvent; 81 import android.view.ThreadedRenderer; 82 import android.view.VelocityTracker; 83 import android.view.View; 84 import android.view.ViewGroup.LayoutParams; 85 import android.view.ViewStub; 86 import android.view.WindowManager; 87 import android.view.WindowManagerGlobal; 88 import android.view.accessibility.AccessibilityEvent; 89 import android.view.animation.AccelerateDecelerateInterpolator; 90 import android.view.animation.AccelerateInterpolator; 91 import android.view.animation.Interpolator; 92 import android.view.animation.LinearInterpolator; 93 import android.view.animation.PathInterpolator; 94 import android.widget.ImageView; 95 import android.widget.TextView; 96 97 import com.android.internal.logging.MetricsLogger; 98 import com.android.internal.statusbar.NotificationVisibility; 99 import com.android.internal.statusbar.StatusBarIcon; 100 import com.android.keyguard.KeyguardHostView.OnDismissAction; 101 import com.android.keyguard.KeyguardUpdateMonitor; 102 import com.android.keyguard.ViewMediatorCallback; 103 import com.android.systemui.BatteryMeterView; 104 import com.android.systemui.DemoMode; 105 import com.android.systemui.EventLogConstants; 106 import com.android.systemui.EventLogTags; 107 import com.android.systemui.Prefs; 108 import com.android.systemui.R; 109 import com.android.systemui.assist.AssistManager; 110 import com.android.systemui.doze.DozeHost; 111 import com.android.systemui.doze.DozeLog; 112 import com.android.systemui.keyguard.KeyguardViewMediator; 113 import com.android.systemui.qs.QSPanel; 114 import com.android.systemui.recents.ScreenPinningRequest; 115 import com.android.systemui.statusbar.ActivatableNotificationView; 116 import com.android.systemui.statusbar.BackDropView; 117 import com.android.systemui.statusbar.BaseStatusBar; 118 import com.android.systemui.statusbar.CommandQueue; 119 import com.android.systemui.statusbar.DismissView; 120 import com.android.systemui.statusbar.DragDownHelper; 121 import com.android.systemui.statusbar.EmptyShadeView; 122 import com.android.systemui.statusbar.ExpandableNotificationRow; 123 import com.android.systemui.statusbar.GestureRecorder; 124 import com.android.systemui.statusbar.KeyguardIndicationController; 125 import com.android.systemui.statusbar.NotificationData; 126 import com.android.systemui.statusbar.NotificationData.Entry; 127 import com.android.systemui.statusbar.NotificationOverflowContainer; 128 import com.android.systemui.statusbar.ScrimView; 129 import com.android.systemui.statusbar.SignalClusterView; 130 import com.android.systemui.statusbar.SpeedBumpView; 131 import com.android.systemui.statusbar.StatusBarState; 132 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; 133 import com.android.systemui.statusbar.policy.AccessibilityController; 134 import com.android.systemui.statusbar.policy.BatteryController; 135 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 136 import com.android.systemui.statusbar.policy.BluetoothControllerImpl; 137 import com.android.systemui.statusbar.policy.BrightnessMirrorController; 138 import com.android.systemui.statusbar.policy.CastControllerImpl; 139 import com.android.systemui.statusbar.policy.FlashlightController; 140 import com.android.systemui.statusbar.policy.HeadsUpManager; 141 import com.android.systemui.statusbar.policy.HotspotControllerImpl; 142 import com.android.systemui.statusbar.policy.KeyButtonView; 143 import com.android.systemui.statusbar.policy.KeyguardMonitor; 144 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; 145 import com.android.systemui.statusbar.policy.LocationControllerImpl; 146 import com.android.systemui.statusbar.policy.NetworkControllerImpl; 147 import com.android.systemui.statusbar.policy.NextAlarmController; 148 import com.android.systemui.statusbar.policy.PreviewInflater; 149 import com.android.systemui.statusbar.policy.RotationLockControllerImpl; 150 import com.android.systemui.statusbar.policy.SecurityControllerImpl; 151 import com.android.systemui.statusbar.policy.UserInfoController; 152 import com.android.systemui.statusbar.policy.UserSwitcherController; 153 import com.android.systemui.statusbar.policy.ZenModeController; 154 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 155 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; 156 import com.android.systemui.statusbar.stack.StackViewState; 157 import com.android.systemui.volume.VolumeComponent; 158 159 import java.io.FileDescriptor; 160 import java.io.PrintWriter; 161 import java.util.ArrayList; 162 import java.util.Collection; 163 import java.util.Collections; 164 import java.util.HashMap; 165 import java.util.HashSet; 166 import java.util.List; 167 import java.util.Map; 168 import java.util.TreeSet; 169 170 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; 171 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; 172 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; 173 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; 174 import static android.app.StatusBarManager.windowStateToString; 175 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; 176 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; 177 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; 178 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 179 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT; 180 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 181 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; 182 183 public class PhoneStatusBar extends BaseStatusBar implements DemoMode, 184 DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, 185 HeadsUpManager.OnHeadsUpChangedListener { 186 static final String TAG = "PhoneStatusBar"; 187 public static final boolean DEBUG = BaseStatusBar.DEBUG; 188 public static final boolean SPEW = false; 189 public static final boolean DUMPTRUCK = true; // extra dumpsys info 190 public static final boolean DEBUG_GESTURES = false; 191 public static final boolean DEBUG_MEDIA = false; 192 public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false; 193 194 public static final boolean DEBUG_WINDOW_STATE = false; 195 196 // additional instrumentation for testing purposes; intended to be left on during development 197 public static final boolean CHATTY = DEBUG; 198 199 public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; 200 201 public static final String ACTION_FAKE_ARTWORK = "fake_artwork"; 202 203 private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; 204 private static final int MSG_CLOSE_PANELS = 1001; 205 private static final int MSG_OPEN_SETTINGS_PANEL = 1002; 206 private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; 207 // 1020-1040 reserved for BaseStatusBar 208 209 // Time after we abort the launch transition. 210 private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; 211 212 private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; 213 214 private static final int STATUS_OR_NAV_TRANSIENT = 215 View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; 216 private static final long AUTOHIDE_TIMEOUT_MS = 3000; 217 218 /** The minimum delay in ms between reports of notification visibility. */ 219 private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500; 220 221 /** 222 * The delay to reset the hint text when the hint animation is finished running. 223 */ 224 private static final int HINT_RESET_DELAY_MS = 1200; 225 226 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 227 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 228 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 229 .build(); 230 231 public static final int FADE_KEYGUARD_START_DELAY = 100; 232 public static final int FADE_KEYGUARD_DURATION = 300; 233 234 /** Allow some time inbetween the long press for back and recents. */ 235 private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200; 236 237 /** If true, the system is in the half-boot-to-decryption-screen state. 238 * Prudently disable QS and notifications. */ 239 private static final boolean ONLY_CORE_APPS; 240 241 static { 242 boolean onlyCoreApps; 243 try { 244 onlyCoreApps = IPackageManager.Stub.asInterface(ServiceManager.getService("package")) 245 .isOnlyCoreApps(); 246 } catch (RemoteException e) { 247 onlyCoreApps = false; 248 } 249 ONLY_CORE_APPS = onlyCoreApps; 250 } 251 252 PhoneStatusBarPolicy mIconPolicy; 253 254 // These are no longer handled by the policy, because we need custom strategies for them 255 BluetoothControllerImpl mBluetoothController; 256 SecurityControllerImpl mSecurityController; 257 BatteryController mBatteryController; 258 LocationControllerImpl mLocationController; 259 NetworkControllerImpl mNetworkController; 260 HotspotControllerImpl mHotspotController; 261 RotationLockControllerImpl mRotationLockController; 262 UserInfoController mUserInfoController; 263 ZenModeController mZenModeController; 264 CastControllerImpl mCastController; 265 VolumeComponent mVolumeComponent; 266 KeyguardUserSwitcher mKeyguardUserSwitcher; 267 FlashlightController mFlashlightController; 268 UserSwitcherController mUserSwitcherController; 269 NextAlarmController mNextAlarmController; 270 KeyguardMonitor mKeyguardMonitor; 271 BrightnessMirrorController mBrightnessMirrorController; 272 AccessibilityController mAccessibilityController; 273 274 int mNaturalBarHeight = -1; 275 276 Display mDisplay; 277 Point mCurrentDisplaySize = new Point(); 278 279 StatusBarWindowView mStatusBarWindow; 280 PhoneStatusBarView mStatusBarView; 281 private int mStatusBarWindowState = WINDOW_STATE_SHOWING; 282 private StatusBarWindowManager mStatusBarWindowManager; 283 private UnlockMethodCache mUnlockMethodCache; 284 private DozeServiceHost mDozeServiceHost; 285 private boolean mScreenOnComingFromTouch; 286 private PointF mScreenOnTouchLocation; 287 288 int mPixelFormat; 289 Object mQueueLock = new Object(); 290 291 StatusBarIconController mIconController; 292 293 // expanded notifications 294 NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window 295 View mExpandedContents; 296 TextView mNotificationPanelDebugText; 297 298 // settings 299 private QSPanel mQSPanel; 300 301 // top bar 302 StatusBarHeaderView mHeader; 303 KeyguardStatusBarView mKeyguardStatusBar; 304 View mKeyguardStatusView; 305 KeyguardBottomAreaView mKeyguardBottomArea; 306 boolean mLeaveOpenOnKeyguardHide; 307 KeyguardIndicationController mKeyguardIndicationController; 308 309 private boolean mKeyguardFadingAway; 310 private long mKeyguardFadingAwayDelay; 311 private long mKeyguardFadingAwayDuration; 312 313 int mKeyguardMaxNotificationCount; 314 315 boolean mExpandedVisible; 316 317 private int mNavigationBarWindowState = WINDOW_STATE_SHOWING; 318 319 // the tracker view 320 int mTrackingPosition; // the position of the top of the tracking view. 321 322 // Tracking finger for opening/closing. 323 boolean mTracking; 324 VelocityTracker mVelocityTracker; 325 326 int[] mAbsPos = new int[2]; 327 ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>(); 328 329 // for disabling the status bar 330 int mDisabled1 = 0; 331 int mDisabled2 = 0; 332 333 // tracking calls to View.setSystemUiVisibility() 334 int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 335 336 // last value sent to window manager 337 private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE; 338 339 DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 340 341 // XXX: gesture research 342 private final GestureRecorder mGestureRec = DEBUG_GESTURES 343 ? new GestureRecorder("/sdcard/statusbar_gestures.dat") 344 : null; 345 346 private ScreenPinningRequest mScreenPinningRequest; 347 348 private int mNavigationIconHints = 0; 349 private HandlerThread mHandlerThread; 350 351 // ensure quick settings is disabled until the current user makes it through the setup wizard 352 private boolean mUserSetup = false; 353 private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) { 354 @Override 355 public void onChange(boolean selfChange) { 356 final boolean userSetup = 0 != Settings.Secure.getIntForUser( 357 mContext.getContentResolver(), 358 Settings.Secure.USER_SETUP_COMPLETE, 359 0 /*default */, 360 mCurrentUserId); 361 if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " + 362 "selfChange=%s userSetup=%s mUserSetup=%s", 363 selfChange, userSetup, mUserSetup)); 364 365 if (userSetup != mUserSetup) { 366 mUserSetup = userSetup; 367 if (!mUserSetup && mStatusBarView != null) 368 animateCollapseQuickSettings(); 369 if (mKeyguardBottomArea != null) { 370 mKeyguardBottomArea.setUserSetupComplete(mUserSetup); 371 } 372 } 373 if (mIconPolicy != null) { 374 mIconPolicy.setCurrentUserSetup(mUserSetup); 375 } 376 } 377 }; 378 379 final private ContentObserver mHeadsUpObserver = new ContentObserver(mHandler) { 380 @Override 381 public void onChange(boolean selfChange) { 382 boolean wasUsing = mUseHeadsUp; 383 mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts 384 && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt( 385 mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, 386 Settings.Global.HEADS_UP_OFF); 387 mHeadsUpTicker = mUseHeadsUp && 0 != Settings.Global.getInt( 388 mContext.getContentResolver(), SETTING_HEADS_UP_TICKER, 0); 389 Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled")); 390 if (wasUsing != mUseHeadsUp) { 391 if (!mUseHeadsUp) { 392 Log.d(TAG, "dismissing any existing heads up notification on disable event"); 393 mHeadsUpManager.releaseAllImmediately(); 394 } 395 } 396 } 397 }; 398 399 private int mInteractingWindows; 400 private boolean mAutohideSuspended; 401 private int mStatusBarMode; 402 private int mNavigationBarMode; 403 404 private ViewMediatorCallback mKeyguardViewMediatorCallback; 405 private ScrimController mScrimController; 406 private DozeScrimController mDozeScrimController; 407 408 private final Runnable mAutohide = new Runnable() { 409 @Override 410 public void run() { 411 int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; 412 if (mSystemUiVisibility != requested) { 413 notifyUiVisibilityChanged(requested); 414 } 415 }}; 416 417 private boolean mWaitingForKeyguardExit; 418 private boolean mDozing; 419 private boolean mDozingRequested; 420 private boolean mScrimSrcModeEnabled; 421 422 private Interpolator mLinearInterpolator = new LinearInterpolator(); 423 private Interpolator mBackdropInterpolator = new AccelerateDecelerateInterpolator(); 424 public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); 425 public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f); 426 427 private BackDropView mBackdrop; 428 private ImageView mBackdropFront, mBackdropBack; 429 private PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); 430 private PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); 431 432 private MediaSessionManager mMediaSessionManager; 433 private MediaController mMediaController; 434 private String mMediaNotificationKey; 435 private MediaMetadata mMediaMetadata; 436 private MediaController.Callback mMediaListener 437 = new MediaController.Callback() { 438 @Override 439 public void onPlaybackStateChanged(PlaybackState state) { 440 super.onPlaybackStateChanged(state); 441 if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); 442 if (state != null) { 443 if (!isPlaybackActive(state.getState())) { 444 clearCurrentMediaNotification(); 445 updateMediaMetaData(true); 446 } 447 } 448 } 449 450 @Override 451 public void onMetadataChanged(MediaMetadata metadata) { 452 super.onMetadataChanged(metadata); 453 if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata); 454 mMediaMetadata = metadata; 455 updateMediaMetaData(true); 456 } 457 }; 458 459 private final OnChildLocationsChangedListener mOnChildLocationsChangedListener = 460 new OnChildLocationsChangedListener() { 461 @Override 462 public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) { 463 userActivity(); 464 } 465 }; 466 467 private int mDisabledUnmodified1; 468 private int mDisabledUnmodified2; 469 470 /** Keys of notifications currently visible to the user. */ 471 private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications = 472 new ArraySet<>(); 473 private long mLastVisibilityReportUptimeMs; 474 475 private final ShadeUpdates mShadeUpdates = new ShadeUpdates(); 476 477 private int mDrawCount; 478 private Runnable mLaunchTransitionEndRunnable; 479 private boolean mLaunchTransitionFadingAway; 480 private ExpandableNotificationRow mDraggedDownRow; 481 482 // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. 483 private int mLastLoggedStateFingerprint; 484 485 private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_CARD 486 | StackViewState.LOCATION_MAIN_AREA; 487 488 private final OnChildLocationsChangedListener mNotificationLocationsChangedListener = 489 new OnChildLocationsChangedListener() { 490 @Override 491 public void onChildLocationsChanged( 492 NotificationStackScrollLayout stackScrollLayout) { 493 if (mHandler.hasCallbacks(mVisibilityReporter)) { 494 // Visibilities will be reported when the existing 495 // callback is executed. 496 return; 497 } 498 // Calculate when we're allowed to run the visibility 499 // reporter. Note that this timestamp might already have 500 // passed. That's OK, the callback will just be executed 501 // ASAP. 502 long nextReportUptimeMs = 503 mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS; 504 mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs); 505 } 506 }; 507 508 // Tracks notifications currently visible in mNotificationStackScroller and 509 // emits visibility events via NoMan on changes. 510 private final Runnable mVisibilityReporter = new Runnable() { 511 private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications = 512 new ArraySet<>(); 513 private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications = 514 new ArraySet<>(); 515 private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications = 516 new ArraySet<>(); 517 518 @Override 519 public void run() { 520 mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis(); 521 final String mediaKey = getCurrentMediaNotificationKey(); 522 523 // 1. Loop over mNotificationData entries: 524 // A. Keep list of visible notifications. 525 // B. Keep list of previously hidden, now visible notifications. 526 // 2. Compute no-longer visible notifications by removing currently 527 // visible notifications from the set of previously visible 528 // notifications. 529 // 3. Report newly visible and no-longer visible notifications. 530 // 4. Keep currently visible notifications for next report. 531 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 532 int N = activeNotifications.size(); 533 for (int i = 0; i < N; i++) { 534 Entry entry = activeNotifications.get(i); 535 String key = entry.notification.getKey(); 536 boolean isVisible = 537 (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0; 538 NotificationVisibility visObj = NotificationVisibility.obtain(key, i, isVisible); 539 boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj); 540 if (isVisible) { 541 // Build new set of visible notifications. 542 mTmpCurrentlyVisibleNotifications.add(visObj); 543 if (!previouslyVisible) { 544 mTmpNewlyVisibleNotifications.add(visObj); 545 } 546 } else { 547 // release object 548 visObj.recycle(); 549 } 550 } 551 mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications); 552 mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications); 553 554 logNotificationVisibilityChanges( 555 mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications); 556 557 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications); 558 mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications); 559 560 recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications); 561 mTmpCurrentlyVisibleNotifications.clear(); 562 mTmpNewlyVisibleNotifications.clear(); 563 mTmpNoLongerVisibleNotifications.clear(); 564 } 565 }; 566 recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array)567 private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) { 568 final int N = array.size(); 569 for (int i = 0 ; i < N; i++) { 570 array.valueAt(i).recycle(); 571 } 572 array.clear(); 573 } 574 575 private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() { 576 @Override 577 public void onClick(View v) { 578 goToLockedShade(null); 579 } 580 }; 581 private HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>> mTmpChildOrderMap 582 = new HashMap<>(); 583 private HashSet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new HashSet<>(); 584 private RankingMap mLatestRankingMap; 585 private boolean mNoAnimationOnNextBarModeChange; 586 587 @Override start()588 public void start() { 589 mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) 590 .getDefaultDisplay(); 591 updateDisplaySize(); 592 mScrimSrcModeEnabled = mContext.getResources().getBoolean( 593 R.bool.config_status_bar_scrim_behind_use_src); 594 595 super.start(); // calls createAndAddWindows() 596 597 mMediaSessionManager 598 = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); 599 // TODO: use MediaSessionManager.SessionListener to hook us up to future updates 600 // in session state 601 602 addNavigationBar(); 603 604 // Lastly, call to the icon policy to install/update all the icons. 605 mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController, 606 mUserInfoController, mBluetoothController); 607 mIconPolicy.setCurrentUserSetup(mUserSetup); 608 mSettingsObserver.onChange(false); // set up 609 610 mHeadsUpObserver.onChange(true); // set up 611 if (ENABLE_HEADS_UP) { 612 mContext.getContentResolver().registerContentObserver( 613 Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true, 614 mHeadsUpObserver); 615 mContext.getContentResolver().registerContentObserver( 616 Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true, 617 mHeadsUpObserver); 618 } 619 mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); 620 mUnlockMethodCache.addListener(this); 621 startKeyguard(); 622 623 mDozeServiceHost = new DozeServiceHost(); 624 putComponent(DozeHost.class, mDozeServiceHost); 625 putComponent(PhoneStatusBar.class, this); 626 627 setControllerUsers(); 628 629 notifyUserAboutHiddenNotifications(); 630 631 mScreenPinningRequest = new ScreenPinningRequest(mContext); 632 } 633 634 // ================================================================================ 635 // Constructing the view 636 // ================================================================================ makeStatusBarView()637 protected PhoneStatusBarView makeStatusBarView() { 638 final Context context = mContext; 639 640 Resources res = context.getResources(); 641 642 updateDisplaySize(); // populates mDisplayMetrics 643 updateResources(); 644 645 mStatusBarWindow = (StatusBarWindowView) View.inflate(context, 646 R.layout.super_status_bar, null); 647 mStatusBarWindow.setService(this); 648 mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() { 649 @Override 650 public boolean onTouch(View v, MotionEvent event) { 651 checkUserAutohide(v, event); 652 if (event.getAction() == MotionEvent.ACTION_DOWN) { 653 if (mExpandedVisible) { 654 animateCollapsePanels(); 655 } 656 } 657 return mStatusBarWindow.onTouchEvent(event); 658 } 659 }); 660 661 mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); 662 mStatusBarView.setBar(this); 663 664 PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); 665 mStatusBarView.setPanelHolder(holder); 666 667 mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById( 668 R.id.notification_panel); 669 mNotificationPanel.setStatusBar(this); 670 671 if (!ActivityManager.isHighEndGfx()) { 672 mStatusBarWindow.setBackground(null); 673 mNotificationPanel.setBackground(new FastColorDrawable(context.getColor( 674 R.color.notification_panel_solid_background))); 675 } 676 677 mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow); 678 mHeadsUpManager.setBar(this); 679 mHeadsUpManager.addListener(this); 680 mHeadsUpManager.addListener(mNotificationPanel); 681 mNotificationPanel.setHeadsUpManager(mHeadsUpManager); 682 mNotificationData.setHeadsUpManager(mHeadsUpManager); 683 684 if (MULTIUSER_DEBUG) { 685 mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( 686 R.id.header_debug_info); 687 mNotificationPanelDebugText.setVisibility(View.VISIBLE); 688 } 689 690 try { 691 boolean showNav = mWindowManagerService.hasNavigationBar(); 692 if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); 693 if (showNav) { 694 mNavigationBarView = 695 (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null); 696 697 mNavigationBarView.setDisabledFlags(mDisabled1); 698 mNavigationBarView.setBar(this); 699 mNavigationBarView.setOnVerticalChangedListener( 700 new NavigationBarView.OnVerticalChangedListener() { 701 @Override 702 public void onVerticalChanged(boolean isVertical) { 703 if (mAssistManager != null) { 704 mAssistManager.onConfigurationChanged(); 705 } 706 mNotificationPanel.setQsScrimEnabled(!isVertical); 707 } 708 }); 709 mNavigationBarView.setOnTouchListener(new View.OnTouchListener() { 710 @Override 711 public boolean onTouch(View v, MotionEvent event) { 712 checkUserAutohide(v, event); 713 return false; 714 }}); 715 } 716 } catch (RemoteException ex) { 717 // no window manager? good luck with that 718 } 719 720 mAssistManager = new AssistManager(this, context); 721 722 // figure out which pixel-format to use for the status bar. 723 mPixelFormat = PixelFormat.OPAQUE; 724 725 mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( 726 R.id.notification_stack_scroller); 727 mStackScroller.setLongPressListener(getNotificationLongClicker()); 728 mStackScroller.setPhoneStatusBar(this); 729 mStackScroller.setGroupManager(mGroupManager); 730 mStackScroller.setHeadsUpManager(mHeadsUpManager); 731 mGroupManager.setOnGroupChangeListener(mStackScroller); 732 733 mKeyguardIconOverflowContainer = 734 (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate( 735 R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false); 736 mKeyguardIconOverflowContainer.setOnActivatedListener(this); 737 mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener); 738 mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer); 739 740 SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate( 741 R.layout.status_bar_notification_speed_bump, mStackScroller, false); 742 mStackScroller.setSpeedBumpView(speedBump); 743 mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( 744 R.layout.status_bar_no_notifications, mStackScroller, false); 745 mStackScroller.setEmptyShadeView(mEmptyShadeView); 746 mDismissView = (DismissView) LayoutInflater.from(mContext).inflate( 747 R.layout.status_bar_notification_dismiss_all, mStackScroller, false); 748 mDismissView.setOnButtonClickListener(new View.OnClickListener() { 749 @Override 750 public void onClick(View v) { 751 MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES); 752 clearAllNotifications(); 753 } 754 }); 755 mStackScroller.setDismissView(mDismissView); 756 mExpandedContents = mStackScroller; 757 758 mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop); 759 mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front); 760 mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back); 761 762 ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind); 763 ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front); 764 View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim); 765 mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim, 766 mScrimSrcModeEnabled); 767 mHeadsUpManager.addListener(mScrimController); 768 mStackScroller.setScrimController(mScrimController); 769 mScrimController.setBackDropView(mBackdrop); 770 mStatusBarView.setScrimController(mScrimController); 771 mDozeScrimController = new DozeScrimController(mScrimController, context); 772 773 mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header); 774 mHeader.setActivityStarter(this); 775 mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); 776 mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view); 777 mKeyguardBottomArea = 778 (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area); 779 mKeyguardBottomArea.setActivityStarter(this); 780 mKeyguardBottomArea.setAssistManager(mAssistManager); 781 mKeyguardIndicationController = new KeyguardIndicationController(mContext, 782 (KeyguardIndicationTextView) mStatusBarWindow.findViewById( 783 R.id.keyguard_indication_text)); 784 mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController); 785 786 // set the inital view visibility 787 setAreThereNotifications(); 788 789 mIconController = new StatusBarIconController( 790 mContext, mStatusBarView, mKeyguardStatusBar, this); 791 792 // Background thread for any controllers that need it. 793 mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); 794 mHandlerThread.start(); 795 796 // Other icons 797 mLocationController = new LocationControllerImpl(mContext, 798 mHandlerThread.getLooper()); // will post a notification 799 mBatteryController = new BatteryController(mContext); 800 mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { 801 @Override 802 public void onPowerSaveChanged() { 803 mHandler.post(mCheckBarModes); 804 if (mDozeServiceHost != null) { 805 mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave()); 806 } 807 } 808 @Override 809 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 810 // noop 811 } 812 }); 813 mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); 814 mHotspotController = new HotspotControllerImpl(mContext); 815 mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper()); 816 mSecurityController = new SecurityControllerImpl(mContext); 817 if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) { 818 mRotationLockController = new RotationLockControllerImpl(mContext); 819 } 820 mUserInfoController = new UserInfoController(mContext); 821 mVolumeComponent = getComponent(VolumeComponent.class); 822 if (mVolumeComponent != null) { 823 mZenModeController = mVolumeComponent.getZenController(); 824 } 825 mCastController = new CastControllerImpl(mContext); 826 final SignalClusterView signalCluster = 827 (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); 828 final SignalClusterView signalClusterKeyguard = 829 (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster); 830 final SignalClusterView signalClusterQs = 831 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster); 832 mNetworkController.addSignalCallback(signalCluster); 833 mNetworkController.addSignalCallback(signalClusterKeyguard); 834 mNetworkController.addSignalCallback(signalClusterQs); 835 signalCluster.setSecurityController(mSecurityController); 836 signalCluster.setNetworkController(mNetworkController); 837 signalClusterKeyguard.setSecurityController(mSecurityController); 838 signalClusterKeyguard.setNetworkController(mNetworkController); 839 signalClusterQs.setSecurityController(mSecurityController); 840 signalClusterQs.setNetworkController(mNetworkController); 841 final boolean isAPhone = mNetworkController.hasVoiceCallingFeature(); 842 if (isAPhone) { 843 mNetworkController.addEmergencyListener(mHeader); 844 } 845 846 mFlashlightController = new FlashlightController(mContext); 847 mKeyguardBottomArea.setFlashlightController(mFlashlightController); 848 mKeyguardBottomArea.setPhoneStatusBar(this); 849 mKeyguardBottomArea.setUserSetupComplete(mUserSetup); 850 mAccessibilityController = new AccessibilityController(mContext); 851 mKeyguardBottomArea.setAccessibilityController(mAccessibilityController); 852 mNextAlarmController = new NextAlarmController(mContext); 853 mKeyguardMonitor = new KeyguardMonitor(mContext); 854 if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) { 855 mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor, 856 mHandler); 857 } 858 mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, 859 (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), 860 mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController); 861 862 863 // Set up the quick settings tile panel 864 mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel); 865 if (mQSPanel != null) { 866 final QSTileHost qsh = new QSTileHost(mContext, this, 867 mBluetoothController, mLocationController, mRotationLockController, 868 mNetworkController, mZenModeController, mHotspotController, 869 mCastController, mFlashlightController, 870 mUserSwitcherController, mKeyguardMonitor, 871 mSecurityController); 872 mQSPanel.setHost(qsh); 873 mQSPanel.setTiles(qsh.getTiles()); 874 mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); 875 mQSPanel.setBrightnessMirror(mBrightnessMirrorController); 876 mHeader.setQSPanel(mQSPanel); 877 qsh.setCallback(new QSTileHost.Callback() { 878 @Override 879 public void onTilesChanged() { 880 mQSPanel.setTiles(qsh.getTiles()); 881 } 882 }); 883 } 884 885 // User info. Trigger first load. 886 mHeader.setUserInfoController(mUserInfoController); 887 mKeyguardStatusBar.setUserInfoController(mUserInfoController); 888 mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController); 889 mUserInfoController.reloadUserInfo(); 890 891 mHeader.setBatteryController(mBatteryController); 892 ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController( 893 mBatteryController); 894 mKeyguardStatusBar.setBatteryController(mBatteryController); 895 mHeader.setNextAlarmController(mNextAlarmController); 896 897 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 898 mBroadcastReceiver.onReceive(mContext, 899 new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF)); 900 901 902 // receive broadcasts 903 IntentFilter filter = new IntentFilter(); 904 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 905 filter.addAction(Intent.ACTION_SCREEN_OFF); 906 filter.addAction(Intent.ACTION_SCREEN_ON); 907 context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 908 909 IntentFilter demoFilter = new IntentFilter(); 910 if (DEBUG_MEDIA_FAKE_ARTWORK) { 911 demoFilter.addAction(ACTION_FAKE_ARTWORK); 912 } 913 demoFilter.addAction(ACTION_DEMO); 914 context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, 915 android.Manifest.permission.DUMP, null); 916 917 // listen for USER_SETUP_COMPLETE setting (per-user) 918 resetUserSetupObserver(); 919 920 // disable profiling bars, since they overlap and clutter the output on app windows 921 ThreadedRenderer.overrideProperty("disableProfileBars", "true"); 922 923 // Private API call to make the shadows look better for Recents 924 ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); 925 926 return mStatusBarView; 927 } 928 clearAllNotifications()929 private void clearAllNotifications() { 930 931 // animate-swipe all dismissable notifications, then animate the shade closed 932 int numChildren = mStackScroller.getChildCount(); 933 934 final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren); 935 for (int i = 0; i < numChildren; i++) { 936 final View child = mStackScroller.getChildAt(i); 937 if (child instanceof ExpandableNotificationRow) { 938 if (mStackScroller.canChildBeDismissed(child)) { 939 if (child.getVisibility() == View.VISIBLE) { 940 viewsToHide.add(child); 941 } 942 } 943 ExpandableNotificationRow row = (ExpandableNotificationRow) child; 944 List<ExpandableNotificationRow> children = row.getNotificationChildren(); 945 if (row.areChildrenExpanded() && children != null) { 946 for (ExpandableNotificationRow childRow : children) { 947 if (childRow.getVisibility() == View.VISIBLE) { 948 viewsToHide.add(childRow); 949 } 950 } 951 } 952 } 953 } 954 if (viewsToHide.isEmpty()) { 955 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 956 return; 957 } 958 959 addPostCollapseAction(new Runnable() { 960 @Override 961 public void run() { 962 mStackScroller.setDismissAllInProgress(false); 963 try { 964 mBarService.onClearAllNotifications(mCurrentUserId); 965 } catch (Exception ex) { } 966 } 967 }); 968 969 performDismissAllAnimations(viewsToHide); 970 971 } 972 performDismissAllAnimations(ArrayList<View> hideAnimatedList)973 private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) { 974 Runnable animationFinishAction = new Runnable() { 975 @Override 976 public void run() { 977 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 978 } 979 }; 980 981 // let's disable our normal animations 982 mStackScroller.setDismissAllInProgress(true); 983 984 // Decrease the delay for every row we animate to give the sense of 985 // accelerating the swipes 986 int rowDelayDecrement = 10; 987 int currentDelay = 140; 988 int totalDelay = 180; 989 int numItems = hideAnimatedList.size(); 990 for (int i = numItems - 1; i >= 0; i--) { 991 View view = hideAnimatedList.get(i); 992 Runnable endRunnable = null; 993 if (i == 0) { 994 endRunnable = animationFinishAction; 995 } 996 mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260); 997 currentDelay = Math.max(50, currentDelay - rowDelayDecrement); 998 totalDelay += currentDelay; 999 } 1000 } 1001 1002 @Override setZenMode(int mode)1003 protected void setZenMode(int mode) { 1004 super.setZenMode(mode); 1005 if (mIconPolicy != null) { 1006 mIconPolicy.setZenMode(mode); 1007 } 1008 } 1009 startKeyguard()1010 private void startKeyguard() { 1011 KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); 1012 mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, 1013 mStatusBarWindow, mStatusBarWindowManager, mScrimController); 1014 mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); 1015 } 1016 1017 @Override getStatusBarView()1018 protected View getStatusBarView() { 1019 return mStatusBarView; 1020 } 1021 getStatusBarWindow()1022 public StatusBarWindowView getStatusBarWindow() { 1023 return mStatusBarWindow; 1024 } 1025 getStatusBarHeight()1026 public int getStatusBarHeight() { 1027 if (mNaturalBarHeight < 0) { 1028 final Resources res = mContext.getResources(); 1029 mNaturalBarHeight = 1030 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 1031 } 1032 return mNaturalBarHeight; 1033 } 1034 1035 private View.OnClickListener mRecentsClickListener = new View.OnClickListener() { 1036 public void onClick(View v) { 1037 awakenDreams(); 1038 toggleRecentApps(); 1039 } 1040 }; 1041 1042 private long mLastLockToAppLongPress; 1043 private View.OnLongClickListener mLongPressBackRecentsListener = 1044 new View.OnLongClickListener() { 1045 @Override 1046 public boolean onLongClick(View v) { 1047 handleLongPressBackRecents(v); 1048 return true; 1049 } 1050 }; 1051 1052 private final View.OnLongClickListener mLongPressHomeListener 1053 = new View.OnLongClickListener() { 1054 @Override 1055 public boolean onLongClick(View v) { 1056 if (shouldDisableNavbarGestures()) { 1057 return false; 1058 } 1059 MetricsLogger.action(mContext, MetricsLogger.ACTION_ASSIST_LONG_PRESS); 1060 mAssistManager.startAssist(new Bundle() /* args */); 1061 awakenDreams(); 1062 if (mNavigationBarView != null) { 1063 mNavigationBarView.abortCurrentGesture(); 1064 } 1065 return true; 1066 } 1067 }; 1068 1069 private final View.OnTouchListener mHomeActionListener = new View.OnTouchListener() { 1070 public boolean onTouch(View v, MotionEvent event) { 1071 switch (event.getAction()) { 1072 case MotionEvent.ACTION_UP: 1073 case MotionEvent.ACTION_CANCEL: 1074 awakenDreams(); 1075 break; 1076 } 1077 return false; 1078 } 1079 }; 1080 awakenDreams()1081 private void awakenDreams() { 1082 if (mDreamManager != null) { 1083 try { 1084 mDreamManager.awaken(); 1085 } catch (RemoteException e) { 1086 // fine, stay asleep then 1087 } 1088 } 1089 } 1090 prepareNavigationBarView()1091 private void prepareNavigationBarView() { 1092 mNavigationBarView.reorient(); 1093 1094 mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener); 1095 mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener); 1096 mNavigationBarView.getRecentsButton().setLongClickable(true); 1097 mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener); 1098 mNavigationBarView.getBackButton().setLongClickable(true); 1099 mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener); 1100 mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener); 1101 mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener); 1102 mAssistManager.onConfigurationChanged(); 1103 } 1104 1105 // For small-screen devices (read: phones) that lack hardware navigation buttons addNavigationBar()1106 private void addNavigationBar() { 1107 if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView); 1108 if (mNavigationBarView == null) return; 1109 1110 prepareNavigationBarView(); 1111 1112 mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams()); 1113 } 1114 repositionNavigationBar()1115 private void repositionNavigationBar() { 1116 if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return; 1117 1118 prepareNavigationBarView(); 1119 1120 mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams()); 1121 } 1122 notifyNavigationBarScreenOn(boolean screenOn)1123 private void notifyNavigationBarScreenOn(boolean screenOn) { 1124 if (mNavigationBarView == null) return; 1125 mNavigationBarView.notifyScreenOn(screenOn); 1126 } 1127 getNavigationBarLayoutParams()1128 private WindowManager.LayoutParams getNavigationBarLayoutParams() { 1129 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 1130 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1131 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, 1132 0 1133 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 1134 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 1135 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 1136 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 1137 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 1138 PixelFormat.TRANSLUCENT); 1139 // this will allow the navbar to run in an overlay on devices that support this 1140 if (ActivityManager.isHighEndGfx()) { 1141 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 1142 } 1143 1144 lp.setTitle("NavigationBar"); 1145 lp.windowAnimations = 0; 1146 return lp; 1147 } 1148 addIcon(String slot, int index, int viewIndex, StatusBarIcon icon)1149 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { 1150 mIconController.addSystemIcon(slot, index, viewIndex, icon); 1151 } 1152 updateIcon(String slot, int index, int viewIndex, StatusBarIcon old, StatusBarIcon icon)1153 public void updateIcon(String slot, int index, int viewIndex, 1154 StatusBarIcon old, StatusBarIcon icon) { 1155 mIconController.updateSystemIcon(slot, index, viewIndex, old, icon); 1156 } 1157 removeIcon(String slot, int index, int viewIndex)1158 public void removeIcon(String slot, int index, int viewIndex) { 1159 mIconController.removeSystemIcon(slot, index, viewIndex); 1160 } 1161 getCurrentUserHandle()1162 public UserHandle getCurrentUserHandle() { 1163 return new UserHandle(mCurrentUserId); 1164 } 1165 1166 @Override addNotification(StatusBarNotification notification, RankingMap ranking, Entry oldEntry)1167 public void addNotification(StatusBarNotification notification, RankingMap ranking, 1168 Entry oldEntry) { 1169 if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); 1170 1171 Entry shadeEntry = createNotificationViews(notification); 1172 if (shadeEntry == null) { 1173 return; 1174 } 1175 boolean isHeadsUped = mUseHeadsUp && shouldInterrupt(shadeEntry); 1176 if (isHeadsUped) { 1177 mHeadsUpManager.showNotification(shadeEntry); 1178 // Mark as seen immediately 1179 setNotificationShown(notification); 1180 } 1181 1182 if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) { 1183 // Stop screensaver if the notification has a full-screen intent. 1184 // (like an incoming phone call) 1185 awakenDreams(); 1186 1187 // not immersive & a full-screen alert should be shown 1188 if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); 1189 try { 1190 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, 1191 notification.getKey()); 1192 notification.getNotification().fullScreenIntent.send(); 1193 shadeEntry.notifyFullScreenIntentLaunched(); 1194 MetricsLogger.count(mContext, "note_fullscreen", 1); 1195 } catch (PendingIntent.CanceledException e) { 1196 } 1197 } 1198 addNotificationViews(shadeEntry, ranking); 1199 // Recalculate the position of the sliding windows and the titles. 1200 setAreThereNotifications(); 1201 } 1202 1203 @Override updateNotificationRanking(RankingMap ranking)1204 protected void updateNotificationRanking(RankingMap ranking) { 1205 mNotificationData.updateRanking(ranking); 1206 updateNotifications(); 1207 } 1208 1209 @Override removeNotification(String key, RankingMap ranking)1210 public void removeNotification(String key, RankingMap ranking) { 1211 boolean deferRemoval = false; 1212 if (mHeadsUpManager.isHeadsUp(key)) { 1213 deferRemoval = !mHeadsUpManager.removeNotification(key); 1214 } 1215 if (key.equals(mMediaNotificationKey)) { 1216 clearCurrentMediaNotification(); 1217 updateMediaMetaData(true); 1218 } 1219 if (deferRemoval) { 1220 mLatestRankingMap = ranking; 1221 mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); 1222 return; 1223 } 1224 StatusBarNotification old = removeNotificationViews(key, ranking); 1225 if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); 1226 1227 if (old != null) { 1228 if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() 1229 && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) { 1230 if (mState == StatusBarState.SHADE) { 1231 animateCollapsePanels(); 1232 } else if (mState == StatusBarState.SHADE_LOCKED) { 1233 goToKeyguard(); 1234 } 1235 } 1236 } 1237 setAreThereNotifications(); 1238 } 1239 1240 @Override refreshLayout(int layoutDirection)1241 protected void refreshLayout(int layoutDirection) { 1242 if (mNavigationBarView != null) { 1243 mNavigationBarView.setLayoutDirection(layoutDirection); 1244 } 1245 } 1246 updateNotificationShade()1247 private void updateNotificationShade() { 1248 if (mStackScroller == null) return; 1249 1250 // Do not modify the notifications during collapse. 1251 if (isCollapsing()) { 1252 addPostCollapseAction(new Runnable() { 1253 @Override 1254 public void run() { 1255 updateNotificationShade(); 1256 } 1257 }); 1258 return; 1259 } 1260 1261 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 1262 ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size()); 1263 final int N = activeNotifications.size(); 1264 for (int i=0; i<N; i++) { 1265 Entry ent = activeNotifications.get(i); 1266 int vis = ent.notification.getNotification().visibility; 1267 1268 // Display public version of the notification if we need to redact. 1269 final boolean hideSensitive = 1270 !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId()); 1271 boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE; 1272 boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey()); 1273 boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage; 1274 boolean showingPublic = sensitive && isLockscreenPublicMode(); 1275 ent.row.setSensitive(sensitive); 1276 if (ent.autoRedacted && ent.legacy) { 1277 // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form 1278 // for legacy auto redacted notifications. 1279 if (showingPublic) { 1280 ent.row.setShowingLegacyBackground(false); 1281 } else { 1282 ent.row.setShowingLegacyBackground(true); 1283 } 1284 } 1285 if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) { 1286 ExpandableNotificationRow summary = mGroupManager.getGroupSummary( 1287 ent.row.getStatusBarNotification()); 1288 List<ExpandableNotificationRow> orderedChildren = 1289 mTmpChildOrderMap.get(summary); 1290 if (orderedChildren == null) { 1291 orderedChildren = new ArrayList<>(); 1292 mTmpChildOrderMap.put(summary, orderedChildren); 1293 } 1294 orderedChildren.add(ent.row); 1295 } else { 1296 toShow.add(ent.row); 1297 } 1298 1299 } 1300 1301 ArrayList<View> toRemove = new ArrayList<>(); 1302 for (int i=0; i< mStackScroller.getChildCount(); i++) { 1303 View child = mStackScroller.getChildAt(i); 1304 if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) { 1305 toRemove.add(child); 1306 } 1307 } 1308 1309 for (View remove : toRemove) { 1310 mStackScroller.removeView(remove); 1311 } 1312 for (int i=0; i<toShow.size(); i++) { 1313 View v = toShow.get(i); 1314 if (v.getParent() == null) { 1315 mStackScroller.addView(v); 1316 } 1317 } 1318 1319 // So after all this work notifications still aren't sorted correctly. 1320 // Let's do that now by advancing through toShow and mStackScroller in 1321 // lock-step, making sure mStackScroller matches what we see in toShow. 1322 int j = 0; 1323 for (int i = 0; i < mStackScroller.getChildCount(); i++) { 1324 View child = mStackScroller.getChildAt(i); 1325 if (!(child instanceof ExpandableNotificationRow)) { 1326 // We don't care about non-notification views. 1327 continue; 1328 } 1329 1330 ExpandableNotificationRow targetChild = toShow.get(j); 1331 if (child != targetChild) { 1332 // Oops, wrong notification at this position. Put the right one 1333 // here and advance both lists. 1334 mStackScroller.changeViewPosition(targetChild, i); 1335 } 1336 j++; 1337 1338 } 1339 1340 // lets handle the child notifications now 1341 updateNotificationShadeForChildren(); 1342 1343 // clear the map again for the next usage 1344 mTmpChildOrderMap.clear(); 1345 1346 updateRowStates(); 1347 updateSpeedbump(); 1348 updateClearAll(); 1349 updateEmptyShadeView(); 1350 1351 updateQsExpansionEnabled(); 1352 mShadeUpdates.check(); 1353 } 1354 1355 /** 1356 * Disable QS if device not provisioned. 1357 * If the user switcher is simple then disable QS during setup because 1358 * the user intends to use the lock screen user switcher, QS in not needed. 1359 */ updateQsExpansionEnabled()1360 private void updateQsExpansionEnabled() { 1361 mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() 1362 && (mUserSetup || mUserSwitcherController == null 1363 || !mUserSwitcherController.isSimpleUserSwitcher()) 1364 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) 1365 && !ONLY_CORE_APPS); 1366 } 1367 updateNotificationShadeForChildren()1368 private void updateNotificationShadeForChildren() { 1369 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>(); 1370 boolean orderChanged = false; 1371 for (int i = 0; i < mStackScroller.getChildCount(); i++) { 1372 View view = mStackScroller.getChildAt(i); 1373 if (!(view instanceof ExpandableNotificationRow)) { 1374 // We don't care about non-notification views. 1375 continue; 1376 } 1377 1378 ExpandableNotificationRow parent = (ExpandableNotificationRow) view; 1379 List<ExpandableNotificationRow> children = parent.getNotificationChildren(); 1380 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent); 1381 1382 // lets first remove all undesired children 1383 if (children != null) { 1384 toRemove.clear(); 1385 for (ExpandableNotificationRow childRow : children) { 1386 if (orderedChildren == null || !orderedChildren.contains(childRow)) { 1387 toRemove.add(childRow); 1388 } 1389 } 1390 for (ExpandableNotificationRow remove : toRemove) { 1391 parent.removeChildNotification(remove); 1392 mStackScroller.notifyGroupChildRemoved(remove); 1393 } 1394 } 1395 1396 // We now add all the children which are not in there already 1397 for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size(); 1398 childIndex++) { 1399 ExpandableNotificationRow childView = orderedChildren.get(childIndex); 1400 if (children == null || !children.contains(childView)) { 1401 parent.addChildNotification(childView, childIndex); 1402 mStackScroller.notifyGroupChildAdded(childView); 1403 } 1404 } 1405 1406 // Finally after removing and adding has been beformed we can apply the order. 1407 orderChanged |= parent.applyChildOrder(orderedChildren); 1408 } 1409 if (orderChanged) { 1410 mStackScroller.generateChildOrderChangedEvent(); 1411 } 1412 } 1413 packageHasVisibilityOverride(String key)1414 private boolean packageHasVisibilityOverride(String key) { 1415 return mNotificationData.getVisibilityOverride(key) 1416 != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE; 1417 } 1418 updateClearAll()1419 private void updateClearAll() { 1420 boolean showDismissView = 1421 mState != StatusBarState.KEYGUARD && 1422 mNotificationData.hasActiveClearableNotifications(); 1423 mStackScroller.updateDismissView(showDismissView); 1424 } 1425 updateEmptyShadeView()1426 private void updateEmptyShadeView() { 1427 boolean showEmptyShade = 1428 mState != StatusBarState.KEYGUARD && 1429 mNotificationData.getActiveNotifications().size() == 0; 1430 mNotificationPanel.setShadeEmpty(showEmptyShade); 1431 } 1432 updateSpeedbump()1433 private void updateSpeedbump() { 1434 int speedbumpIndex = -1; 1435 int currentIndex = 0; 1436 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 1437 final int N = activeNotifications.size(); 1438 for (int i = 0; i < N; i++) { 1439 Entry entry = activeNotifications.get(i); 1440 boolean isChild = !isTopLevelChild(entry); 1441 if (isChild) { 1442 continue; 1443 } 1444 if (entry.row.getVisibility() != View.GONE && 1445 mNotificationData.isAmbient(entry.key)) { 1446 speedbumpIndex = currentIndex; 1447 break; 1448 } 1449 currentIndex++; 1450 } 1451 mStackScroller.updateSpeedBumpIndex(speedbumpIndex); 1452 } 1453 isTopLevelChild(Entry entry)1454 public static boolean isTopLevelChild(Entry entry) { 1455 return entry.row.getParent() instanceof NotificationStackScrollLayout; 1456 } 1457 1458 @Override updateNotifications()1459 protected void updateNotifications() { 1460 mNotificationData.filterAndSort(); 1461 1462 updateNotificationShade(); 1463 mIconController.updateNotificationIcons(mNotificationData); 1464 } 1465 1466 @Override updateRowStates()1467 protected void updateRowStates() { 1468 super.updateRowStates(); 1469 mNotificationPanel.notifyVisibleChildrenChanged(); 1470 } 1471 1472 @Override setAreThereNotifications()1473 protected void setAreThereNotifications() { 1474 1475 if (SPEW) { 1476 final boolean clearable = hasActiveNotifications() && 1477 mNotificationData.hasActiveClearableNotifications(); 1478 Log.d(TAG, "setAreThereNotifications: N=" + 1479 mNotificationData.getActiveNotifications().size() + " any=" + 1480 hasActiveNotifications() + " clearable=" + clearable); 1481 } 1482 1483 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); 1484 final boolean showDot = hasActiveNotifications() && !areLightsOn(); 1485 if (showDot != (nlo.getAlpha() == 1.0f)) { 1486 if (showDot) { 1487 nlo.setAlpha(0f); 1488 nlo.setVisibility(View.VISIBLE); 1489 } 1490 nlo.animate() 1491 .alpha(showDot?1:0) 1492 .setDuration(showDot?750:250) 1493 .setInterpolator(new AccelerateInterpolator(2.0f)) 1494 .setListener(showDot ? null : new AnimatorListenerAdapter() { 1495 @Override 1496 public void onAnimationEnd(Animator _a) { 1497 nlo.setVisibility(View.GONE); 1498 } 1499 }) 1500 .start(); 1501 } 1502 1503 findAndUpdateMediaNotifications(); 1504 } 1505 findAndUpdateMediaNotifications()1506 public void findAndUpdateMediaNotifications() { 1507 boolean metaDataChanged = false; 1508 1509 synchronized (mNotificationData) { 1510 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 1511 final int N = activeNotifications.size(); 1512 1513 // Promote the media notification with a controller in 'playing' state, if any. 1514 Entry mediaNotification = null; 1515 MediaController controller = null; 1516 for (int i = 0; i < N; i++) { 1517 final Entry entry = activeNotifications.get(i); 1518 if (isMediaNotification(entry)) { 1519 final MediaSession.Token token = 1520 entry.notification.getNotification().extras 1521 .getParcelable(Notification.EXTRA_MEDIA_SESSION); 1522 if (token != null) { 1523 MediaController aController = new MediaController(mContext, token); 1524 if (PlaybackState.STATE_PLAYING == 1525 getMediaControllerPlaybackState(aController)) { 1526 if (DEBUG_MEDIA) { 1527 Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching " 1528 + entry.notification.getKey()); 1529 } 1530 mediaNotification = entry; 1531 controller = aController; 1532 break; 1533 } 1534 } 1535 } 1536 } 1537 if (mediaNotification == null) { 1538 // Still nothing? OK, let's just look for live media sessions and see if they match 1539 // one of our notifications. This will catch apps that aren't (yet!) using media 1540 // notifications. 1541 1542 if (mMediaSessionManager != null) { 1543 final List<MediaController> sessions 1544 = mMediaSessionManager.getActiveSessionsForUser( 1545 null, 1546 UserHandle.USER_ALL); 1547 1548 for (MediaController aController : sessions) { 1549 if (PlaybackState.STATE_PLAYING == 1550 getMediaControllerPlaybackState(aController)) { 1551 // now to see if we have one like this 1552 final String pkg = aController.getPackageName(); 1553 1554 for (int i = 0; i < N; i++) { 1555 final Entry entry = activeNotifications.get(i); 1556 if (entry.notification.getPackageName().equals(pkg)) { 1557 if (DEBUG_MEDIA) { 1558 Log.v(TAG, "DEBUG_MEDIA: found controller matching " 1559 + entry.notification.getKey()); 1560 } 1561 controller = aController; 1562 mediaNotification = entry; 1563 break; 1564 } 1565 } 1566 } 1567 } 1568 } 1569 } 1570 1571 if (controller != null && !sameSessions(mMediaController, controller)) { 1572 // We have a new media session 1573 clearCurrentMediaNotification(); 1574 mMediaController = controller; 1575 mMediaController.registerCallback(mMediaListener); 1576 mMediaMetadata = mMediaController.getMetadata(); 1577 if (DEBUG_MEDIA) { 1578 Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " 1579 + mMediaMetadata); 1580 } 1581 1582 if (mediaNotification != null) { 1583 mMediaNotificationKey = mediaNotification.notification.getKey(); 1584 if (DEBUG_MEDIA) { 1585 Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" 1586 + mMediaNotificationKey + " controller=" + mMediaController); 1587 } 1588 } 1589 metaDataChanged = true; 1590 } 1591 } 1592 1593 if (metaDataChanged) { 1594 updateNotifications(); 1595 } 1596 updateMediaMetaData(metaDataChanged); 1597 } 1598 getMediaControllerPlaybackState(MediaController controller)1599 private int getMediaControllerPlaybackState(MediaController controller) { 1600 if (controller != null) { 1601 final PlaybackState playbackState = controller.getPlaybackState(); 1602 if (playbackState != null) { 1603 return playbackState.getState(); 1604 } 1605 } 1606 return PlaybackState.STATE_NONE; 1607 } 1608 isPlaybackActive(int state)1609 private boolean isPlaybackActive(int state) { 1610 if (state != PlaybackState.STATE_STOPPED 1611 && state != PlaybackState.STATE_ERROR 1612 && state != PlaybackState.STATE_NONE) { 1613 return true; 1614 } 1615 return false; 1616 } 1617 clearCurrentMediaNotification()1618 private void clearCurrentMediaNotification() { 1619 mMediaNotificationKey = null; 1620 mMediaMetadata = null; 1621 if (mMediaController != null) { 1622 if (DEBUG_MEDIA) { 1623 Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " 1624 + mMediaController.getPackageName()); 1625 } 1626 mMediaController.unregisterCallback(mMediaListener); 1627 } 1628 mMediaController = null; 1629 } 1630 sameSessions(MediaController a, MediaController b)1631 private boolean sameSessions(MediaController a, MediaController b) { 1632 if (a == b) return true; 1633 if (a == null) return false; 1634 return a.controlsSameSession(b); 1635 } 1636 1637 /** 1638 * Hide the album artwork that is fading out and release its bitmap. 1639 */ 1640 private Runnable mHideBackdropFront = new Runnable() { 1641 @Override 1642 public void run() { 1643 if (DEBUG_MEDIA) { 1644 Log.v(TAG, "DEBUG_MEDIA: removing fade layer"); 1645 } 1646 mBackdropFront.setVisibility(View.INVISIBLE); 1647 mBackdropFront.animate().cancel(); 1648 mBackdropFront.setImageDrawable(null); 1649 } 1650 }; 1651 1652 /** 1653 * Refresh or remove lockscreen artwork from media metadata. 1654 */ updateMediaMetaData(boolean metaDataChanged)1655 public void updateMediaMetaData(boolean metaDataChanged) { 1656 if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) return; 1657 1658 if (mBackdrop == null) return; // called too early 1659 1660 if (mLaunchTransitionFadingAway) { 1661 mBackdrop.setVisibility(View.INVISIBLE); 1662 return; 1663 } 1664 1665 if (DEBUG_MEDIA) { 1666 Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " + mMediaNotificationKey 1667 + " metadata=" + mMediaMetadata 1668 + " metaDataChanged=" + metaDataChanged 1669 + " state=" + mState); 1670 } 1671 1672 Bitmap artworkBitmap = null; 1673 if (mMediaMetadata != null) { 1674 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); 1675 if (artworkBitmap == null) { 1676 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); 1677 // might still be null 1678 } 1679 } 1680 1681 final boolean hasArtwork = artworkBitmap != null; 1682 1683 if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) 1684 && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { 1685 // time to show some art! 1686 if (mBackdrop.getVisibility() != View.VISIBLE) { 1687 mBackdrop.setVisibility(View.VISIBLE); 1688 mBackdrop.animate().alpha(1f); 1689 metaDataChanged = true; 1690 if (DEBUG_MEDIA) { 1691 Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork"); 1692 } 1693 } 1694 if (metaDataChanged) { 1695 if (mBackdropBack.getDrawable() != null) { 1696 Drawable drawable = 1697 mBackdropBack.getDrawable().getConstantState().newDrawable().mutate(); 1698 mBackdropFront.setImageDrawable(drawable); 1699 if (mScrimSrcModeEnabled) { 1700 mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode); 1701 } 1702 mBackdropFront.setAlpha(1f); 1703 mBackdropFront.setVisibility(View.VISIBLE); 1704 } else { 1705 mBackdropFront.setVisibility(View.INVISIBLE); 1706 } 1707 1708 if (DEBUG_MEDIA_FAKE_ARTWORK) { 1709 final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF); 1710 Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c)); 1711 mBackdropBack.setBackgroundColor(0xFFFFFFFF); 1712 mBackdropBack.setImageDrawable(new ColorDrawable(c)); 1713 } else { 1714 mBackdropBack.setImageBitmap(artworkBitmap); 1715 } 1716 if (mScrimSrcModeEnabled) { 1717 mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode); 1718 } 1719 1720 if (mBackdropFront.getVisibility() == View.VISIBLE) { 1721 if (DEBUG_MEDIA) { 1722 Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from " 1723 + mBackdropFront.getDrawable() 1724 + " to " 1725 + mBackdropBack.getDrawable()); 1726 } 1727 mBackdropFront.animate() 1728 .setDuration(250) 1729 .alpha(0f).withEndAction(mHideBackdropFront); 1730 } 1731 } 1732 } else { 1733 // need to hide the album art, either because we are unlocked or because 1734 // the metadata isn't there to support it 1735 if (mBackdrop.getVisibility() != View.GONE) { 1736 if (DEBUG_MEDIA) { 1737 Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork"); 1738 } 1739 mBackdrop.animate() 1740 // Never let the alpha become zero - otherwise the RenderNode 1741 // won't draw anything and uninitialized memory will show through 1742 // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in libhwui. 1743 .alpha(0.002f) 1744 .setInterpolator(mBackdropInterpolator) 1745 .setDuration(300) 1746 .setStartDelay(0) 1747 .withEndAction(new Runnable() { 1748 @Override 1749 public void run() { 1750 mBackdrop.setVisibility(View.GONE); 1751 mBackdropFront.animate().cancel(); 1752 mBackdropBack.animate().cancel(); 1753 mHandler.post(mHideBackdropFront); 1754 } 1755 }); 1756 if (mKeyguardFadingAway) { 1757 mBackdrop.animate() 1758 1759 // Make it disappear faster, as the focus should be on the activity behind. 1760 .setDuration(mKeyguardFadingAwayDuration / 2) 1761 .setStartDelay(mKeyguardFadingAwayDelay) 1762 .setInterpolator(mLinearInterpolator) 1763 .start(); 1764 } 1765 } 1766 } 1767 } 1768 adjustDisableFlags(int state)1769 private int adjustDisableFlags(int state) { 1770 if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway 1771 && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) { 1772 state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; 1773 state |= StatusBarManager.DISABLE_SYSTEM_INFO; 1774 } 1775 return state; 1776 } 1777 1778 /** 1779 * State is one or more of the DISABLE constants from StatusBarManager. 1780 */ disable(int state1, int state2, boolean animate)1781 public void disable(int state1, int state2, boolean animate) { 1782 animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN; 1783 mDisabledUnmodified1 = state1; 1784 mDisabledUnmodified2 = state2; 1785 state1 = adjustDisableFlags(state1); 1786 final int old1 = mDisabled1; 1787 final int diff1 = state1 ^ old1; 1788 mDisabled1 = state1; 1789 1790 final int old2 = mDisabled2; 1791 final int diff2 = state2 ^ old2; 1792 mDisabled2 = state2; 1793 1794 if (DEBUG) { 1795 Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", 1796 old1, state1, diff1)); 1797 Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", 1798 old2, state2, diff2)); 1799 } 1800 1801 StringBuilder flagdbg = new StringBuilder(); 1802 flagdbg.append("disable: < "); 1803 flagdbg.append(((state1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "EXPAND" : "expand"); 1804 flagdbg.append(((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "* " : " "); 1805 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "ICONS" : "icons"); 1806 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " "); 1807 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts"); 1808 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " "); 1809 flagdbg.append(((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info"); 1810 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " "); 1811 flagdbg.append(((state1 & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back"); 1812 flagdbg.append(((diff1 & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " "); 1813 flagdbg.append(((state1 & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home"); 1814 flagdbg.append(((diff1 & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " "); 1815 flagdbg.append(((state1 & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent"); 1816 flagdbg.append(((diff1 & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " "); 1817 flagdbg.append(((state1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock"); 1818 flagdbg.append(((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " "); 1819 flagdbg.append(((state1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search"); 1820 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " "); 1821 flagdbg.append(((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "QUICK_SETTINGS" 1822 : "quick_settings"); 1823 flagdbg.append(((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "* " : " "); 1824 flagdbg.append(">"); 1825 Log.d(TAG, flagdbg.toString()); 1826 1827 if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { 1828 if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { 1829 mIconController.hideSystemIconArea(animate); 1830 } else { 1831 mIconController.showSystemIconArea(animate); 1832 } 1833 } 1834 1835 if ((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) { 1836 boolean visible = (state1 & StatusBarManager.DISABLE_CLOCK) == 0; 1837 mIconController.setClockVisibility(visible); 1838 } 1839 if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { 1840 if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { 1841 animateCollapsePanels(); 1842 } 1843 } 1844 1845 if ((diff1 & (StatusBarManager.DISABLE_HOME 1846 | StatusBarManager.DISABLE_RECENT 1847 | StatusBarManager.DISABLE_BACK 1848 | StatusBarManager.DISABLE_SEARCH)) != 0) { 1849 // the nav bar will take care of these 1850 if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1); 1851 1852 if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) { 1853 // close recents if it's visible 1854 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 1855 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 1856 } 1857 } 1858 1859 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { 1860 if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { 1861 mIconController.hideNotificationIconArea(animate); 1862 } else { 1863 mIconController.showNotificationIconArea(animate); 1864 } 1865 } 1866 1867 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { 1868 mDisableNotificationAlerts = 1869 (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; 1870 mHeadsUpObserver.onChange(true); 1871 } 1872 1873 if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) { 1874 updateQsExpansionEnabled(); 1875 } 1876 } 1877 1878 @Override createHandler()1879 protected BaseStatusBar.H createHandler() { 1880 return new PhoneStatusBar.H(); 1881 } 1882 1883 @Override startActivity(Intent intent, boolean dismissShade)1884 public void startActivity(Intent intent, boolean dismissShade) { 1885 startActivityDismissingKeyguard(intent, false, dismissShade); 1886 } 1887 1888 @Override startActivity(Intent intent, boolean dismissShade, Callback callback)1889 public void startActivity(Intent intent, boolean dismissShade, Callback callback) { 1890 startActivityDismissingKeyguard(intent, false, dismissShade, callback); 1891 } 1892 1893 @Override preventNextAnimation()1894 public void preventNextAnimation() { 1895 overrideActivityPendingAppTransition(true /* keyguardShowing */); 1896 } 1897 setQsExpanded(boolean expanded)1898 public void setQsExpanded(boolean expanded) { 1899 mStatusBarWindowManager.setQsExpanded(expanded); 1900 mKeyguardStatusView.setImportantForAccessibility(expanded 1901 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 1902 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); 1903 } 1904 isGoingToNotificationShade()1905 public boolean isGoingToNotificationShade() { 1906 return mLeaveOpenOnKeyguardHide; 1907 } 1908 isQsExpanded()1909 public boolean isQsExpanded() { 1910 return mNotificationPanel.isQsExpanded(); 1911 } 1912 isScreenOnComingFromTouch()1913 public boolean isScreenOnComingFromTouch() { 1914 return mScreenOnComingFromTouch; 1915 } 1916 isFalsingThresholdNeeded()1917 public boolean isFalsingThresholdNeeded() { 1918 return getBarState() == StatusBarState.KEYGUARD; 1919 } 1920 isDozing()1921 public boolean isDozing() { 1922 return mDozing; 1923 } 1924 1925 @Override // NotificationData.Environment getCurrentMediaNotificationKey()1926 public String getCurrentMediaNotificationKey() { 1927 return mMediaNotificationKey; 1928 } 1929 isScrimSrcModeEnabled()1930 public boolean isScrimSrcModeEnabled() { 1931 return mScrimSrcModeEnabled; 1932 } 1933 1934 /** 1935 * To be called when there's a state change in StatusBarKeyguardViewManager. 1936 */ onKeyguardViewManagerStatesUpdated()1937 public void onKeyguardViewManagerStatesUpdated() { 1938 logStateToEventlog(); 1939 } 1940 1941 @Override // UnlockMethodCache.OnUnlockMethodChangedListener onUnlockMethodStateChanged()1942 public void onUnlockMethodStateChanged() { 1943 logStateToEventlog(); 1944 } 1945 1946 @Override onHeadsUpPinnedModeChanged(boolean inPinnedMode)1947 public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { 1948 if (inPinnedMode) { 1949 mStatusBarWindowManager.setHeadsUpShowing(true); 1950 mStatusBarWindowManager.setForceStatusBarVisible(true); 1951 if (mNotificationPanel.isFullyCollapsed()) { 1952 // We need to ensure that the touchable region is updated before the window will be 1953 // resized, in order to not catch any touches. A layout will ensure that 1954 // onComputeInternalInsets will be called and after that we can resize the layout. Let's 1955 // make sure that the window stays small for one frame until the touchableRegion is set. 1956 mNotificationPanel.requestLayout(); 1957 mStatusBarWindowManager.setForceWindowCollapsed(true); 1958 mNotificationPanel.post(new Runnable() { 1959 @Override 1960 public void run() { 1961 mStatusBarWindowManager.setForceWindowCollapsed(false); 1962 } 1963 }); 1964 } 1965 } else { 1966 if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) { 1967 // We are currently tracking or is open and the shade doesn't need to be kept 1968 // open artificially. 1969 mStatusBarWindowManager.setHeadsUpShowing(false); 1970 } else { 1971 // we need to keep the panel open artificially, let's wait until the animation 1972 // is finished. 1973 mHeadsUpManager.setHeadsUpGoingAway(true); 1974 mStackScroller.runAfterAnimationFinished(new Runnable() { 1975 @Override 1976 public void run() { 1977 if (!mHeadsUpManager.hasPinnedHeadsUp()) { 1978 mStatusBarWindowManager.setHeadsUpShowing(false); 1979 mHeadsUpManager.setHeadsUpGoingAway(false); 1980 } 1981 } 1982 }); 1983 } 1984 } 1985 } 1986 1987 @Override onHeadsUpPinned(ExpandableNotificationRow headsUp)1988 public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { 1989 dismissVolumeDialog(); 1990 } 1991 1992 @Override onHeadsUpUnPinned(ExpandableNotificationRow headsUp)1993 public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { 1994 } 1995 1996 @Override onHeadsUpStateChanged(Entry entry, boolean isHeadsUp)1997 public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { 1998 if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) { 1999 removeNotification(entry.key, mLatestRankingMap); 2000 mHeadsUpEntriesToRemoveOnSwitch.remove(entry); 2001 if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) { 2002 mLatestRankingMap = null; 2003 } 2004 } else { 2005 updateNotificationRanking(null); 2006 } 2007 2008 } 2009 updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, boolean alertAgain)2010 protected void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, 2011 boolean alertAgain) { 2012 final boolean wasHeadsUp = isHeadsUp(key); 2013 if (wasHeadsUp) { 2014 if (!shouldInterrupt) { 2015 // We don't want this to be interrupting anymore, lets remove it 2016 mHeadsUpManager.removeNotification(key); 2017 } else { 2018 mHeadsUpManager.updateNotification(entry, alertAgain); 2019 } 2020 } else if (shouldInterrupt && alertAgain) { 2021 // This notification was updated to be a heads-up, show it! 2022 mHeadsUpManager.showNotification(entry); 2023 } 2024 } 2025 setHeadsUpUser(int newUserId)2026 protected void setHeadsUpUser(int newUserId) { 2027 if (mHeadsUpManager != null) { 2028 mHeadsUpManager.setUser(newUserId); 2029 } 2030 } 2031 isHeadsUp(String key)2032 public boolean isHeadsUp(String key) { 2033 return mHeadsUpManager.isHeadsUp(key); 2034 } 2035 isSnoozedPackage(StatusBarNotification sbn)2036 protected boolean isSnoozedPackage(StatusBarNotification sbn) { 2037 return mHeadsUpManager.isSnoozed(sbn.getPackageName()); 2038 } 2039 isKeyguardCurrentlySecure()2040 public boolean isKeyguardCurrentlySecure() { 2041 return !mUnlockMethodCache.canSkipBouncer(); 2042 } 2043 setPanelExpanded(boolean isExpanded)2044 public void setPanelExpanded(boolean isExpanded) { 2045 mStatusBarWindowManager.setPanelExpanded(isExpanded); 2046 } 2047 2048 /** 2049 * All changes to the status bar and notifications funnel through here and are batched. 2050 */ 2051 private class H extends BaseStatusBar.H { handleMessage(Message m)2052 public void handleMessage(Message m) { 2053 super.handleMessage(m); 2054 switch (m.what) { 2055 case MSG_OPEN_NOTIFICATION_PANEL: 2056 animateExpandNotificationsPanel(); 2057 break; 2058 case MSG_OPEN_SETTINGS_PANEL: 2059 animateExpandSettingsPanel(); 2060 break; 2061 case MSG_CLOSE_PANELS: 2062 animateCollapsePanels(); 2063 break; 2064 case MSG_LAUNCH_TRANSITION_TIMEOUT: 2065 onLaunchTransitionTimeout(); 2066 break; 2067 } 2068 } 2069 } 2070 2071 @Override maybeEscalateHeadsUp()2072 public void maybeEscalateHeadsUp() { 2073 TreeSet<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getSortedEntries(); 2074 for (HeadsUpManager.HeadsUpEntry entry : entries) { 2075 final StatusBarNotification sbn = entry.entry.notification; 2076 final Notification notification = sbn.getNotification(); 2077 if (notification.fullScreenIntent != null) { 2078 if (DEBUG) { 2079 Log.d(TAG, "converting a heads up to fullScreen"); 2080 } 2081 try { 2082 EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, 2083 sbn.getKey()); 2084 notification.fullScreenIntent.send(); 2085 entry.entry.notifyFullScreenIntentLaunched(); 2086 } catch (PendingIntent.CanceledException e) { 2087 } 2088 } 2089 } 2090 mHeadsUpManager.releaseAllImmediately(); 2091 } 2092 panelsEnabled()2093 boolean panelsEnabled() { 2094 return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS; 2095 } 2096 makeExpandedVisible(boolean force)2097 void makeExpandedVisible(boolean force) { 2098 if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); 2099 if (!force && (mExpandedVisible || !panelsEnabled())) { 2100 return; 2101 } 2102 2103 mExpandedVisible = true; 2104 if (mNavigationBarView != null) 2105 mNavigationBarView.setSlippery(true); 2106 2107 // Expand the window to encompass the full screen in anticipation of the drag. 2108 // This is only possible to do atomically because the status bar is at the top of the screen! 2109 mStatusBarWindowManager.setPanelVisible(true); 2110 2111 visibilityChanged(true); 2112 mWaitingForKeyguardExit = false; 2113 disable(mDisabledUnmodified1, mDisabledUnmodified2, !force /* animate */); 2114 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 2115 } 2116 animateCollapsePanels()2117 public void animateCollapsePanels() { 2118 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 2119 } 2120 2121 private final Runnable mAnimateCollapsePanels = new Runnable() { 2122 @Override 2123 public void run() { 2124 animateCollapsePanels(); 2125 } 2126 }; 2127 postAnimateCollapsePanels()2128 public void postAnimateCollapsePanels() { 2129 mHandler.post(mAnimateCollapsePanels); 2130 } 2131 animateCollapsePanels(int flags)2132 public void animateCollapsePanels(int flags) { 2133 animateCollapsePanels(flags, false /* force */, false /* delayed */, 2134 1.0f /* speedUpFactor */); 2135 } 2136 animateCollapsePanels(int flags, boolean force)2137 public void animateCollapsePanels(int flags, boolean force) { 2138 animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */); 2139 } 2140 animateCollapsePanels(int flags, boolean force, boolean delayed)2141 public void animateCollapsePanels(int flags, boolean force, boolean delayed) { 2142 animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */); 2143 } 2144 animateCollapsePanels(int flags, boolean force, boolean delayed, float speedUpFactor)2145 public void animateCollapsePanels(int flags, boolean force, boolean delayed, 2146 float speedUpFactor) { 2147 if (!force && 2148 (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { 2149 runPostCollapseRunnables(); 2150 return; 2151 } 2152 if (SPEW) { 2153 Log.d(TAG, "animateCollapse():" 2154 + " mExpandedVisible=" + mExpandedVisible 2155 + " flags=" + flags); 2156 } 2157 2158 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) { 2159 if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) { 2160 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 2161 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 2162 } 2163 } 2164 2165 if (mStatusBarWindow != null) { 2166 // release focus immediately to kick off focus change transition 2167 mStatusBarWindowManager.setStatusBarFocusable(false); 2168 2169 mStatusBarWindow.cancelExpandHelper(); 2170 mStatusBarView.collapseAllPanels(true /* animate */, delayed, speedUpFactor); 2171 } 2172 } 2173 runPostCollapseRunnables()2174 private void runPostCollapseRunnables() { 2175 ArrayList<Runnable> clonedList = new ArrayList<>(mPostCollapseRunnables); 2176 mPostCollapseRunnables.clear(); 2177 int size = clonedList.size(); 2178 for (int i = 0; i < size; i++) { 2179 clonedList.get(i).run(); 2180 } 2181 2182 } 2183 2184 Animator mScrollViewAnim, mClearButtonAnim; 2185 2186 @Override animateExpandNotificationsPanel()2187 public void animateExpandNotificationsPanel() { 2188 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2189 if (!panelsEnabled()) { 2190 return ; 2191 } 2192 2193 mNotificationPanel.expand(); 2194 2195 if (false) postStartTracing(); 2196 } 2197 2198 @Override animateExpandSettingsPanel()2199 public void animateExpandSettingsPanel() { 2200 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2201 if (!panelsEnabled()) { 2202 return; 2203 } 2204 2205 // Settings are not available in setup 2206 if (!mUserSetup) return; 2207 2208 mNotificationPanel.expandWithQs(); 2209 2210 if (false) postStartTracing(); 2211 } 2212 animateCollapseQuickSettings()2213 public void animateCollapseQuickSettings() { 2214 if (mState == StatusBarState.SHADE) { 2215 mStatusBarView.collapseAllPanels(true, false /* delayed */, 1.0f /* speedUpFactor */); 2216 } 2217 } 2218 makeExpandedInvisible()2219 void makeExpandedInvisible() { 2220 if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible 2221 + " mExpandedVisible=" + mExpandedVisible); 2222 2223 if (!mExpandedVisible || mStatusBarWindow == null) { 2224 return; 2225 } 2226 2227 // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) 2228 mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/, 2229 1.0f /* speedUpFactor */); 2230 2231 mNotificationPanel.closeQs(); 2232 2233 mExpandedVisible = false; 2234 if (mNavigationBarView != null) 2235 mNavigationBarView.setSlippery(false); 2236 visibilityChanged(false); 2237 2238 // Shrink the window to the size of the status bar only 2239 mStatusBarWindowManager.setPanelVisible(false); 2240 mStatusBarWindowManager.setForceStatusBarVisible(false); 2241 2242 // Close any "App info" popups that might have snuck on-screen 2243 dismissPopups(); 2244 2245 runPostCollapseRunnables(); 2246 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 2247 showBouncer(); 2248 disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */); 2249 2250 // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in 2251 // the bouncer appear animation. 2252 if (!mStatusBarKeyguardViewManager.isShowing()) { 2253 WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 2254 } 2255 } 2256 interceptTouchEvent(MotionEvent event)2257 public boolean interceptTouchEvent(MotionEvent event) { 2258 if (DEBUG_GESTURES) { 2259 if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { 2260 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, 2261 event.getActionMasked(), (int) event.getX(), (int) event.getY(), 2262 mDisabled1, mDisabled2); 2263 } 2264 2265 } 2266 2267 if (SPEW) { 2268 Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" 2269 + mDisabled1 + " mDisabled2=" + mDisabled2 + " mTracking=" + mTracking); 2270 } else if (CHATTY) { 2271 if (event.getAction() != MotionEvent.ACTION_MOVE) { 2272 Log.d(TAG, String.format( 2273 "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", 2274 MotionEvent.actionToString(event.getAction()), 2275 event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); 2276 } 2277 } 2278 2279 if (DEBUG_GESTURES) { 2280 mGestureRec.add(event); 2281 } 2282 2283 if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { 2284 final boolean upOrCancel = 2285 event.getAction() == MotionEvent.ACTION_UP || 2286 event.getAction() == MotionEvent.ACTION_CANCEL; 2287 if (upOrCancel && !mExpandedVisible) { 2288 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 2289 } else { 2290 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 2291 } 2292 } 2293 return false; 2294 } 2295 getGestureRecorder()2296 public GestureRecorder getGestureRecorder() { 2297 return mGestureRec; 2298 } 2299 setNavigationIconHints(int hints)2300 private void setNavigationIconHints(int hints) { 2301 if (hints == mNavigationIconHints) return; 2302 2303 mNavigationIconHints = hints; 2304 2305 if (mNavigationBarView != null) { 2306 mNavigationBarView.setNavigationIconHints(hints); 2307 } 2308 checkBarModes(); 2309 } 2310 2311 @Override // CommandQueue setWindowState(int window, int state)2312 public void setWindowState(int window, int state) { 2313 boolean showing = state == WINDOW_STATE_SHOWING; 2314 if (mStatusBarWindow != null 2315 && window == StatusBarManager.WINDOW_STATUS_BAR 2316 && mStatusBarWindowState != state) { 2317 mStatusBarWindowState = state; 2318 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); 2319 if (!showing && mState == StatusBarState.SHADE) { 2320 mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */, 2321 1.0f /* speedUpFactor */); 2322 } 2323 } 2324 if (mNavigationBarView != null 2325 && window == StatusBarManager.WINDOW_NAVIGATION_BAR 2326 && mNavigationBarWindowState != state) { 2327 mNavigationBarWindowState = state; 2328 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state)); 2329 } 2330 } 2331 2332 @Override // CommandQueue buzzBeepBlinked()2333 public void buzzBeepBlinked() { 2334 if (mDozeServiceHost != null) { 2335 mDozeServiceHost.fireBuzzBeepBlinked(); 2336 } 2337 } 2338 2339 @Override notificationLightOff()2340 public void notificationLightOff() { 2341 if (mDozeServiceHost != null) { 2342 mDozeServiceHost.fireNotificationLight(false); 2343 } 2344 } 2345 2346 @Override notificationLightPulse(int argb, int onMillis, int offMillis)2347 public void notificationLightPulse(int argb, int onMillis, int offMillis) { 2348 if (mDozeServiceHost != null) { 2349 mDozeServiceHost.fireNotificationLight(true); 2350 } 2351 } 2352 2353 @Override // CommandQueue setSystemUiVisibility(int vis, int mask)2354 public void setSystemUiVisibility(int vis, int mask) { 2355 final int oldVal = mSystemUiVisibility; 2356 final int newVal = (oldVal&~mask) | (vis&mask); 2357 final int diff = newVal ^ oldVal; 2358 if (DEBUG) Log.d(TAG, String.format( 2359 "setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s", 2360 Integer.toHexString(vis), Integer.toHexString(mask), 2361 Integer.toHexString(oldVal), Integer.toHexString(newVal), 2362 Integer.toHexString(diff))); 2363 if (diff != 0) { 2364 // we never set the recents bit via this method, so save the prior state to prevent 2365 // clobbering the bit below 2366 final boolean wasRecentsVisible = (mSystemUiVisibility & View.RECENT_APPS_VISIBLE) > 0; 2367 2368 mSystemUiVisibility = newVal; 2369 2370 // update low profile 2371 if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) { 2372 final boolean lightsOut = (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0; 2373 if (lightsOut) { 2374 animateCollapsePanels(); 2375 } 2376 2377 setAreThereNotifications(); 2378 } 2379 2380 // ready to unhide 2381 if ((vis & View.STATUS_BAR_UNHIDE) != 0) { 2382 mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE; 2383 mNoAnimationOnNextBarModeChange = true; 2384 } 2385 2386 // update status bar mode 2387 final int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(), 2388 View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT); 2389 2390 // update navigation bar mode 2391 final int nbMode = mNavigationBarView == null ? -1 : computeBarMode( 2392 oldVal, newVal, mNavigationBarView.getBarTransitions(), 2393 View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT); 2394 final boolean sbModeChanged = sbMode != -1; 2395 final boolean nbModeChanged = nbMode != -1; 2396 boolean checkBarModes = false; 2397 if (sbModeChanged && sbMode != mStatusBarMode) { 2398 mStatusBarMode = sbMode; 2399 checkBarModes = true; 2400 } 2401 if (nbModeChanged && nbMode != mNavigationBarMode) { 2402 mNavigationBarMode = nbMode; 2403 checkBarModes = true; 2404 } 2405 if (checkBarModes) { 2406 checkBarModes(); 2407 } 2408 if (sbModeChanged || nbModeChanged) { 2409 // update transient bar autohide 2410 if (mStatusBarMode == MODE_SEMI_TRANSPARENT || mNavigationBarMode == MODE_SEMI_TRANSPARENT) { 2411 scheduleAutohide(); 2412 } else { 2413 cancelAutohide(); 2414 } 2415 } 2416 2417 if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) { 2418 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE; 2419 } 2420 2421 if ((diff & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0 || sbModeChanged) { 2422 boolean isTransparentBar = (mStatusBarMode == MODE_TRANSPARENT 2423 || mStatusBarMode == MODE_LIGHTS_OUT_TRANSPARENT); 2424 boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave(); 2425 boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0; 2426 2427 mIconController.setIconsDark(allowLight && light); 2428 } 2429 // restore the recents bit 2430 if (wasRecentsVisible) { 2431 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE; 2432 } 2433 2434 // send updated sysui visibility to window manager 2435 notifyUiVisibilityChanged(mSystemUiVisibility); 2436 } 2437 } 2438 computeBarMode(int oldVis, int newVis, BarTransitions transitions, int transientFlag, int translucentFlag)2439 private int computeBarMode(int oldVis, int newVis, BarTransitions transitions, 2440 int transientFlag, int translucentFlag) { 2441 final int oldMode = barMode(oldVis, transientFlag, translucentFlag); 2442 final int newMode = barMode(newVis, transientFlag, translucentFlag); 2443 if (oldMode == newMode) { 2444 return -1; // no mode change 2445 } 2446 return newMode; 2447 } 2448 barMode(int vis, int transientFlag, int translucentFlag)2449 private int barMode(int vis, int transientFlag, int translucentFlag) { 2450 int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_TRANSPARENT; 2451 return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT 2452 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT 2453 : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT 2454 : (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT 2455 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT 2456 : MODE_OPAQUE; 2457 } 2458 checkBarModes()2459 private void checkBarModes() { 2460 if (mDemoMode) return; 2461 checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarView.getBarTransitions(), 2462 mNoAnimationOnNextBarModeChange); 2463 if (mNavigationBarView != null) { 2464 checkBarMode(mNavigationBarMode, 2465 mNavigationBarWindowState, mNavigationBarView.getBarTransitions(), 2466 mNoAnimationOnNextBarModeChange); 2467 } 2468 mNoAnimationOnNextBarModeChange = false; 2469 } 2470 checkBarMode(int mode, int windowState, BarTransitions transitions, boolean noAnimation)2471 private void checkBarMode(int mode, int windowState, BarTransitions transitions, 2472 boolean noAnimation) { 2473 final boolean powerSave = mBatteryController.isPowerSave(); 2474 final boolean anim = !noAnimation && (mScreenOn == null || mScreenOn) 2475 && windowState != WINDOW_STATE_HIDDEN && !powerSave; 2476 if (powerSave && getBarState() == StatusBarState.SHADE) { 2477 mode = MODE_WARNING; 2478 } 2479 transitions.transitionTo(mode, anim); 2480 } 2481 finishBarAnimations()2482 private void finishBarAnimations() { 2483 mStatusBarView.getBarTransitions().finishAnimations(); 2484 if (mNavigationBarView != null) { 2485 mNavigationBarView.getBarTransitions().finishAnimations(); 2486 } 2487 } 2488 2489 private final Runnable mCheckBarModes = new Runnable() { 2490 @Override 2491 public void run() { 2492 checkBarModes(); 2493 } 2494 }; 2495 2496 @Override setInteracting(int barWindow, boolean interacting)2497 public void setInteracting(int barWindow, boolean interacting) { 2498 final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting; 2499 mInteractingWindows = interacting 2500 ? (mInteractingWindows | barWindow) 2501 : (mInteractingWindows & ~barWindow); 2502 if (mInteractingWindows != 0) { 2503 suspendAutohide(); 2504 } else { 2505 resumeSuspendedAutohide(); 2506 } 2507 // manually dismiss the volume panel when interacting with the nav bar 2508 if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) { 2509 dismissVolumeDialog(); 2510 } 2511 checkBarModes(); 2512 } 2513 dismissVolumeDialog()2514 private void dismissVolumeDialog() { 2515 if (mVolumeComponent != null) { 2516 mVolumeComponent.dismissNow(); 2517 } 2518 } 2519 resumeSuspendedAutohide()2520 private void resumeSuspendedAutohide() { 2521 if (mAutohideSuspended) { 2522 scheduleAutohide(); 2523 mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher 2524 } 2525 } 2526 suspendAutohide()2527 private void suspendAutohide() { 2528 mHandler.removeCallbacks(mAutohide); 2529 mHandler.removeCallbacks(mCheckBarModes); 2530 mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0; 2531 } 2532 cancelAutohide()2533 private void cancelAutohide() { 2534 mAutohideSuspended = false; 2535 mHandler.removeCallbacks(mAutohide); 2536 } 2537 scheduleAutohide()2538 private void scheduleAutohide() { 2539 cancelAutohide(); 2540 mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); 2541 } 2542 checkUserAutohide(View v, MotionEvent event)2543 private void checkUserAutohide(View v, MotionEvent event) { 2544 if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed 2545 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar 2546 && event.getX() == 0 && event.getY() == 0 // a touch outside both bars 2547 ) { 2548 userAutohide(); 2549 } 2550 } 2551 userAutohide()2552 private void userAutohide() { 2553 cancelAutohide(); 2554 mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear 2555 } 2556 areLightsOn()2557 private boolean areLightsOn() { 2558 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); 2559 } 2560 setLightsOn(boolean on)2561 public void setLightsOn(boolean on) { 2562 Log.v(TAG, "setLightsOn(" + on + ")"); 2563 if (on) { 2564 setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE); 2565 } else { 2566 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE); 2567 } 2568 } 2569 notifyUiVisibilityChanged(int vis)2570 private void notifyUiVisibilityChanged(int vis) { 2571 try { 2572 if (mLastDispatchedSystemUiVisibility != vis) { 2573 mWindowManagerService.statusBarVisibilityChanged(vis); 2574 mLastDispatchedSystemUiVisibility = vis; 2575 } 2576 } catch (RemoteException ex) { 2577 } 2578 } 2579 topAppWindowChanged(boolean showMenu)2580 public void topAppWindowChanged(boolean showMenu) { 2581 if (DEBUG) { 2582 Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button"); 2583 } 2584 if (mNavigationBarView != null) { 2585 mNavigationBarView.setMenuVisibility(showMenu); 2586 } 2587 2588 // See above re: lights-out policy for legacy apps. 2589 if (showMenu) setLightsOn(true); 2590 } 2591 2592 @Override setImeWindowStatus(IBinder token, int vis, int backDisposition, boolean showImeSwitcher)2593 public void setImeWindowStatus(IBinder token, int vis, int backDisposition, 2594 boolean showImeSwitcher) { 2595 boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; 2596 int flags = mNavigationIconHints; 2597 if ((backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) || imeShown) { 2598 flags |= NAVIGATION_HINT_BACK_ALT; 2599 } else { 2600 flags &= ~NAVIGATION_HINT_BACK_ALT; 2601 } 2602 if (showImeSwitcher) { 2603 flags |= NAVIGATION_HINT_IME_SHOWN; 2604 } else { 2605 flags &= ~NAVIGATION_HINT_IME_SHOWN; 2606 } 2607 2608 setNavigationIconHints(flags); 2609 } 2610 viewInfo(View v)2611 public static String viewInfo(View v) { 2612 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() 2613 + ") " + v.getWidth() + "x" + v.getHeight() + "]"; 2614 } 2615 dump(FileDescriptor fd, PrintWriter pw, String[] args)2616 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2617 synchronized (mQueueLock) { 2618 pw.println("Current Status Bar state:"); 2619 pw.println(" mExpandedVisible=" + mExpandedVisible 2620 + ", mTrackingPosition=" + mTrackingPosition); 2621 pw.println(" mTracking=" + mTracking); 2622 pw.println(" mDisplayMetrics=" + mDisplayMetrics); 2623 pw.println(" mStackScroller: " + viewInfo(mStackScroller)); 2624 pw.println(" mStackScroller: " + viewInfo(mStackScroller) 2625 + " scroll " + mStackScroller.getScrollX() 2626 + "," + mStackScroller.getScrollY()); 2627 } 2628 2629 pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); 2630 pw.print(" mStatusBarWindowState="); 2631 pw.println(windowStateToString(mStatusBarWindowState)); 2632 pw.print(" mStatusBarMode="); 2633 pw.println(BarTransitions.modeToString(mStatusBarMode)); 2634 pw.print(" mDozing="); pw.println(mDozing); 2635 pw.print(" mZenMode="); 2636 pw.println(Settings.Global.zenModeToString(mZenMode)); 2637 pw.print(" mUseHeadsUp="); 2638 pw.println(mUseHeadsUp); 2639 dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); 2640 if (mNavigationBarView != null) { 2641 pw.print(" mNavigationBarWindowState="); 2642 pw.println(windowStateToString(mNavigationBarWindowState)); 2643 pw.print(" mNavigationBarMode="); 2644 pw.println(BarTransitions.modeToString(mNavigationBarMode)); 2645 dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions()); 2646 } 2647 2648 pw.print(" mNavigationBarView="); 2649 if (mNavigationBarView == null) { 2650 pw.println("null"); 2651 } else { 2652 mNavigationBarView.dump(fd, pw, args); 2653 } 2654 2655 pw.print(" mMediaSessionManager="); 2656 pw.println(mMediaSessionManager); 2657 pw.print(" mMediaNotificationKey="); 2658 pw.println(mMediaNotificationKey); 2659 pw.print(" mMediaController="); 2660 pw.print(mMediaController); 2661 if (mMediaController != null) { 2662 pw.print(" state=" + mMediaController.getPlaybackState()); 2663 } 2664 pw.println(); 2665 pw.print(" mMediaMetadata="); 2666 pw.print(mMediaMetadata); 2667 if (mMediaMetadata != null) { 2668 pw.print(" title=" + mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE)); 2669 } 2670 pw.println(); 2671 2672 pw.println(" Panels: "); 2673 if (mNotificationPanel != null) { 2674 pw.println(" mNotificationPanel=" + 2675 mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug("")); 2676 pw.print (" "); 2677 mNotificationPanel.dump(fd, pw, args); 2678 } 2679 2680 DozeLog.dump(pw); 2681 2682 if (DUMPTRUCK) { 2683 synchronized (mNotificationData) { 2684 mNotificationData.dump(pw, " "); 2685 } 2686 2687 mIconController.dump(pw); 2688 2689 if (false) { 2690 pw.println("see the logcat for a dump of the views we have created."); 2691 // must happen on ui thread 2692 mHandler.post(new Runnable() { 2693 public void run() { 2694 mStatusBarView.getLocationOnScreen(mAbsPos); 2695 Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] 2696 + ") " + mStatusBarView.getWidth() + "x" 2697 + getStatusBarHeight()); 2698 mStatusBarView.debug(); 2699 } 2700 }); 2701 } 2702 } 2703 2704 if (DEBUG_GESTURES) { 2705 pw.print(" status bar gestures: "); 2706 mGestureRec.dump(fd, pw, args); 2707 } 2708 if (mStatusBarWindowManager != null) { 2709 mStatusBarWindowManager.dump(fd, pw, args); 2710 } 2711 if (mNetworkController != null) { 2712 mNetworkController.dump(fd, pw, args); 2713 } 2714 if (mBluetoothController != null) { 2715 mBluetoothController.dump(fd, pw, args); 2716 } 2717 if (mHotspotController != null) { 2718 mHotspotController.dump(fd, pw, args); 2719 } 2720 if (mCastController != null) { 2721 mCastController.dump(fd, pw, args); 2722 } 2723 if (mUserSwitcherController != null) { 2724 mUserSwitcherController.dump(fd, pw, args); 2725 } 2726 if (mBatteryController != null) { 2727 mBatteryController.dump(fd, pw, args); 2728 } 2729 if (mNextAlarmController != null) { 2730 mNextAlarmController.dump(fd, pw, args); 2731 } 2732 if (mAssistManager != null) { 2733 mAssistManager.dump(fd, pw, args); 2734 } 2735 if (mSecurityController != null) { 2736 mSecurityController.dump(fd, pw, args); 2737 } 2738 if (mHeadsUpManager != null) { 2739 mHeadsUpManager.dump(fd, pw, args); 2740 } else { 2741 pw.println(" mHeadsUpManager: null"); 2742 } 2743 if (KeyguardUpdateMonitor.getInstance(mContext) != null) { 2744 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args); 2745 } 2746 2747 pw.println("SharedPreferences:"); 2748 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) { 2749 pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); 2750 } 2751 } 2752 hunStateToString(Entry entry)2753 private String hunStateToString(Entry entry) { 2754 if (entry == null) return "null"; 2755 if (entry.notification == null) return "corrupt"; 2756 return entry.notification.getPackageName(); 2757 } 2758 dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions)2759 private static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) { 2760 pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode="); 2761 pw.println(BarTransitions.modeToString(transitions.getMode())); 2762 } 2763 2764 @Override createAndAddWindows()2765 public void createAndAddWindows() { 2766 addStatusBarWindow(); 2767 } 2768 addStatusBarWindow()2769 private void addStatusBarWindow() { 2770 makeStatusBarView(); 2771 mStatusBarWindowManager = new StatusBarWindowManager(mContext); 2772 mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); 2773 } 2774 2775 // called by makeStatusbar and also by PhoneStatusBarView updateDisplaySize()2776 void updateDisplaySize() { 2777 mDisplay.getMetrics(mDisplayMetrics); 2778 mDisplay.getSize(mCurrentDisplaySize); 2779 if (DEBUG_GESTURES) { 2780 mGestureRec.tag("display", 2781 String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); 2782 } 2783 } 2784 getDisplayDensity()2785 float getDisplayDensity() { 2786 return mDisplayMetrics.density; 2787 } 2788 startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade)2789 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 2790 boolean dismissShade) { 2791 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */); 2792 } 2793 startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final Callback callback)2794 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 2795 final boolean dismissShade, final Callback callback) { 2796 if (onlyProvisioned && !isDeviceProvisioned()) return; 2797 2798 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( 2799 mContext, intent, mCurrentUserId); 2800 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); 2801 Runnable runnable = new Runnable() { 2802 public void run() { 2803 mAssistManager.hideAssist(); 2804 intent.setFlags( 2805 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2806 int result = ActivityManager.START_CANCELED; 2807 try { 2808 result = ActivityManagerNative.getDefault().startActivityAsUser( 2809 null, mContext.getBasePackageName(), 2810 intent, 2811 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2812 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, 2813 UserHandle.CURRENT.getIdentifier()); 2814 } catch (RemoteException e) { 2815 Log.w(TAG, "Unable to start activity", e); 2816 } 2817 overrideActivityPendingAppTransition( 2818 keyguardShowing && !afterKeyguardGone); 2819 if (callback != null) { 2820 callback.onActivityStarted(result); 2821 } 2822 } 2823 }; 2824 Runnable cancelRunnable = new Runnable() { 2825 @Override 2826 public void run() { 2827 if (callback != null) { 2828 callback.onActivityStarted(ActivityManager.START_CANCELED); 2829 } 2830 } 2831 }; 2832 executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, 2833 afterKeyguardGone); 2834 } 2835 executeRunnableDismissingKeyguard(final Runnable runnable, final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone)2836 public void executeRunnableDismissingKeyguard(final Runnable runnable, 2837 final Runnable cancelAction, 2838 final boolean dismissShade, 2839 final boolean afterKeyguardGone) { 2840 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); 2841 dismissKeyguardThenExecute(new OnDismissAction() { 2842 @Override 2843 public boolean onDismiss() { 2844 AsyncTask.execute(new Runnable() { 2845 public void run() { 2846 try { 2847 if (keyguardShowing && !afterKeyguardGone) { 2848 ActivityManagerNative.getDefault() 2849 .keyguardWaitingForActivityDrawn(); 2850 } 2851 if (runnable != null) { 2852 runnable.run(); 2853 } 2854 } catch (RemoteException e) { 2855 } 2856 } 2857 }); 2858 if (dismissShade) { 2859 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, 2860 true /* delayed*/); 2861 } 2862 return true; 2863 } 2864 }, cancelAction, afterKeyguardGone); 2865 } 2866 2867 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 2868 public void onReceive(Context context, Intent intent) { 2869 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 2870 String action = intent.getAction(); 2871 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { 2872 if (isCurrentProfile(getSendingUserId())) { 2873 int flags = CommandQueue.FLAG_EXCLUDE_NONE; 2874 String reason = intent.getStringExtra("reason"); 2875 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { 2876 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; 2877 } 2878 animateCollapsePanels(flags); 2879 } 2880 } 2881 else if (Intent.ACTION_SCREEN_OFF.equals(action)) { 2882 mScreenOn = false; 2883 notifyNavigationBarScreenOn(false); 2884 notifyHeadsUpScreenOff(); 2885 finishBarAnimations(); 2886 resetUserExpandedStates(); 2887 } 2888 else if (Intent.ACTION_SCREEN_ON.equals(action)) { 2889 mScreenOn = true; 2890 notifyNavigationBarScreenOn(true); 2891 } 2892 } 2893 }; 2894 2895 private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { 2896 public void onReceive(Context context, Intent intent) { 2897 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 2898 String action = intent.getAction(); 2899 if (ACTION_DEMO.equals(action)) { 2900 Bundle bundle = intent.getExtras(); 2901 if (bundle != null) { 2902 String command = bundle.getString("command", "").trim().toLowerCase(); 2903 if (command.length() > 0) { 2904 try { 2905 dispatchDemoCommand(command, bundle); 2906 } catch (Throwable t) { 2907 Log.w(TAG, "Error running demo command, intent=" + intent, t); 2908 } 2909 } 2910 } 2911 } else if (ACTION_FAKE_ARTWORK.equals(action)) { 2912 if (DEBUG_MEDIA_FAKE_ARTWORK) { 2913 updateMediaMetaData(true); 2914 } 2915 } 2916 } 2917 }; 2918 resetUserExpandedStates()2919 private void resetUserExpandedStates() { 2920 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 2921 final int notificationCount = activeNotifications.size(); 2922 for (int i = 0; i < notificationCount; i++) { 2923 NotificationData.Entry entry = activeNotifications.get(i); 2924 if (entry.row != null) { 2925 entry.row.resetUserExpansion(); 2926 } 2927 } 2928 } 2929 2930 @Override dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone)2931 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { 2932 dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); 2933 } 2934 dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone)2935 private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, 2936 boolean afterKeyguardGone) { 2937 if (mStatusBarKeyguardViewManager.isShowing()) { 2938 mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, 2939 afterKeyguardGone); 2940 } else { 2941 action.onDismiss(); 2942 } 2943 } 2944 2945 // SystemUIService notifies SystemBars of configuration changes, which then calls down here 2946 @Override onConfigurationChanged(Configuration newConfig)2947 protected void onConfigurationChanged(Configuration newConfig) { 2948 super.onConfigurationChanged(newConfig); // calls refreshLayout 2949 2950 if (DEBUG) { 2951 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); 2952 } 2953 updateDisplaySize(); // populates mDisplayMetrics 2954 2955 updateResources(); 2956 repositionNavigationBar(); 2957 updateRowStates(); 2958 mIconController.updateResources(); 2959 mScreenPinningRequest.onConfigurationChanged(); 2960 mNetworkController.onConfigurationChanged(); 2961 } 2962 2963 @Override userSwitched(int newUserId)2964 public void userSwitched(int newUserId) { 2965 super.userSwitched(newUserId); 2966 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId); 2967 animateCollapsePanels(); 2968 updatePublicMode(); 2969 updateNotifications(); 2970 resetUserSetupObserver(); 2971 setControllerUsers(); 2972 mAssistManager.onUserSwitched(newUserId); 2973 } 2974 setControllerUsers()2975 private void setControllerUsers() { 2976 if (mZenModeController != null) { 2977 mZenModeController.setUserId(mCurrentUserId); 2978 } 2979 if (mSecurityController != null) { 2980 mSecurityController.onUserSwitched(mCurrentUserId); 2981 } 2982 } 2983 resetUserSetupObserver()2984 private void resetUserSetupObserver() { 2985 mContext.getContentResolver().unregisterContentObserver(mUserSetupObserver); 2986 mUserSetupObserver.onChange(false); 2987 mContext.getContentResolver().registerContentObserver( 2988 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true, 2989 mUserSetupObserver, mCurrentUserId); 2990 } 2991 2992 /** 2993 * Reload some of our resources when the configuration changes. 2994 * 2995 * We don't reload everything when the configuration changes -- we probably 2996 * should, but getting that smooth is tough. Someday we'll fix that. In the 2997 * meantime, just update the things that we know change. 2998 */ updateResources()2999 void updateResources() { 3000 // Update the quick setting tiles 3001 if (mQSPanel != null) { 3002 mQSPanel.updateResources(); 3003 } 3004 3005 loadDimens(); 3006 3007 if (mNotificationPanel != null) { 3008 mNotificationPanel.updateResources(); 3009 } 3010 if (mBrightnessMirrorController != null) { 3011 mBrightnessMirrorController.updateResources(); 3012 } 3013 } 3014 loadDimens()3015 protected void loadDimens() { 3016 final Resources res = mContext.getResources(); 3017 3018 mNaturalBarHeight = res.getDimensionPixelSize( 3019 com.android.internal.R.dimen.status_bar_height); 3020 3021 mRowMinHeight = res.getDimensionPixelSize(R.dimen.notification_min_height); 3022 mRowMaxHeight = res.getDimensionPixelSize(R.dimen.notification_max_height); 3023 3024 mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count); 3025 3026 if (DEBUG) Log.v(TAG, "updateResources"); 3027 } 3028 3029 // Visibility reporting 3030 3031 @Override handleVisibleToUserChanged(boolean visibleToUser)3032 protected void handleVisibleToUserChanged(boolean visibleToUser) { 3033 if (visibleToUser) { 3034 super.handleVisibleToUserChanged(visibleToUser); 3035 startNotificationLogging(); 3036 } else { 3037 stopNotificationLogging(); 3038 super.handleVisibleToUserChanged(visibleToUser); 3039 } 3040 } 3041 stopNotificationLogging()3042 private void stopNotificationLogging() { 3043 // Report all notifications as invisible and turn down the 3044 // reporter. 3045 if (!mCurrentlyVisibleNotifications.isEmpty()) { 3046 logNotificationVisibilityChanges(Collections.<NotificationVisibility>emptyList(), 3047 mCurrentlyVisibleNotifications); 3048 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications); 3049 } 3050 mHandler.removeCallbacks(mVisibilityReporter); 3051 mStackScroller.setChildLocationsChangedListener(null); 3052 } 3053 startNotificationLogging()3054 private void startNotificationLogging() { 3055 mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener); 3056 // Some transitions like mVisibleToUser=false -> mVisibleToUser=true don't 3057 // cause the scroller to emit child location events. Hence generate 3058 // one ourselves to guarantee that we're reporting visible 3059 // notifications. 3060 // (Note that in cases where the scroller does emit events, this 3061 // additional event doesn't break anything.) 3062 mNotificationLocationsChangedListener.onChildLocationsChanged(mStackScroller); 3063 } 3064 logNotificationVisibilityChanges( Collection<NotificationVisibility> newlyVisible, Collection<NotificationVisibility> noLongerVisible)3065 private void logNotificationVisibilityChanges( 3066 Collection<NotificationVisibility> newlyVisible, 3067 Collection<NotificationVisibility> noLongerVisible) { 3068 if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) { 3069 return; 3070 } 3071 NotificationVisibility[] newlyVisibleAr = 3072 newlyVisible.toArray(new NotificationVisibility[newlyVisible.size()]); 3073 NotificationVisibility[] noLongerVisibleAr = 3074 noLongerVisible.toArray(new NotificationVisibility[noLongerVisible.size()]); 3075 try { 3076 mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr); 3077 } catch (RemoteException e) { 3078 // Ignore. 3079 } 3080 3081 final int N = newlyVisible.size(); 3082 if (N > 0) { 3083 String[] newlyVisibleKeyAr = new String[N]; 3084 for (int i = 0; i < N; i++) { 3085 newlyVisibleKeyAr[i] = newlyVisibleAr[i].key; 3086 } 3087 3088 setNotificationsShown(newlyVisibleKeyAr); 3089 } 3090 } 3091 3092 // State logging 3093 logStateToEventlog()3094 private void logStateToEventlog() { 3095 boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); 3096 boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); 3097 boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); 3098 boolean isSecure = mUnlockMethodCache.isMethodSecure(); 3099 boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer(); 3100 int stateFingerprint = getLoggingFingerprint(mState, 3101 isShowing, 3102 isOccluded, 3103 isBouncerShowing, 3104 isSecure, 3105 canSkipBouncer); 3106 if (stateFingerprint != mLastLoggedStateFingerprint) { 3107 EventLogTags.writeSysuiStatusBarState(mState, 3108 isShowing ? 1 : 0, 3109 isOccluded ? 1 : 0, 3110 isBouncerShowing ? 1 : 0, 3111 isSecure ? 1 : 0, 3112 canSkipBouncer ? 1 : 0); 3113 mLastLoggedStateFingerprint = stateFingerprint; 3114 } 3115 } 3116 3117 /** 3118 * Returns a fingerprint of fields logged to eventlog 3119 */ getLoggingFingerprint(int statusBarState, boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing, boolean secure, boolean currentlyInsecure)3120 private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, 3121 boolean keyguardOccluded, boolean bouncerShowing, boolean secure, 3122 boolean currentlyInsecure) { 3123 // Reserve 8 bits for statusBarState. We'll never go higher than 3124 // that, right? Riiiight. 3125 return (statusBarState & 0xFF) 3126 | ((keyguardShowing ? 1 : 0) << 8) 3127 | ((keyguardOccluded ? 1 : 0) << 9) 3128 | ((bouncerShowing ? 1 : 0) << 10) 3129 | ((secure ? 1 : 0) << 11) 3130 | ((currentlyInsecure ? 1 : 0) << 12); 3131 } 3132 3133 // 3134 // tracing 3135 // 3136 postStartTracing()3137 void postStartTracing() { 3138 mHandler.postDelayed(mStartTracing, 3000); 3139 } 3140 vibrate()3141 void vibrate() { 3142 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService( 3143 Context.VIBRATOR_SERVICE); 3144 vib.vibrate(250, VIBRATION_ATTRIBUTES); 3145 } 3146 3147 Runnable mStartTracing = new Runnable() { 3148 public void run() { 3149 vibrate(); 3150 SystemClock.sleep(250); 3151 Log.d(TAG, "startTracing"); 3152 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace"); 3153 mHandler.postDelayed(mStopTracing, 10000); 3154 } 3155 }; 3156 3157 Runnable mStopTracing = new Runnable() { 3158 public void run() { 3159 android.os.Debug.stopMethodTracing(); 3160 Log.d(TAG, "stopTracing"); 3161 vibrate(); 3162 } 3163 }; 3164 3165 @Override shouldDisableNavbarGestures()3166 public boolean shouldDisableNavbarGestures() { 3167 return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0; 3168 } 3169 postStartActivityDismissingKeyguard(final Intent intent, int delay)3170 public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { 3171 mHandler.postDelayed(new Runnable() { 3172 @Override 3173 public void run() { 3174 handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/); 3175 } 3176 }, delay); 3177 } 3178 handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned)3179 private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { 3180 startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */); 3181 } 3182 3183 private static class FastColorDrawable extends Drawable { 3184 private final int mColor; 3185 FastColorDrawable(int color)3186 public FastColorDrawable(int color) { 3187 mColor = 0xff000000 | color; 3188 } 3189 3190 @Override draw(Canvas canvas)3191 public void draw(Canvas canvas) { 3192 canvas.drawColor(mColor, PorterDuff.Mode.SRC); 3193 } 3194 3195 @Override setAlpha(int alpha)3196 public void setAlpha(int alpha) { 3197 } 3198 3199 @Override setColorFilter(ColorFilter colorFilter)3200 public void setColorFilter(ColorFilter colorFilter) { 3201 } 3202 3203 @Override getOpacity()3204 public int getOpacity() { 3205 return PixelFormat.OPAQUE; 3206 } 3207 3208 @Override setBounds(int left, int top, int right, int bottom)3209 public void setBounds(int left, int top, int right, int bottom) { 3210 } 3211 3212 @Override setBounds(Rect bounds)3213 public void setBounds(Rect bounds) { 3214 } 3215 } 3216 3217 @Override destroy()3218 public void destroy() { 3219 super.destroy(); 3220 if (mStatusBarWindow != null) { 3221 mWindowManager.removeViewImmediate(mStatusBarWindow); 3222 mStatusBarWindow = null; 3223 } 3224 if (mNavigationBarView != null) { 3225 mWindowManager.removeViewImmediate(mNavigationBarView); 3226 mNavigationBarView = null; 3227 } 3228 if (mHandlerThread != null) { 3229 mHandlerThread.quitSafely(); 3230 mHandlerThread = null; 3231 } 3232 mContext.unregisterReceiver(mBroadcastReceiver); 3233 mContext.unregisterReceiver(mDemoReceiver); 3234 mAssistManager.destroy(); 3235 3236 final SignalClusterView signalCluster = 3237 (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); 3238 final SignalClusterView signalClusterKeyguard = 3239 (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster); 3240 final SignalClusterView signalClusterQs = 3241 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster); 3242 mNetworkController.removeSignalCallback(signalCluster); 3243 mNetworkController.removeSignalCallback(signalClusterKeyguard); 3244 mNetworkController.removeSignalCallback(signalClusterQs); 3245 if (mQSPanel != null && mQSPanel.getHost() != null) { 3246 mQSPanel.getHost().destroy(); 3247 } 3248 } 3249 3250 private boolean mDemoModeAllowed; 3251 private boolean mDemoMode; 3252 3253 @Override dispatchDemoCommand(String command, Bundle args)3254 public void dispatchDemoCommand(String command, Bundle args) { 3255 if (!mDemoModeAllowed) { 3256 mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), 3257 DEMO_MODE_ALLOWED, 0) != 0; 3258 } 3259 if (!mDemoModeAllowed) return; 3260 if (command.equals(COMMAND_ENTER)) { 3261 mDemoMode = true; 3262 } else if (command.equals(COMMAND_EXIT)) { 3263 mDemoMode = false; 3264 checkBarModes(); 3265 } else if (!mDemoMode) { 3266 // automatically enter demo mode on first demo command 3267 dispatchDemoCommand(COMMAND_ENTER, new Bundle()); 3268 } 3269 boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); 3270 if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) { 3271 mVolumeComponent.dispatchDemoCommand(command, args); 3272 } 3273 if (modeChange || command.equals(COMMAND_CLOCK)) { 3274 dispatchDemoCommandToView(command, args, R.id.clock); 3275 } 3276 if (modeChange || command.equals(COMMAND_BATTERY)) { 3277 dispatchDemoCommandToView(command, args, R.id.battery); 3278 } 3279 if (modeChange || command.equals(COMMAND_STATUS)) { 3280 mIconController.dispatchDemoCommand(command, args); 3281 3282 } 3283 if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { 3284 mNetworkController.dispatchDemoCommand(command, args); 3285 } 3286 if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) { 3287 View notifications = mStatusBarView == null ? null 3288 : mStatusBarView.findViewById(R.id.notification_icon_area); 3289 if (notifications != null) { 3290 String visible = args.getString("visible"); 3291 int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; 3292 notifications.setVisibility(vis); 3293 } 3294 } 3295 if (command.equals(COMMAND_BARS)) { 3296 String mode = args.getString("mode"); 3297 int barMode = "opaque".equals(mode) ? MODE_OPAQUE : 3298 "translucent".equals(mode) ? MODE_TRANSLUCENT : 3299 "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT : 3300 "transparent".equals(mode) ? MODE_TRANSPARENT : 3301 "warning".equals(mode) ? MODE_WARNING : 3302 -1; 3303 if (barMode != -1) { 3304 boolean animate = true; 3305 if (mStatusBarView != null) { 3306 mStatusBarView.getBarTransitions().transitionTo(barMode, animate); 3307 } 3308 if (mNavigationBarView != null) { 3309 mNavigationBarView.getBarTransitions().transitionTo(barMode, animate); 3310 } 3311 } 3312 } 3313 } 3314 dispatchDemoCommandToView(String command, Bundle args, int id)3315 private void dispatchDemoCommandToView(String command, Bundle args, int id) { 3316 if (mStatusBarView == null) return; 3317 View v = mStatusBarView.findViewById(id); 3318 if (v instanceof DemoMode) { 3319 ((DemoMode)v).dispatchDemoCommand(command, args); 3320 } 3321 } 3322 3323 /** 3324 * @return The {@link StatusBarState} the status bar is in. 3325 */ getBarState()3326 public int getBarState() { 3327 return mState; 3328 } 3329 3330 @Override isPanelFullyCollapsed()3331 protected boolean isPanelFullyCollapsed() { 3332 return mNotificationPanel.isFullyCollapsed(); 3333 } 3334 showKeyguard()3335 public void showKeyguard() { 3336 if (mLaunchTransitionFadingAway) { 3337 mNotificationPanel.animate().cancel(); 3338 onLaunchTransitionFadingEnded(); 3339 } 3340 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3341 setBarState(StatusBarState.KEYGUARD); 3342 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 3343 if (!mScreenOnFromKeyguard) { 3344 3345 // If the screen is off already, we need to disable touch events because these might 3346 // collapse the panel after we expanded it, and thus we would end up with a blank 3347 // Keyguard. 3348 mNotificationPanel.setTouchDisabled(true); 3349 } 3350 instantExpandNotificationsPanel(); 3351 mLeaveOpenOnKeyguardHide = false; 3352 if (mDraggedDownRow != null) { 3353 mDraggedDownRow.setUserLocked(false); 3354 mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */); 3355 mDraggedDownRow = null; 3356 } 3357 mAssistManager.onLockscreenShown(); 3358 } 3359 onLaunchTransitionFadingEnded()3360 private void onLaunchTransitionFadingEnded() { 3361 mNotificationPanel.setAlpha(1.0f); 3362 runLaunchTransitionEndRunnable(); 3363 mLaunchTransitionFadingAway = false; 3364 mScrimController.forceHideScrims(false /* hide */); 3365 updateMediaMetaData(true /* metaDataChanged */); 3366 } 3367 isCollapsing()3368 public boolean isCollapsing() { 3369 return mNotificationPanel.isCollapsing(); 3370 } 3371 addPostCollapseAction(Runnable r)3372 public void addPostCollapseAction(Runnable r) { 3373 mPostCollapseRunnables.add(r); 3374 } 3375 isInLaunchTransition()3376 public boolean isInLaunchTransition() { 3377 return mNotificationPanel.isLaunchTransitionRunning() 3378 || mNotificationPanel.isLaunchTransitionFinished(); 3379 } 3380 3381 /** 3382 * Fades the content of the keyguard away after the launch transition is done. 3383 * 3384 * @param beforeFading the runnable to be run when the circle is fully expanded and the fading 3385 * starts 3386 * @param endRunnable the runnable to be run when the transition is done 3387 */ fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, Runnable endRunnable)3388 public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, 3389 Runnable endRunnable) { 3390 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3391 mLaunchTransitionEndRunnable = endRunnable; 3392 Runnable hideRunnable = new Runnable() { 3393 @Override 3394 public void run() { 3395 mLaunchTransitionFadingAway = true; 3396 if (beforeFading != null) { 3397 beforeFading.run(); 3398 } 3399 mScrimController.forceHideScrims(true /* hide */); 3400 updateMediaMetaData(false); 3401 mNotificationPanel.setAlpha(1); 3402 mNotificationPanel.animate() 3403 .alpha(0) 3404 .setStartDelay(FADE_KEYGUARD_START_DELAY) 3405 .setDuration(FADE_KEYGUARD_DURATION) 3406 .withLayer() 3407 .withEndAction(new Runnable() { 3408 @Override 3409 public void run() { 3410 onLaunchTransitionFadingEnded(); 3411 } 3412 }); 3413 mIconController.appTransitionStarting(SystemClock.uptimeMillis(), 3414 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION); 3415 } 3416 }; 3417 if (mNotificationPanel.isLaunchTransitionRunning()) { 3418 mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable); 3419 } else { 3420 hideRunnable.run(); 3421 } 3422 } 3423 3424 /** 3425 * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that 3426 * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen 3427 * because the launched app crashed or something else went wrong. 3428 */ startLaunchTransitionTimeout()3429 public void startLaunchTransitionTimeout() { 3430 mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT, 3431 LAUNCH_TRANSITION_TIMEOUT_MS); 3432 } 3433 onLaunchTransitionTimeout()3434 private void onLaunchTransitionTimeout() { 3435 Log.w(TAG, "Launch transition: Timeout!"); 3436 mNotificationPanel.resetViews(); 3437 } 3438 runLaunchTransitionEndRunnable()3439 private void runLaunchTransitionEndRunnable() { 3440 if (mLaunchTransitionEndRunnable != null) { 3441 Runnable r = mLaunchTransitionEndRunnable; 3442 3443 // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, 3444 // which would lead to infinite recursion. Protect against it. 3445 mLaunchTransitionEndRunnable = null; 3446 r.run(); 3447 } 3448 } 3449 3450 /** 3451 * @return true if we would like to stay in the shade, false if it should go away entirely 3452 */ hideKeyguard()3453 public boolean hideKeyguard() { 3454 boolean staying = mLeaveOpenOnKeyguardHide; 3455 setBarState(StatusBarState.SHADE); 3456 if (mLeaveOpenOnKeyguardHide) { 3457 mLeaveOpenOnKeyguardHide = false; 3458 mNotificationPanel.animateToFullShade(calculateGoingToFullShadeDelay()); 3459 if (mDraggedDownRow != null) { 3460 mDraggedDownRow.setUserLocked(false); 3461 mDraggedDownRow = null; 3462 } 3463 } else { 3464 instantCollapseNotificationPanel(); 3465 } 3466 updateKeyguardState(staying, false /* fromShadeLocked */); 3467 3468 // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile 3469 // visibilities so next time we open the panel we know the correct height already. 3470 if (mQSPanel != null) { 3471 mQSPanel.refreshAllTiles(); 3472 } 3473 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3474 return staying; 3475 } 3476 calculateGoingToFullShadeDelay()3477 public long calculateGoingToFullShadeDelay() { 3478 return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; 3479 } 3480 3481 /** 3482 * Notifies the status bar that Keyguard is going away very soon. 3483 */ keyguardGoingAway()3484 public void keyguardGoingAway() { 3485 3486 // Treat Keyguard exit animation as an app transition to achieve nice transition for status 3487 // bar. 3488 mIconController.appTransitionPending(); 3489 } 3490 3491 /** 3492 * Notifies the status bar the Keyguard is fading away with the specified timings. 3493 * 3494 * @param startTime the start time of the animations in uptime millis 3495 * @param delay the precalculated animation delay in miliseconds 3496 * @param fadeoutDuration the duration of the exit animation, in milliseconds 3497 */ setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration)3498 public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { 3499 mKeyguardFadingAway = true; 3500 mKeyguardFadingAwayDelay = delay; 3501 mKeyguardFadingAwayDuration = fadeoutDuration; 3502 mWaitingForKeyguardExit = false; 3503 mIconController.appTransitionStarting( 3504 startTime + fadeoutDuration 3505 - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION, 3506 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION); 3507 disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */); 3508 } 3509 isKeyguardFadingAway()3510 public boolean isKeyguardFadingAway() { 3511 return mKeyguardFadingAway; 3512 } 3513 3514 /** 3515 * Notifies that the Keyguard fading away animation is done. 3516 */ finishKeyguardFadingAway()3517 public void finishKeyguardFadingAway() { 3518 mKeyguardFadingAway = false; 3519 } 3520 stopWaitingForKeyguardExit()3521 public void stopWaitingForKeyguardExit() { 3522 mWaitingForKeyguardExit = false; 3523 } 3524 updatePublicMode()3525 private void updatePublicMode() { 3526 setLockscreenPublicMode( 3527 mStatusBarKeyguardViewManager.isShowing() && mStatusBarKeyguardViewManager 3528 .isSecure(mCurrentUserId)); 3529 } 3530 updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked)3531 private void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) { 3532 if (mState == StatusBarState.KEYGUARD) { 3533 mKeyguardIndicationController.setVisible(true); 3534 mNotificationPanel.resetViews(); 3535 mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked); 3536 mStatusBarView.removePendingHideExpandedRunnables(); 3537 } else { 3538 mKeyguardIndicationController.setVisible(false); 3539 mKeyguardUserSwitcher.setKeyguard(false, 3540 goingToFullShade || mState == StatusBarState.SHADE_LOCKED || fromShadeLocked); 3541 } 3542 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 3543 mScrimController.setKeyguardShowing(true); 3544 mIconPolicy.setKeyguardShowing(true); 3545 } else { 3546 mScrimController.setKeyguardShowing(false); 3547 mIconPolicy.setKeyguardShowing(false); 3548 } 3549 mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade); 3550 updateDozingState(); 3551 updatePublicMode(); 3552 updateStackScrollerState(goingToFullShade); 3553 updateNotifications(); 3554 checkBarModes(); 3555 updateMediaMetaData(false); 3556 mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), 3557 mStatusBarKeyguardViewManager.isSecure()); 3558 } 3559 updateDozingState()3560 private void updateDozingState() { 3561 boolean animate = !mDozing && mDozeScrimController.isPulsing(); 3562 mNotificationPanel.setDozing(mDozing, animate); 3563 mStackScroller.setDark(mDozing, animate, mScreenOnTouchLocation); 3564 mScrimController.setDozing(mDozing); 3565 mDozeScrimController.setDozing(mDozing, animate); 3566 } 3567 updateStackScrollerState(boolean goingToFullShade)3568 public void updateStackScrollerState(boolean goingToFullShade) { 3569 if (mStackScroller == null) return; 3570 boolean onKeyguard = mState == StatusBarState.KEYGUARD; 3571 mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade); 3572 mStackScroller.setDimmed(onKeyguard, false /* animate */); 3573 mStackScroller.setExpandingEnabled(!onKeyguard); 3574 ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); 3575 mStackScroller.setActivatedChild(null); 3576 if (activatedChild != null) { 3577 activatedChild.makeInactive(false /* animate */); 3578 } 3579 } 3580 userActivity()3581 public void userActivity() { 3582 if (mState == StatusBarState.KEYGUARD) { 3583 mKeyguardViewMediatorCallback.userActivity(); 3584 } 3585 } 3586 interceptMediaKey(KeyEvent event)3587 public boolean interceptMediaKey(KeyEvent event) { 3588 return mState == StatusBarState.KEYGUARD 3589 && mStatusBarKeyguardViewManager.interceptMediaKey(event); 3590 } 3591 onMenuPressed()3592 public boolean onMenuPressed() { 3593 return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed(); 3594 } 3595 onBackPressed()3596 public boolean onBackPressed() { 3597 if (mStatusBarKeyguardViewManager.onBackPressed()) { 3598 return true; 3599 } 3600 if (mNotificationPanel.isQsExpanded()) { 3601 if (mNotificationPanel.isQsDetailShowing()) { 3602 mNotificationPanel.closeQsDetail(); 3603 } else { 3604 mNotificationPanel.animateCloseQs(); 3605 } 3606 return true; 3607 } 3608 if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { 3609 animateCollapsePanels(); 3610 return true; 3611 } 3612 return false; 3613 } 3614 onSpacePressed()3615 public boolean onSpacePressed() { 3616 if (mScreenOn != null && mScreenOn 3617 && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { 3618 animateCollapsePanels( 3619 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); 3620 return true; 3621 } 3622 return false; 3623 } 3624 showBouncer()3625 private void showBouncer() { 3626 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 3627 mWaitingForKeyguardExit = mStatusBarKeyguardViewManager.isShowing(); 3628 mStatusBarKeyguardViewManager.dismiss(); 3629 } 3630 } 3631 instantExpandNotificationsPanel()3632 private void instantExpandNotificationsPanel() { 3633 3634 // Make our window larger and the panel expanded. 3635 makeExpandedVisible(true); 3636 mNotificationPanel.instantExpand(); 3637 } 3638 instantCollapseNotificationPanel()3639 private void instantCollapseNotificationPanel() { 3640 mNotificationPanel.instantCollapse(); 3641 } 3642 3643 @Override onActivated(ActivatableNotificationView view)3644 public void onActivated(ActivatableNotificationView view) { 3645 EventLogTags.writeSysuiLockscreenGesture( 3646 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE, 3647 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); 3648 mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); 3649 ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); 3650 if (previousView != null) { 3651 previousView.makeInactive(true /* animate */); 3652 } 3653 mStackScroller.setActivatedChild(view); 3654 } 3655 3656 /** 3657 * @param state The {@link StatusBarState} to set. 3658 */ setBarState(int state)3659 public void setBarState(int state) { 3660 // If we're visible and switched to SHADE_LOCKED (the user dragged 3661 // down on the lockscreen), clear notification LED, vibration, 3662 // ringing. 3663 // Other transitions are covered in handleVisibleToUserChanged(). 3664 if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED 3665 || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) { 3666 clearNotificationEffects(); 3667 } 3668 mState = state; 3669 mGroupManager.setStatusBarState(state); 3670 mStatusBarWindowManager.setStatusBarState(state); 3671 updateDozing(); 3672 } 3673 3674 @Override onActivationReset(ActivatableNotificationView view)3675 public void onActivationReset(ActivatableNotificationView view) { 3676 if (view == mStackScroller.getActivatedChild()) { 3677 mKeyguardIndicationController.hideTransientIndication(); 3678 mStackScroller.setActivatedChild(null); 3679 } 3680 } 3681 onTrackingStarted()3682 public void onTrackingStarted() { 3683 runPostCollapseRunnables(); 3684 } 3685 onClosingFinished()3686 public void onClosingFinished() { 3687 runPostCollapseRunnables(); 3688 } 3689 onUnlockHintStarted()3690 public void onUnlockHintStarted() { 3691 mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); 3692 } 3693 onHintFinished()3694 public void onHintFinished() { 3695 // Delay the reset a bit so the user can read the text. 3696 mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); 3697 } 3698 onCameraHintStarted()3699 public void onCameraHintStarted() { 3700 mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); 3701 } 3702 onVoiceAssistHintStarted()3703 public void onVoiceAssistHintStarted() { 3704 mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); 3705 } 3706 onPhoneHintStarted()3707 public void onPhoneHintStarted() { 3708 mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); 3709 } 3710 onTrackingStopped(boolean expand)3711 public void onTrackingStopped(boolean expand) { 3712 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 3713 if (!expand && !mUnlockMethodCache.canSkipBouncer()) { 3714 showBouncer(); 3715 } 3716 } 3717 } 3718 3719 @Override getMaxKeyguardNotifications()3720 protected int getMaxKeyguardNotifications() { 3721 return mKeyguardMaxNotificationCount; 3722 } 3723 getNavigationBarView()3724 public NavigationBarView getNavigationBarView() { 3725 return mNavigationBarView; 3726 } 3727 3728 // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ 3729 3730 @Override onDraggedDown(View startingChild, int dragLengthY)3731 public boolean onDraggedDown(View startingChild, int dragLengthY) { 3732 if (hasActiveNotifications()) { 3733 EventLogTags.writeSysuiLockscreenGesture( 3734 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE, 3735 (int) (dragLengthY / mDisplayMetrics.density), 3736 0 /* velocityDp - N/A */); 3737 3738 // We have notifications, go to locked shade. 3739 goToLockedShade(startingChild); 3740 return true; 3741 } else { 3742 3743 // No notifications - abort gesture. 3744 return false; 3745 } 3746 } 3747 3748 @Override onDragDownReset()3749 public void onDragDownReset() { 3750 mStackScroller.setDimmed(true /* dimmed */, true /* animated */); 3751 } 3752 3753 @Override onThresholdReached()3754 public void onThresholdReached() { 3755 mStackScroller.setDimmed(false /* dimmed */, true /* animate */); 3756 } 3757 3758 @Override onTouchSlopExceeded()3759 public void onTouchSlopExceeded() { 3760 mStackScroller.removeLongPressCallback(); 3761 } 3762 3763 @Override setEmptyDragAmount(float amount)3764 public void setEmptyDragAmount(float amount) { 3765 mNotificationPanel.setEmptyDragAmount(amount); 3766 } 3767 3768 /** 3769 * If secure with redaction: Show bouncer, go to unlocked shade. 3770 * 3771 * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p> 3772 * 3773 * @param expandView The view to expand after going to the shade. 3774 */ goToLockedShade(View expandView)3775 public void goToLockedShade(View expandView) { 3776 ExpandableNotificationRow row = null; 3777 if (expandView instanceof ExpandableNotificationRow) { 3778 row = (ExpandableNotificationRow) expandView; 3779 row.setUserExpanded(true); 3780 } 3781 boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId) 3782 || !mShowLockscreenNotifications; 3783 if (isLockscreenPublicMode() && fullShadeNeedsBouncer) { 3784 mLeaveOpenOnKeyguardHide = true; 3785 showBouncer(); 3786 mDraggedDownRow = row; 3787 } else { 3788 mNotificationPanel.animateToFullShade(0 /* delay */); 3789 setBarState(StatusBarState.SHADE_LOCKED); 3790 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 3791 if (row != null) { 3792 row.setUserLocked(false); 3793 } 3794 } 3795 } 3796 3797 /** 3798 * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}. 3799 */ goToKeyguard()3800 public void goToKeyguard() { 3801 if (mState == StatusBarState.SHADE_LOCKED) { 3802 mStackScroller.onGoToKeyguard(); 3803 setBarState(StatusBarState.KEYGUARD); 3804 updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/); 3805 } 3806 } 3807 getKeyguardFadingAwayDelay()3808 public long getKeyguardFadingAwayDelay() { 3809 return mKeyguardFadingAwayDelay; 3810 } 3811 getKeyguardFadingAwayDuration()3812 public long getKeyguardFadingAwayDuration() { 3813 return mKeyguardFadingAwayDuration; 3814 } 3815 3816 @Override setBouncerShowing(boolean bouncerShowing)3817 public void setBouncerShowing(boolean bouncerShowing) { 3818 super.setBouncerShowing(bouncerShowing); 3819 mStatusBarView.setBouncerShowing(bouncerShowing); 3820 disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */); 3821 } 3822 onScreenTurnedOff()3823 public void onScreenTurnedOff() { 3824 mScreenOnFromKeyguard = false; 3825 mScreenOnComingFromTouch = false; 3826 mScreenOnTouchLocation = null; 3827 mStackScroller.setAnimationsEnabled(false); 3828 updateVisibleToUser(); 3829 } 3830 onScreenTurnedOn()3831 public void onScreenTurnedOn() { 3832 mScreenOnFromKeyguard = true; 3833 mStackScroller.setAnimationsEnabled(true); 3834 mNotificationPanel.setTouchDisabled(false); 3835 updateVisibleToUser(); 3836 } 3837 onScreenTurningOn()3838 public void onScreenTurningOn() { 3839 mNotificationPanel.onScreenTurningOn(); 3840 } 3841 3842 /** 3843 * This handles long-press of both back and recents. They are 3844 * handled together to capture them both being long-pressed 3845 * at the same time to exit screen pinning (lock task). 3846 * 3847 * When accessibility mode is on, only a long-press from recents 3848 * is required to exit. 3849 * 3850 * In all other circumstances we try to pass through long-press events 3851 * for Back, so that apps can still use it. Which can be from two things. 3852 * 1) Not currently in screen pinning (lock task). 3853 * 2) Back is long-pressed without recents. 3854 */ handleLongPressBackRecents(View v)3855 private void handleLongPressBackRecents(View v) { 3856 try { 3857 boolean sendBackLongPress = false; 3858 IActivityManager activityManager = ActivityManagerNative.getDefault(); 3859 boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled(); 3860 if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) { 3861 long time = System.currentTimeMillis(); 3862 // If we recently long-pressed the other button then they were 3863 // long-pressed 'together' 3864 if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) { 3865 activityManager.stopLockTaskModeOnCurrent(); 3866 // When exiting refresh disabled flags. 3867 mNavigationBarView.setDisabledFlags(mDisabled1, true); 3868 } else if ((v.getId() == R.id.back) 3869 && !mNavigationBarView.getRecentsButton().isPressed()) { 3870 // If we aren't pressing recents right now then they presses 3871 // won't be together, so send the standard long-press action. 3872 sendBackLongPress = true; 3873 } 3874 mLastLockToAppLongPress = time; 3875 } else { 3876 // If this is back still need to handle sending the long-press event. 3877 if (v.getId() == R.id.back) { 3878 sendBackLongPress = true; 3879 } else if (isAccessiblityEnabled && activityManager.isInLockTaskMode()) { 3880 // When in accessibility mode a long press that is recents (not back) 3881 // should stop lock task. 3882 activityManager.stopLockTaskModeOnCurrent(); 3883 // When exiting refresh disabled flags. 3884 mNavigationBarView.setDisabledFlags(mDisabled1, true); 3885 } 3886 } 3887 if (sendBackLongPress) { 3888 KeyButtonView keyButtonView = (KeyButtonView) v; 3889 keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS); 3890 keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 3891 } 3892 } catch (RemoteException e) { 3893 Log.d(TAG, "Unable to reach activity manager", e); 3894 } 3895 } 3896 3897 // Recents 3898 3899 @Override showRecents(boolean triggeredFromAltTab)3900 protected void showRecents(boolean triggeredFromAltTab) { 3901 // Set the recents visibility flag 3902 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE; 3903 notifyUiVisibilityChanged(mSystemUiVisibility); 3904 super.showRecents(triggeredFromAltTab); 3905 } 3906 3907 @Override hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey)3908 protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 3909 // Unset the recents visibility flag 3910 mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE; 3911 notifyUiVisibilityChanged(mSystemUiVisibility); 3912 super.hideRecents(triggeredFromAltTab, triggeredFromHomeKey); 3913 } 3914 3915 @Override toggleRecents()3916 protected void toggleRecents() { 3917 // Toggle the recents visibility flag 3918 mSystemUiVisibility ^= View.RECENT_APPS_VISIBLE; 3919 notifyUiVisibilityChanged(mSystemUiVisibility); 3920 super.toggleRecents(); 3921 } 3922 3923 @Override onVisibilityChanged(boolean visible)3924 public void onVisibilityChanged(boolean visible) { 3925 // Update the recents visibility flag 3926 if (visible) { 3927 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE; 3928 } else { 3929 mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE; 3930 } 3931 notifyUiVisibilityChanged(mSystemUiVisibility); 3932 } 3933 3934 @Override showScreenPinningRequest()3935 public void showScreenPinningRequest() { 3936 if (mKeyguardMonitor.isShowing()) { 3937 // Don't allow apps to trigger this from keyguard. 3938 return; 3939 } 3940 // Show screen pinning request, since this comes from an app, show 'no thanks', button. 3941 showScreenPinningRequest(true); 3942 } 3943 showScreenPinningRequest(boolean allowCancel)3944 public void showScreenPinningRequest(boolean allowCancel) { 3945 mScreenPinningRequest.showPrompt(allowCancel); 3946 } 3947 hasActiveNotifications()3948 public boolean hasActiveNotifications() { 3949 return !mNotificationData.getActiveNotifications().isEmpty(); 3950 } 3951 wakeUpIfDozing(long time, MotionEvent event)3952 public void wakeUpIfDozing(long time, MotionEvent event) { 3953 if (mDozing && mDozeScrimController.isPulsing()) { 3954 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 3955 pm.wakeUp(time, "com.android.systemui:NODOZE"); 3956 mScreenOnComingFromTouch = true; 3957 mScreenOnTouchLocation = new PointF(event.getX(), event.getY()); 3958 mNotificationPanel.setTouchDisabled(false); 3959 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); 3960 } 3961 } 3962 3963 @Override appTransitionPending()3964 public void appTransitionPending() { 3965 3966 // Use own timings when Keyguard is going away, see keyguardGoingAway and 3967 // setKeyguardFadingAway 3968 if (!mKeyguardFadingAway) { 3969 mIconController.appTransitionPending(); 3970 } 3971 } 3972 3973 @Override appTransitionCancelled()3974 public void appTransitionCancelled() { 3975 mIconController.appTransitionCancelled(); 3976 } 3977 3978 @Override appTransitionStarting(long startTime, long duration)3979 public void appTransitionStarting(long startTime, long duration) { 3980 3981 // Use own timings when Keyguard is going away, see keyguardGoingAway and 3982 // setKeyguardFadingAway 3983 if (!mKeyguardFadingAway) { 3984 mIconController.appTransitionStarting(startTime, duration); 3985 } 3986 if (mIconPolicy != null) { 3987 mIconPolicy.appTransitionStarting(startTime, duration); 3988 } 3989 } 3990 updateDozing()3991 private void updateDozing() { 3992 mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD; 3993 updateDozingState(); 3994 } 3995 3996 private final class ShadeUpdates { 3997 private final ArraySet<String> mVisibleNotifications = new ArraySet<String>(); 3998 private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>(); 3999 check()4000 public void check() { 4001 mNewVisibleNotifications.clear(); 4002 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 4003 for (int i = 0; i < activeNotifications.size(); i++) { 4004 final Entry entry = activeNotifications.get(i); 4005 final boolean visible = entry.row != null 4006 && entry.row.getVisibility() == View.VISIBLE; 4007 if (visible) { 4008 mNewVisibleNotifications.add(entry.key + entry.notification.getPostTime()); 4009 } 4010 } 4011 final boolean updates = !mVisibleNotifications.containsAll(mNewVisibleNotifications); 4012 mVisibleNotifications.clear(); 4013 mVisibleNotifications.addAll(mNewVisibleNotifications); 4014 4015 // We have new notifications 4016 if (updates && mDozeServiceHost != null) { 4017 mDozeServiceHost.fireNewNotifications(); 4018 } 4019 } 4020 } 4021 4022 private final class DozeServiceHost implements DozeHost { 4023 // Amount of time to allow to update the time shown on the screen before releasing 4024 // the wakelock. This timeout is design to compensate for the fact that we don't 4025 // currently have a way to know when time display contents have actually been 4026 // refreshed once we've finished rendering a new frame. 4027 private static final long PROCESSING_TIME = 500; 4028 4029 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 4030 private final H mHandler = new H(); 4031 4032 // Keeps the last reported state by fireNotificationLight. 4033 private boolean mNotificationLightOn; 4034 4035 @Override toString()4036 public String toString() { 4037 return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; 4038 } 4039 firePowerSaveChanged(boolean active)4040 public void firePowerSaveChanged(boolean active) { 4041 for (Callback callback : mCallbacks) { 4042 callback.onPowerSaveChanged(active); 4043 } 4044 } 4045 fireBuzzBeepBlinked()4046 public void fireBuzzBeepBlinked() { 4047 for (Callback callback : mCallbacks) { 4048 callback.onBuzzBeepBlinked(); 4049 } 4050 } 4051 fireNotificationLight(boolean on)4052 public void fireNotificationLight(boolean on) { 4053 mNotificationLightOn = on; 4054 for (Callback callback : mCallbacks) { 4055 callback.onNotificationLight(on); 4056 } 4057 } 4058 fireNewNotifications()4059 public void fireNewNotifications() { 4060 for (Callback callback : mCallbacks) { 4061 callback.onNewNotifications(); 4062 } 4063 } 4064 4065 @Override addCallback(@onNull Callback callback)4066 public void addCallback(@NonNull Callback callback) { 4067 mCallbacks.add(callback); 4068 } 4069 4070 @Override removeCallback(@onNull Callback callback)4071 public void removeCallback(@NonNull Callback callback) { 4072 mCallbacks.remove(callback); 4073 } 4074 4075 @Override startDozing(@onNull Runnable ready)4076 public void startDozing(@NonNull Runnable ready) { 4077 mHandler.obtainMessage(H.MSG_START_DOZING, ready).sendToTarget(); 4078 } 4079 4080 @Override pulseWhileDozing(@onNull PulseCallback callback, int reason)4081 public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { 4082 mHandler.obtainMessage(H.MSG_PULSE_WHILE_DOZING, reason, 0, callback).sendToTarget(); 4083 } 4084 4085 @Override stopDozing()4086 public void stopDozing() { 4087 mHandler.obtainMessage(H.MSG_STOP_DOZING).sendToTarget(); 4088 } 4089 4090 @Override isPowerSaveActive()4091 public boolean isPowerSaveActive() { 4092 return mBatteryController != null && mBatteryController.isPowerSave(); 4093 } 4094 4095 @Override isNotificationLightOn()4096 public boolean isNotificationLightOn() { 4097 return mNotificationLightOn; 4098 } 4099 handleStartDozing(@onNull Runnable ready)4100 private void handleStartDozing(@NonNull Runnable ready) { 4101 if (!mDozingRequested) { 4102 mDozingRequested = true; 4103 DozeLog.traceDozing(mContext, mDozing); 4104 updateDozing(); 4105 } 4106 ready.run(); 4107 } 4108 handlePulseWhileDozing(@onNull PulseCallback callback, int reason)4109 private void handlePulseWhileDozing(@NonNull PulseCallback callback, int reason) { 4110 mDozeScrimController.pulse(callback, reason); 4111 } 4112 handleStopDozing()4113 private void handleStopDozing() { 4114 if (mDozingRequested) { 4115 mDozingRequested = false; 4116 DozeLog.traceDozing(mContext, mDozing); 4117 updateDozing(); 4118 } 4119 } 4120 4121 private final class H extends Handler { 4122 private static final int MSG_START_DOZING = 1; 4123 private static final int MSG_PULSE_WHILE_DOZING = 2; 4124 private static final int MSG_STOP_DOZING = 3; 4125 4126 @Override handleMessage(Message msg)4127 public void handleMessage(Message msg) { 4128 switch (msg.what) { 4129 case MSG_START_DOZING: 4130 handleStartDozing((Runnable) msg.obj); 4131 break; 4132 case MSG_PULSE_WHILE_DOZING: 4133 handlePulseWhileDozing((PulseCallback) msg.obj, msg.arg1); 4134 break; 4135 case MSG_STOP_DOZING: 4136 handleStopDozing(); 4137 break; 4138 } 4139 } 4140 } 4141 } 4142 } 4143