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